Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
1918c7f5
Commit
1918c7f5
authored
Oct 05, 2012
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sparc64: switch to generic kernel_thread()
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
dff933da
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
42 additions
and
82 deletions
+42
-82
arch/sparc/Kconfig
arch/sparc/Kconfig
+1
-0
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/processor_64.h
+0
-2
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/ptrace.h
+3
-0
arch/sparc/kernel/process_64.c
arch/sparc/kernel/process_64.c
+30
-77
arch/sparc/kernel/syscalls.S
arch/sparc/kernel/syscalls.S
+8
-3
No files found.
arch/sparc/Kconfig
View file @
1918c7f5
...
...
@@ -74,6 +74,7 @@ config SPARC64
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select HAVE_C_RECORDMCOUNT
select NO_BOOTMEM
select GENERIC_KERNEL_THREAD
config ARCH_DEFCONFIG
string
...
...
arch/sparc/include/asm/processor_64.h
View file @
1918c7f5
...
...
@@ -188,8 +188,6 @@ do { \
/* Free all resources held by a thread. */
#define release_thread(tsk) do { } while (0)
extern
pid_t
kernel_thread
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
unsigned
long
flags
);
extern
unsigned
long
get_wchan
(
struct
task_struct
*
task
);
#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
...
...
arch/sparc/include/asm/ptrace.h
View file @
1918c7f5
...
...
@@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
#define arch_ptrace_stop(exit_code, info) \
synchronize_user_stack()
#define current_pt_regs() \
((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
struct
global_reg_snapshot
{
unsigned
long
tstate
;
unsigned
long
tpc
;
...
...
arch/sparc/kernel/process_64.c
View file @
1918c7f5
...
...
@@ -538,64 +538,56 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
* Child --> %o0 == parents pid, %o1 == 1
*/
int
copy_thread
(
unsigned
long
clone_flags
,
unsigned
long
sp
,
unsigned
long
unused
,
unsigned
long
arg
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
{
struct
thread_info
*
t
=
task_thread_info
(
p
);
struct
sparc_stackf
*
parent_sf
;
unsigned
long
child_stack_sz
;
char
*
child_trap_frame
;
int
kernel_thread
;
kernel_thread
=
(
regs
->
tstate
&
TSTATE_PRIV
)
?
1
:
0
;
parent_sf
=
((
struct
sparc_stackf
*
)
regs
)
-
1
;
/* Calculate offset to stack_frame & pt_regs */
child_stack_sz
=
((
STACKFRAME_SZ
+
TRACEREG_SZ
)
+
(
kernel_thread
?
STACKFRAME_SZ
:
0
));
child_stack_sz
=
(
STACKFRAME_SZ
+
TRACEREG_SZ
);
child_trap_frame
=
(
task_stack_page
(
p
)
+
(
THREAD_SIZE
-
child_stack_sz
));
memcpy
(
child_trap_frame
,
parent_sf
,
child_stack_sz
);
__thread_flag_byte_ptr
(
t
)[
TI_FLAG_BYTE_CWP
]
=
(
regs
->
tstate
+
1
)
&
TSTATE_CWP
;
t
->
new_child
=
1
;
t
->
ksp
=
((
unsigned
long
)
child_trap_frame
)
-
STACK_BIAS
;
t
->
kregs
=
(
struct
pt_regs
*
)
(
child_trap_frame
+
sizeof
(
struct
sparc_stackf
));
t
->
fpsaved
[
0
]
=
0
;
if
(
kernel_thread
)
{
struct
sparc_stackf
*
child_sf
=
(
struct
sparc_stackf
*
)
(
child_trap_frame
+
(
STACKFRAME_SZ
+
TRACEREG_SZ
));
/* Zero terminate the stack backtrace. */
child_sf
->
fp
=
NULL
;
t
->
kregs
->
u_regs
[
UREG_FP
]
=
((
unsigned
long
)
child_sf
)
-
STACK_BIAS
;
if
(
unlikely
(
p
->
flags
&
PF_KTHREAD
))
{
memset
(
child_trap_frame
,
0
,
child_stack_sz
);
__thread_flag_byte_ptr
(
t
)[
TI_FLAG_BYTE_CWP
]
=
(
current_pt_regs
()
->
tstate
+
1
)
&
TSTATE_CWP
;
t
->
current_ds
=
ASI_P
;
t
->
kregs
->
u_regs
[
UREG_G6
]
=
(
unsigned
long
)
t
;
t
->
kregs
->
u_regs
[
UREG_G4
]
=
(
unsigned
long
)
t
->
task
;
}
else
{
if
(
t
->
flags
&
_TIF_32BIT
)
{
sp
&=
0x00000000ffffffffUL
;
regs
->
u_regs
[
UREG_FP
]
&=
0x00000000ffffffffUL
;
}
t
->
kregs
->
u_regs
[
UREG_FP
]
=
sp
;
t
->
current_ds
=
ASI_AIUS
;
if
(
sp
!=
regs
->
u_regs
[
UREG_FP
])
{
unsigned
long
csp
;
csp
=
clone_stackframe
(
sp
,
regs
->
u_regs
[
UREG_FP
]);
if
(
!
csp
)
return
-
EFAULT
;
t
->
kregs
->
u_regs
[
UREG_FP
]
=
csp
;
}
if
(
t
->
utraps
)
t
->
utraps
[
0
]
++
;
t
->
kregs
->
u_regs
[
UREG_G1
]
=
sp
;
/* function */
t
->
kregs
->
u_regs
[
UREG_G2
]
=
arg
;
return
0
;
}
parent_sf
=
((
struct
sparc_stackf
*
)
regs
)
-
1
;
memcpy
(
child_trap_frame
,
parent_sf
,
child_stack_sz
);
if
(
t
->
flags
&
_TIF_32BIT
)
{
sp
&=
0x00000000ffffffffUL
;
regs
->
u_regs
[
UREG_FP
]
&=
0x00000000ffffffffUL
;
}
t
->
kregs
->
u_regs
[
UREG_FP
]
=
sp
;
__thread_flag_byte_ptr
(
t
)[
TI_FLAG_BYTE_CWP
]
=
(
regs
->
tstate
+
1
)
&
TSTATE_CWP
;
t
->
current_ds
=
ASI_AIUS
;
if
(
sp
!=
regs
->
u_regs
[
UREG_FP
])
{
unsigned
long
csp
;
csp
=
clone_stackframe
(
sp
,
regs
->
u_regs
[
UREG_FP
]);
if
(
!
csp
)
return
-
EFAULT
;
t
->
kregs
->
u_regs
[
UREG_FP
]
=
csp
;
}
if
(
t
->
utraps
)
t
->
utraps
[
0
]
++
;
/* Set the return value for the child. */
t
->
kregs
->
u_regs
[
UREG_I0
]
=
current
->
pid
;
t
->
kregs
->
u_regs
[
UREG_I1
]
=
1
;
...
...
@@ -609,45 +601,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
return
0
;
}
/*
* This is the mechanism for creating a new kernel thread.
*
* NOTE! Only a kernel-only process(ie the swapper or direct descendants
* who haven't done an "execve()") should use this: it will work within
* a system call from a "real" process, but the process memory space will
* not be freed until both the parent and the child have exited.
*/
pid_t
kernel_thread
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
unsigned
long
flags
)
{
long
retval
;
/* If the parent runs before fn(arg) is called by the child,
* the input registers of this function can be clobbered.
* So we stash 'fn' and 'arg' into global registers which
* will not be modified by the parent.
*/
__asm__
__volatile__
(
"mov %4, %%g2
\n\t
"
/* Save FN into global */
"mov %5, %%g3
\n\t
"
/* Save ARG into global */
"mov %1, %%g1
\n\t
"
/* Clone syscall nr. */
"mov %2, %%o0
\n\t
"
/* Clone flags. */
"mov 0, %%o1
\n\t
"
/* usp arg == 0 */
"t 0x6d
\n\t
"
/* Linux/Sparc clone(). */
"brz,a,pn %%o1, 1f
\n\t
"
/* Parent, just return. */
" mov %%o0, %0
\n\t
"
"jmpl %%g2, %%o7
\n\t
"
/* Call the function. */
" mov %%g3, %%o0
\n\t
"
/* Set arg in delay. */
"mov %3, %%g1
\n\t
"
"t 0x6d
\n\t
"
/* Linux/Sparc exit(). */
/* Notreached by child. */
"1:"
:
"=r"
(
retval
)
:
"i"
(
__NR_clone
),
"r"
(
flags
|
CLONE_VM
|
CLONE_UNTRACED
),
"i"
(
__NR_exit
),
"r"
(
fn
),
"r"
(
arg
)
:
"g1"
,
"g2"
,
"g3"
,
"o0"
,
"o1"
,
"memory"
,
"cc"
);
return
retval
;
}
EXPORT_SYMBOL
(
kernel_thread
);
typedef
struct
{
union
{
unsigned
int
pr_regs
[
32
];
...
...
arch/sparc/kernel/syscalls.S
View file @
1918c7f5
...
...
@@ -112,11 +112,16 @@ sys_clone:
ret_from_syscall
:
/
*
Clear
current_thread_info
()->
new_child
.
*/
stb
%
g0
,
[%
g6
+
TI_NEW_CHILD
]
ldx
[%
g6
+
TI_FLAGS
],
%
l0
call
schedule_tail
mov
%
g7
,
%
o0
ba
,
pt
%
xcc
,
ret_sys_call
ldx
[%
sp
+
PTREGS_OFF
+
PT_V9_I0
],
%
o0
ldx
[%
sp
+
PTREGS_OFF
+
PT_V9_I0
],
%
o0
brnz
,
a
,
pt
%
o0
,
ret_sys_call
ldx
[%
g6
+
TI_FLAGS
],
%
l0
ldx
[%
sp
+
PTREGS_OFF
+
PT_V9_G1
],
%
l0
call
%
l0
ldx
[%
sp
+
PTREGS_OFF
+
PT_V9_G2
],
%
o0
call
do_exit
!
will
not
return
mov
0
,%
o0
.
globl
sparc_exit
.
type
sparc_exit
,#
function
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment