Skip to content

Commit 7e3a1e0

Browse files
committed
Merge tag 'sparc-for-7.0-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/alarsson/linux-sparc
Pull sparc updates from Andreas Larsson: - Hardcode uapi ioctls.h TC* constants to not rely upon struct termio that has been dropped by glibc - Fix bug for fork/clone and add support for clone3 - Add ARCH_HAS_CC_CAN_LINK - API choice improvements and cleanup of unused variables * tag 'sparc-for-7.0-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/alarsson/linux-sparc: sparc: remove unused variable strtab sparc64: fix unused variable warning sparc: don't reference obsolete termio struct for TC* constants sparc: vio: Replace snprintf with strscpy in vio_create_one sparc: Add architecture support for clone3 sparc: Synchronize user stack on fork and clone sparc: Implement ARCH_HAS_CC_CAN_LINK
2 parents b33c3b8 + d844152 commit 7e3a1e0

14 files changed

Lines changed: 119 additions & 43 deletions

File tree

arch/sparc/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ config 64BIT
1313
config SPARC
1414
bool
1515
default y
16+
select ARCH_HAS_CC_CAN_LINK
1617
select ARCH_HAS_CPU_CACHE_ALIASING
1718
select ARCH_HAS_DMA_OPS
1819
select ARCH_MIGHT_HAVE_PC_PARPORT if SPARC64 && PCI
@@ -475,4 +476,14 @@ config COMPAT
475476
select ARCH_WANT_OLD_COMPAT_IPC
476477
select COMPAT_OLD_SIGACTION
477478

479+
config ARCH_CC_CAN_LINK
480+
bool
481+
default $(cc_can_link_user,-m64) if 64BIT
482+
default $(cc_can_link_user,-m32)
483+
484+
config ARCH_USERFLAGS
485+
string
486+
default "-m64" if 64BIT
487+
default "-m32"
488+
478489
source "drivers/sbus/char/Kconfig"

arch/sparc/include/asm/syscalls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ struct pt_regs;
77
asmlinkage long sparc_fork(struct pt_regs *regs);
88
asmlinkage long sparc_vfork(struct pt_regs *regs);
99
asmlinkage long sparc_clone(struct pt_regs *regs);
10+
asmlinkage long sparc_clone3(struct pt_regs *regs);
1011

1112
#endif /* _SPARC64_SYSCALLS_H */

arch/sparc/include/asm/unistd.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@
4949
#define __ARCH_WANT_COMPAT_STAT
5050
#endif
5151

52-
#define __ARCH_BROKEN_SYS_CLONE3
53-
5452
#ifdef __32bit_syscall_numbers__
5553
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
5654
* it never had the plain ones and there is no value to adding those

arch/sparc/include/uapi/asm/ioctls.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
#include <asm/ioctl.h>
66

77
/* Big T */
8-
#define TCGETA _IOR('T', 1, struct termio)
9-
#define TCSETA _IOW('T', 2, struct termio)
10-
#define TCSETAW _IOW('T', 3, struct termio)
11-
#define TCSETAF _IOW('T', 4, struct termio)
8+
#define TCGETA 0x40125401 /* _IOR('T', 1, struct termio) */
9+
#define TCSETA 0x80125402 /* _IOW('T', 2, struct termio) */
10+
#define TCSETAW 0x80125403 /* _IOW('T', 3, struct termio) */
11+
#define TCSETAF 0x80125404 /* _IOW('T', 4, struct termio) */
1212
#define TCSBRK _IO('T', 5)
1313
#define TCXONC _IO('T', 6)
1414
#define TCFLSH _IO('T', 7)

arch/sparc/kernel/entry.S

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,21 @@ flush_patch_four:
907907
jmpl %l1 + %lo(sparc_vfork), %g0
908908
add %sp, STACKFRAME_SZ, %o0
909909

910+
.globl __sys_clone3, flush_patch_five
911+
__sys_clone3:
912+
mov %o7, %l5
913+
flush_patch_five:
914+
FLUSH_ALL_KERNEL_WINDOWS;
915+
ld [%curptr + TI_TASK], %o4
916+
rd %psr, %g4
917+
WRITE_PAUSE
918+
rd %wim, %g5
919+
WRITE_PAUSE
920+
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
921+
add %sp, STACKFRAME_SZ, %o0
922+
call sparc_clone3
923+
mov %l5, %o7
924+
910925
.align 4
911926
linux_sparc_ni_syscall:
912927
sethi %hi(sys_ni_syscall), %l7

arch/sparc/kernel/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ extern int ncpus_probed;
1818
asmlinkage long sparc_clone(struct pt_regs *regs);
1919
asmlinkage long sparc_fork(struct pt_regs *regs);
2020
asmlinkage long sparc_vfork(struct pt_regs *regs);
21+
asmlinkage long sparc_clone3(struct pt_regs *regs);
2122

2223
#ifdef CONFIG_SPARC64
2324
/* setup_64.c */

arch/sparc/kernel/module.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
2929
{
3030
unsigned int symidx;
3131
Elf_Sym *sym;
32-
char *strtab;
3332
int i;
3433

3534
for (symidx = 0; sechdrs[symidx].sh_type != SHT_SYMTAB; symidx++) {
@@ -39,7 +38,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
3938
}
4039
}
4140
sym = (Elf_Sym *)sechdrs[symidx].sh_addr;
42-
strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr;
4341

4442
for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) {
4543
if (sym[i].st_shndx == SHN_UNDEF) {

arch/sparc/kernel/process.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,24 @@
1212
#include <linux/sched/task.h>
1313
#include <linux/sched/task_stack.h>
1414
#include <linux/signal.h>
15+
#include <linux/syscalls.h>
1516

1617
#include "kernel.h"
1718

1819
asmlinkage long sparc_fork(struct pt_regs *regs)
1920
{
20-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
21+
unsigned long orig_i1;
2122
long ret;
2223
struct kernel_clone_args args = {
2324
.exit_signal = SIGCHLD,
24-
/* Reuse the parent's stack for the child. */
25-
.stack = regs->u_regs[UREG_FP],
2625
};
2726

27+
synchronize_user_stack();
28+
29+
orig_i1 = regs->u_regs[UREG_I1];
30+
/* Reuse the parent's stack for the child. */
31+
args.stack = regs->u_regs[UREG_FP];
32+
2833
ret = kernel_clone(&args);
2934

3035
/* If we get an error and potentially restart the system
@@ -40,16 +45,19 @@ asmlinkage long sparc_fork(struct pt_regs *regs)
4045

4146
asmlinkage long sparc_vfork(struct pt_regs *regs)
4247
{
43-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
48+
unsigned long orig_i1;
4449
long ret;
45-
4650
struct kernel_clone_args args = {
4751
.flags = CLONE_VFORK | CLONE_VM,
4852
.exit_signal = SIGCHLD,
49-
/* Reuse the parent's stack for the child. */
50-
.stack = regs->u_regs[UREG_FP],
5153
};
5254

55+
synchronize_user_stack();
56+
57+
orig_i1 = regs->u_regs[UREG_I1];
58+
/* Reuse the parent's stack for the child. */
59+
args.stack = regs->u_regs[UREG_FP];
60+
5361
ret = kernel_clone(&args);
5462

5563
/* If we get an error and potentially restart the system
@@ -65,15 +73,18 @@ asmlinkage long sparc_vfork(struct pt_regs *regs)
6573

6674
asmlinkage long sparc_clone(struct pt_regs *regs)
6775
{
68-
unsigned long orig_i1 = regs->u_regs[UREG_I1];
69-
unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]);
76+
unsigned long orig_i1;
77+
unsigned int flags;
7078
long ret;
79+
struct kernel_clone_args args = {0};
7180

72-
struct kernel_clone_args args = {
73-
.flags = (flags & ~CSIGNAL),
74-
.exit_signal = (flags & CSIGNAL),
75-
.tls = regs->u_regs[UREG_I3],
76-
};
81+
synchronize_user_stack();
82+
83+
orig_i1 = regs->u_regs[UREG_I1];
84+
flags = lower_32_bits(regs->u_regs[UREG_I0]);
85+
args.flags = (flags & ~CSIGNAL);
86+
args.exit_signal = (flags & CSIGNAL);
87+
args.tls = regs->u_regs[UREG_I3];
7788

7889
#ifdef CONFIG_COMPAT
7990
if (test_thread_flag(TIF_32BIT)) {
@@ -108,3 +119,16 @@ asmlinkage long sparc_clone(struct pt_regs *regs)
108119

109120
return ret;
110121
}
122+
123+
asmlinkage long sparc_clone3(struct pt_regs *regs)
124+
{
125+
unsigned long sz;
126+
struct clone_args __user *cl_args;
127+
128+
synchronize_user_stack();
129+
130+
cl_args = (struct clone_args __user *)regs->u_regs[UREG_I0];
131+
sz = regs->u_regs[UREG_I1];
132+
133+
return sys_clone3(cl_args, sz);
134+
}

arch/sparc/kernel/process_32.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ clone_stackframe(struct sparc_stackf __user *dst,
247247
* Parent --> %o0 == childs pid, %o1 == 0
248248
* Child --> %o0 == parents pid, %o1 == 1
249249
*
250+
* clone3() - Uses regular kernel return value conventions
251+
*
250252
* NOTE: We have a separate fork kpsr/kwim because
251253
* the parent could change these values between
252254
* sys_fork invocation and when we reach here
@@ -261,11 +263,11 @@ extern void ret_from_kernel_thread(void);
261263
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
262264
{
263265
u64 clone_flags = args->flags;
264-
unsigned long sp = args->stack;
265266
unsigned long tls = args->tls;
266267
struct thread_info *ti = task_thread_info(p);
267268
struct pt_regs *childregs, *regs = current_pt_regs();
268269
char *new_stack;
270+
unsigned long sp = args->stack ? args->stack : regs->u_regs[UREG_FP];
269271

270272
#ifndef CONFIG_SMP
271273
if(last_task_used_math == current) {
@@ -350,13 +352,22 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
350352
childregs->psr &= ~PSR_EF;
351353
clear_tsk_thread_flag(p, TIF_USEDFPU);
352354
#endif
355+
/* Handle return value conventions */
356+
if (regs->u_regs[UREG_G1] == __NR_clone3) {
357+
/* clone3() - use regular kernel return value convention */
358+
359+
/* Set the return value for the child. */
360+
childregs->u_regs[UREG_I0] = 0;
361+
} else {
362+
/* clone()/fork() - use SunOS return value convention */
353363

354-
/* Set the return value for the child. */
355-
childregs->u_regs[UREG_I0] = current->pid;
356-
childregs->u_regs[UREG_I1] = 1;
364+
/* Set the return value for the child. */
365+
childregs->u_regs[UREG_I0] = current->pid;
366+
childregs->u_regs[UREG_I1] = 1;
357367

358-
/* Set the return value for the parent. */
359-
regs->u_regs[UREG_I1] = 0;
368+
/* Set the return value for the parent. */
369+
regs->u_regs[UREG_I1] = 0;
370+
}
360371

361372
if (clone_flags & CLONE_SETTLS)
362373
childregs->u_regs[UREG_G7] = tls;

arch/sparc/kernel/process_64.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -564,17 +564,19 @@ void fault_in_user_windows(struct pt_regs *regs)
564564
* under SunOS are nothing short of bletcherous:
565565
* Parent --> %o0 == childs pid, %o1 == 0
566566
* Child --> %o0 == parents pid, %o1 == 1
567+
*
568+
* clone3() - Uses regular kernel return value conventions
567569
*/
568570
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
569571
{
570572
u64 clone_flags = args->flags;
571-
unsigned long sp = args->stack;
572573
unsigned long tls = args->tls;
573574
struct thread_info *t = task_thread_info(p);
574575
struct pt_regs *regs = current_pt_regs();
575576
struct sparc_stackf *parent_sf;
576577
unsigned long child_stack_sz;
577578
char *child_trap_frame;
579+
unsigned long sp = args->stack ? args->stack : regs->u_regs[UREG_FP];
578580

579581
/* Calculate offset to stack_frame & pt_regs */
580582
child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);
@@ -616,12 +618,25 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
616618
if (t->utraps)
617619
t->utraps[0]++;
618620

619-
/* Set the return value for the child. */
620-
t->kregs->u_regs[UREG_I0] = current->pid;
621-
t->kregs->u_regs[UREG_I1] = 1;
621+
/* Handle return value conventions */
622+
if (regs->u_regs[UREG_G1] == __NR_clone3) {
623+
/* clone3() - use regular kernel return value convention */
624+
625+
/* Set the return value for the child. */
626+
t->kregs->u_regs[UREG_I0] = 0;
627+
628+
/* Clear g1 to indicate user thread */
629+
t->kregs->u_regs[UREG_G1] = 0;
630+
} else {
631+
/* clone()/fork() - use SunOS return value convention */
632+
633+
/* Set the return value for the child. */
634+
t->kregs->u_regs[UREG_I0] = current->pid;
635+
t->kregs->u_regs[UREG_I1] = 1;
622636

623-
/* Set the second return value for the parent. */
624-
regs->u_regs[UREG_I1] = 0;
637+
/* Set the second return value for the parent. */
638+
regs->u_regs[UREG_I1] = 0;
639+
}
625640

626641
if (clone_flags & CLONE_SETTLS)
627642
t->kregs->u_regs[UREG_G7] = tls;

0 commit comments

Comments
 (0)