Skip to content

Commit a4261d4

Browse files
author
Christian Brauner
committed
sparc: share process creation helpers between sparc and sparc64
As promised in the previous patch, this moves the process creation helpers into a common process.c file that is shared between sparc and sparc64. It allows us to get rid of quite a bit custom assembler and the to remove the separe 32bit specific sparc_do_fork() call. One thing to note, is that when clone() was called with a separate stack for the child the assembler would align it. But copy_thread() has always been doing that too so that line wasn't needed and can thus simply be removed. Signed-off-by: Christian Brauner <[email protected]> Acked-by: David S. Miller <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: "David S. Miller" <[email protected]> Cc: Guo Ren <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent dcad2a6 commit a4261d4

File tree

6 files changed

+123
-149
lines changed

6 files changed

+123
-149
lines changed

arch/sparc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ obj-y += irq_$(BITS).o
3333
obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o
3434

3535
obj-y += process_$(BITS).o
36+
obj-y += process.o
3637
obj-y += signal_$(BITS).o
3738
obj-y += sigutil_$(BITS).o
3839
obj-$(CONFIG_SPARC32) += ioport.o

arch/sparc/kernel/entry.S

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -869,14 +869,11 @@ flush_patch_two:
869869
ld [%curptr + TI_TASK], %o4
870870
rd %psr, %g4
871871
WRITE_PAUSE
872-
mov SIGCHLD, %o0 ! arg0: clone flags
873872
rd %wim, %g5
874873
WRITE_PAUSE
875-
mov %fp, %o1 ! arg1: usp
876874
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
877-
add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr
878-
mov 0, %o3
879-
call sparc_do_fork
875+
add %sp, STACKFRAME_SZ, %o0
876+
call sparc_fork
880877
mov %l5, %o7
881878

882879
/* Whee, kernel threads! */
@@ -888,19 +885,11 @@ flush_patch_three:
888885
ld [%curptr + TI_TASK], %o4
889886
rd %psr, %g4
890887
WRITE_PAUSE
891-
892-
/* arg0,1: flags,usp -- loaded already */
893-
cmp %o1, 0x0 ! Is new_usp NULL?
894888
rd %wim, %g5
895889
WRITE_PAUSE
896-
be,a 1f
897-
mov %fp, %o1 ! yes, use callers usp
898-
andn %o1, 7, %o1 ! no, align to 8 bytes
899-
1:
900890
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
901-
add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr
902-
mov 0, %o3
903-
call sparc_do_fork
891+
add %sp, STACKFRAME_SZ, %o0
892+
call sparc_clone
904893
mov %l5, %o7
905894

906895
/* Whee, real vfork! */
@@ -914,13 +903,9 @@ flush_patch_four:
914903
rd %wim, %g5
915904
WRITE_PAUSE
916905
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
917-
sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
918-
mov %fp, %o1
919-
or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
920-
sethi %hi(sparc_do_fork), %l1
921-
mov 0, %o3
922-
jmpl %l1 + %lo(sparc_do_fork), %g0
923-
add %sp, STACKFRAME_SZ, %o2
906+
sethi %hi(sparc_vfork), %l1
907+
jmpl %l1 + %lo(sparc_vfork), %g0
908+
add %sp, STACKFRAME_SZ, %o0
924909

925910
.align 4
926911
linux_sparc_ni_syscall:

arch/sparc/kernel/kernel.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ extern const char *sparc_pmu_type;
1414
extern unsigned int fsr_storage;
1515
extern int ncpus_probed;
1616

17+
/* process{_32,_64}.c */
18+
asmlinkage long sparc_clone(struct pt_regs *regs);
19+
asmlinkage long sparc_fork(struct pt_regs *regs);
20+
asmlinkage long sparc_vfork(struct pt_regs *regs);
21+
1722
#ifdef CONFIG_SPARC64
1823
/* setup_64.c */
1924
struct seq_file;
@@ -153,12 +158,6 @@ void floppy_hardint(void);
153158
extern unsigned long sun4m_cpu_startup;
154159
extern unsigned long sun4d_cpu_startup;
155160

156-
/* process_32.c */
157-
asmlinkage int sparc_do_fork(unsigned long clone_flags,
158-
unsigned long stack_start,
159-
struct pt_regs *regs,
160-
unsigned long stack_size);
161-
162161
/* signal_32.c */
163162
asmlinkage void do_sigreturn(struct pt_regs *regs);
164163
asmlinkage void do_rt_sigreturn(struct pt_regs *regs);

arch/sparc/kernel/process.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* This file handles the architecture independent parts of process handling..
5+
*/
6+
7+
#include <linux/compat.h>
8+
#include <linux/errno.h>
9+
#include <linux/kernel.h>
10+
#include <linux/ptrace.h>
11+
#include <linux/sched.h>
12+
#include <linux/sched/task.h>
13+
#include <linux/sched/task_stack.h>
14+
#include <linux/signal.h>
15+
16+
#include "kernel.h"
17+
18+
asmlinkage long sparc_fork(struct pt_regs *regs)
19+
{
20+
unsigned long orig_i1 = regs->u_regs[UREG_I1];
21+
long ret;
22+
struct kernel_clone_args args = {
23+
.exit_signal = SIGCHLD,
24+
/* Reuse the parent's stack for the child. */
25+
.stack = regs->u_regs[UREG_FP],
26+
};
27+
28+
ret = _do_fork(&args);
29+
30+
/* If we get an error and potentially restart the system
31+
* call, we're screwed because copy_thread_tls() clobbered
32+
* the parent's %o1. So detect that case and restore it
33+
* here.
34+
*/
35+
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
36+
regs->u_regs[UREG_I1] = orig_i1;
37+
38+
return ret;
39+
}
40+
41+
asmlinkage long sparc_vfork(struct pt_regs *regs)
42+
{
43+
unsigned long orig_i1 = regs->u_regs[UREG_I1];
44+
long ret;
45+
46+
struct kernel_clone_args args = {
47+
.flags = CLONE_VFORK | CLONE_VM,
48+
.exit_signal = SIGCHLD,
49+
/* Reuse the parent's stack for the child. */
50+
.stack = regs->u_regs[UREG_FP],
51+
};
52+
53+
ret = _do_fork(&args);
54+
55+
/* If we get an error and potentially restart the system
56+
* call, we're screwed because copy_thread_tls() clobbered
57+
* the parent's %o1. So detect that case and restore it
58+
* here.
59+
*/
60+
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
61+
regs->u_regs[UREG_I1] = orig_i1;
62+
63+
return ret;
64+
}
65+
66+
asmlinkage long sparc_clone(struct pt_regs *regs)
67+
{
68+
unsigned long orig_i1 = regs->u_regs[UREG_I1];
69+
unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]);
70+
long ret;
71+
72+
struct kernel_clone_args args = {
73+
.flags = (flags & ~CSIGNAL),
74+
.exit_signal = (flags & CSIGNAL),
75+
.tls = regs->u_regs[UREG_I3],
76+
};
77+
78+
#ifdef CONFIG_COMPAT
79+
if (test_thread_flag(TIF_32BIT)) {
80+
args.pidfd = compat_ptr(regs->u_regs[UREG_I2]);
81+
args.child_tid = compat_ptr(regs->u_regs[UREG_I4]);
82+
args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]);
83+
} else
84+
#endif
85+
{
86+
args.pidfd = (int __user *)regs->u_regs[UREG_I2];
87+
args.child_tid = (int __user *)regs->u_regs[UREG_I4];
88+
args.parent_tid = (int __user *)regs->u_regs[UREG_I2];
89+
}
90+
91+
/* Did userspace give setup a separate stack for the child or are we
92+
* reusing the parent's?
93+
*/
94+
if (regs->u_regs[UREG_I1])
95+
args.stack = regs->u_regs[UREG_I1];
96+
else
97+
args.stack = regs->u_regs[UREG_FP];
98+
99+
ret = _do_fork(&args);
100+
101+
/* If we get an error and potentially restart the system
102+
* call, we're screwed because copy_thread_tls() clobbered
103+
* the parent's %o1. So detect that case and restore it
104+
* here.
105+
*/
106+
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
107+
regs->u_regs[UREG_I1] = orig_i1;
108+
109+
return ret;
110+
}

arch/sparc/kernel/process_32.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -257,33 +257,6 @@ clone_stackframe(struct sparc_stackf __user *dst,
257257
return sp;
258258
}
259259

260-
asmlinkage int sparc_do_fork(unsigned long clone_flags,
261-
unsigned long stack_start,
262-
struct pt_regs *regs,
263-
unsigned long stack_size)
264-
{
265-
unsigned long parent_tid_ptr, child_tid_ptr;
266-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
267-
long ret;
268-
269-
parent_tid_ptr = regs->u_regs[UREG_I2];
270-
child_tid_ptr = regs->u_regs[UREG_I4];
271-
272-
ret = do_fork(clone_flags, stack_start, stack_size,
273-
(int __user *) parent_tid_ptr,
274-
(int __user *) child_tid_ptr);
275-
276-
/* If we get an error and potentially restart the system
277-
* call, we're screwed because copy_thread() clobbered
278-
* the parent's %o1. So detect that case and restore it
279-
* here.
280-
*/
281-
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
282-
regs->u_regs[UREG_I1] = orig_i1;
283-
284-
return ret;
285-
}
286-
287260
/* Copy a Sparc thread. The fork() return value conventions
288261
* under SunOS are nothing short of bletcherous:
289262
* Parent --> %o0 == childs pid, %o1 == 0

arch/sparc/kernel/process_64.c

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -572,100 +572,6 @@ void fault_in_user_windows(struct pt_regs *regs)
572572
force_sig(SIGSEGV);
573573
}
574574

575-
asmlinkage long sparc_fork(struct pt_regs *regs)
576-
{
577-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
578-
long ret;
579-
struct kernel_clone_args args = {
580-
.exit_signal = SIGCHLD,
581-
/* Reuse the parent's stack for the child. */
582-
.stack = regs->u_regs[UREG_FP],
583-
};
584-
585-
ret = _do_fork(&args);
586-
587-
/* If we get an error and potentially restart the system
588-
* call, we're screwed because copy_thread_tls() clobbered
589-
* the parent's %o1. So detect that case and restore it
590-
* here.
591-
*/
592-
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
593-
regs->u_regs[UREG_I1] = orig_i1;
594-
595-
return ret;
596-
}
597-
598-
asmlinkage long sparc_vfork(struct pt_regs *regs)
599-
{
600-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
601-
long ret;
602-
603-
struct kernel_clone_args args = {
604-
.flags = CLONE_VFORK | CLONE_VM,
605-
.exit_signal = SIGCHLD,
606-
/* Reuse the parent's stack for the child. */
607-
.stack = regs->u_regs[UREG_FP],
608-
};
609-
610-
ret = _do_fork(&args);
611-
612-
/* If we get an error and potentially restart the system
613-
* call, we're screwed because copy_thread_tls() clobbered
614-
* the parent's %o1. So detect that case and restore it
615-
* here.
616-
*/
617-
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
618-
regs->u_regs[UREG_I1] = orig_i1;
619-
620-
return ret;
621-
}
622-
623-
asmlinkage long sparc_clone(struct pt_regs *regs)
624-
{
625-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
626-
unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]);
627-
long ret;
628-
629-
struct kernel_clone_args args = {
630-
.flags = (flags & ~CSIGNAL),
631-
.exit_signal = (flags & CSIGNAL),
632-
.tls = regs->u_regs[UREG_I3],
633-
};
634-
635-
#ifdef CONFIG_COMPAT
636-
if (test_thread_flag(TIF_32BIT)) {
637-
args.pidfd = compat_ptr(regs->u_regs[UREG_I2]);
638-
args.child_tid = compat_ptr(regs->u_regs[UREG_I4]);
639-
args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]);
640-
} else
641-
#endif
642-
{
643-
args.pidfd = (int __user *)regs->u_regs[UREG_I2];
644-
args.child_tid = (int __user *)regs->u_regs[UREG_I4];
645-
args.parent_tid = (int __user *)regs->u_regs[UREG_I2];
646-
}
647-
648-
/* Did userspace setup a separate stack for the child or are we
649-
* copying the parent's?
650-
*/
651-
if (regs->u_regs[UREG_I1])
652-
args.stack = regs->u_regs[UREG_I1];
653-
else
654-
args.stack = regs->u_regs[UREG_FP];
655-
656-
ret = _do_fork(&args);
657-
658-
/* If we get an error and potentially restart the system
659-
* call, we're screwed because copy_thread_tls() clobbered
660-
* the parent's %o1. So detect that case and restore it
661-
* here.
662-
*/
663-
if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
664-
regs->u_regs[UREG_I1] = orig_i1;
665-
666-
return ret;
667-
}
668-
669575
/* Copy a Sparc thread. The fork() return value conventions
670576
* under SunOS are nothing short of bletcherous:
671577
* Parent --> %o0 == childs pid, %o1 == 0

0 commit comments

Comments
 (0)