Commit 6b14e4198c729b748a7f6d22059e6a101d2b241a

Authored by Chris Metcalf
Committed by Al Viro
1 parent 530550651f

arch/tile: eliminate pt_regs trampolines for syscalls

Using the new current_pt_regs() model, we can remove some trampolines
from assembly code and call directly to the C syscall implementations.
rt_sigreturn() and clone() still need some assembly wrapping, but no
longer are passed a pt_regs pointer.  sigaltstack() and the
tilepro-specific cmpxchg_badaddr() syscalls are now just straight C.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>

Showing 10 changed files with 39 additions and 57 deletions Side-by-side Diff

arch/tile/include/asm/compat.h
... ... @@ -280,10 +280,9 @@
280 280 size_t sigsetsize);
281 281 long compat_sys_rt_sigqueueinfo(int pid, int sig,
282 282 struct compat_siginfo __user *uinfo);
283   -long compat_sys_rt_sigreturn(struct pt_regs *);
  283 +long compat_sys_rt_sigreturn(void);
284 284 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
285   - struct compat_sigaltstack __user *uoss_ptr,
286   - struct pt_regs *);
  285 + struct compat_sigaltstack __user *uoss_ptr);
287 286 long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high);
288 287 long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high);
289 288 long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
... ... @@ -300,9 +299,7 @@
300 299 long compat_sys_sched_rr_get_interval(compat_pid_t pid,
301 300 struct compat_timespec __user *interval);
302 301  
303   -/* These are the intvec_64.S trampolines. */
304   -long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
305   - struct compat_sigaltstack __user *uoss_ptr);
  302 +/* Assembly trampoline to avoid clobbering r0. */
306 303 long _compat_sys_rt_sigreturn(void);
307 304  
308 305 #endif /* _ASM_TILE_COMPAT_H */
arch/tile/include/asm/syscalls.h
... ... @@ -51,8 +51,7 @@
51 51  
52 52 #ifndef __tilegx__
53 53 /* mm/fault.c */
54   -long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
55   -long _sys_cmpxchg_badaddr(unsigned long address);
  54 +long sys_cmpxchg_badaddr(unsigned long address);
56 55 #endif
57 56  
58 57 #ifdef CONFIG_COMPAT
59 58  
60 59  
... ... @@ -63,15 +62,23 @@
63 62 long sys_ftruncate64(unsigned int fd, loff_t length);
64 63 #endif
65 64  
66   -/* These are the intvec*.S trampolines. */
67   -long _sys_sigaltstack(const stack_t __user *, stack_t __user *);
68   -long _sys_rt_sigreturn(void);
69   -long _sys_clone(unsigned long clone_flags, unsigned long newsp,
  65 +/* Provide versions of standard syscalls that use current_pt_regs(). */
  66 +long sys_clone(unsigned long clone_flags, unsigned long newsp,
70 67 void __user *parent_tid, void __user *child_tid);
71 68 long sys_execve(const char __user *filename,
72 69 const char __user *const __user *argv,
73 70 const char __user *const __user *envp);
  71 +long sys_rt_sigreturn(void);
  72 +long sys_sigaltstack(const stack_t __user *, stack_t __user *);
  73 +#define sys_clone sys_clone
74 74 #define sys_execve sys_execve
  75 +#define sys_rt_sigreturn sys_rt_sigreturn
  76 +#define sys_sigaltstack sys_sigaltstack
  77 +
  78 +/* These are the intvec*.S trampolines. */
  79 +long _sys_rt_sigreturn(void);
  80 +long _sys_clone(unsigned long clone_flags, unsigned long newsp,
  81 + void __user *parent_tid, void __user *child_tid);
75 82  
76 83 #include <asm-generic/syscalls.h>
77 84  
arch/tile/kernel/compat.c
... ... @@ -102,9 +102,9 @@
102 102 #define compat_sys_fadvise64_64 sys32_fadvise64_64
103 103 #define compat_sys_readahead sys32_readahead
104 104  
105   -/* Call the trampolines to manage pt_regs where necessary. */
106   -#define compat_sys_sigaltstack _compat_sys_sigaltstack
  105 +/* Call the assembly trampolines where necessary. */
107 106 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
  107 +#undef sys_clone
108 108 #define sys_clone _sys_clone
109 109  
110 110 /*
arch/tile/kernel/compat_signal.c
... ... @@ -197,8 +197,7 @@
197 197 }
198 198  
199 199 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
200   - struct compat_sigaltstack __user *uoss_ptr,
201   - struct pt_regs *regs)
  200 + struct compat_sigaltstack __user *uoss_ptr)
202 201 {
203 202 stack_t uss, uoss;
204 203 int ret;
... ... @@ -219,7 +218,7 @@
219 218 set_fs(KERNEL_DS);
220 219 ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
221 220 (stack_t __user __force *)&uoss,
222   - (unsigned long)compat_ptr(regs->sp));
  221 + (unsigned long)compat_ptr(current_pt_regs()->sp));
223 222 set_fs(seg);
224 223 if (ret >= 0 && uoss_ptr) {
225 224 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
226 225  
... ... @@ -232,8 +231,9 @@
232 231 }
233 232  
234 233 /* The assembly shim for this function arranges to ignore the return value. */
235   -long compat_sys_rt_sigreturn(struct pt_regs *regs)
  234 +long compat_sys_rt_sigreturn(void)
236 235 {
  236 + struct pt_regs *regs = current_pt_regs();
237 237 struct compat_rt_sigframe __user *frame =
238 238 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
239 239 sigset_t set;
... ... @@ -248,7 +248,7 @@
248 248 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
249 249 goto badframe;
250 250  
251   - if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
  251 + if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) != 0)
252 252 goto badframe;
253 253  
254 254 return 0;
arch/tile/kernel/intvec_32.S
... ... @@ -1452,15 +1452,6 @@
1452 1452 panic "Unhandled interrupt %#x: PC %#lx"
1453 1453 STD_ENDPROC(bad_intr)
1454 1454  
1455   -/* Put address of pt_regs in reg and jump. */
1456   -#define PTREGS_SYSCALL(x, reg) \
1457   - STD_ENTRY(_##x); \
1458   - { \
1459   - PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \
1460   - j x \
1461   - }; \
1462   - STD_ENDPROC(_##x)
1463   -
1464 1455 /*
1465 1456 * Special-case sigreturn to not write r0 to the stack on return.
1466 1457 * This is technically more efficient, but it also avoids difficulties
1467 1458  
1468 1459  
... ... @@ -1476,11 +1467,9 @@
1476 1467 }; \
1477 1468 STD_ENDPROC(_##x)
1478 1469  
1479   -PTREGS_SYSCALL(sys_sigaltstack, r2)
1480 1470 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
1481   -PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
1482 1471  
1483   -/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
  1472 +/* Save additional callee-saves to pt_regs and jump to standard function. */
1484 1473 STD_ENTRY(_sys_clone)
1485 1474 push_extra_callee_saves r4
1486 1475 j sys_clone
arch/tile/kernel/intvec_64.S
... ... @@ -1181,15 +1181,6 @@
1181 1181 panic "Unhandled interrupt %#x: PC %#lx"
1182 1182 STD_ENDPROC(bad_intr)
1183 1183  
1184   -/* Put address of pt_regs in reg and jump. */
1185   -#define PTREGS_SYSCALL(x, reg) \
1186   - STD_ENTRY(_##x); \
1187   - { \
1188   - PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \
1189   - j x \
1190   - }; \
1191   - STD_ENDPROC(_##x)
1192   -
1193 1184 /*
1194 1185 * Special-case sigreturn to not write r0 to the stack on return.
1195 1186 * This is technically more efficient, but it also avoids difficulties
1196 1187  
1197 1188  
... ... @@ -1205,14 +1196,12 @@
1205 1196 }; \
1206 1197 STD_ENDPROC(_##x)
1207 1198  
1208   -PTREGS_SYSCALL(sys_sigaltstack, r2)
1209 1199 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
1210 1200 #ifdef CONFIG_COMPAT
1211   -PTREGS_SYSCALL(compat_sys_sigaltstack, r2)
1212 1201 PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0)
1213 1202 #endif
1214 1203  
1215   -/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
  1204 +/* Save additional callee-saves to pt_regs and jump to standard function. */
1216 1205 STD_ENTRY(_sys_clone)
1217 1206 push_extra_callee_saves r4
1218 1207 j sys_clone
arch/tile/kernel/process.c
... ... @@ -584,10 +584,10 @@
584 584 }
585 585  
586 586 /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
587   -SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
588   - void __user *, parent_tidptr, void __user *, child_tidptr,
589   - struct pt_regs *, regs)
  587 +SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp,
  588 + void __user *, parent_tidptr, void __user *, child_tidptr)
590 589 {
  590 + struct pt_regs *regs = current_pt_regs();
591 591 if (!newsp)
592 592 newsp = regs->sp;
593 593 return do_fork(clone_flags, newsp, regs, 0,
arch/tile/kernel/signal.c
... ... @@ -37,10 +37,10 @@
37 37  
38 38 #define DEBUG_SIG 0
39 39  
40   -SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
41   - stack_t __user *, uoss, struct pt_regs *, regs)
  40 +SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss,
  41 + stack_t __user *, uoss)
42 42 {
43   - return do_sigaltstack(uss, uoss, regs->sp);
  43 + return do_sigaltstack(uss, uoss, current_pt_regs()->sp);
44 44 }
45 45  
46 46  
47 47  
... ... @@ -83,8 +83,9 @@
83 83 }
84 84  
85 85 /* The assembly shim for this function arranges to ignore the return value. */
86   -SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
  86 +SYSCALL_DEFINE0(rt_sigreturn)
87 87 {
  88 + struct pt_regs *regs = current_pt_regs();
88 89 struct rt_sigframe __user *frame =
89 90 (struct rt_sigframe __user *)(regs->sp);
90 91 sigset_t set;
arch/tile/kernel/sys.c
... ... @@ -106,13 +106,11 @@
106 106 #define sys_readahead sys32_readahead
107 107 #endif
108 108  
109   -/* Call the trampolines to manage pt_regs where necessary. */
110   -#define sys_sigaltstack _sys_sigaltstack
  109 +/* Call the assembly trampolines where necessary. */
  110 +#undef sys_rt_sigreturn
111 111 #define sys_rt_sigreturn _sys_rt_sigreturn
  112 +#undef sys_clone
112 113 #define sys_clone _sys_clone
113   -#ifndef __tilegx__
114   -#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr
115   -#endif
116 114  
117 115 /*
118 116 * Note that we can't include <linux/unistd.h> here since the header
arch/tile/mm/fault.c
... ... @@ -70,9 +70,10 @@
70 70 * Synthesize the fault a PL0 process would get by doing a word-load of
71 71 * an unaligned address or a high kernel address.
72 72 */
73   -SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,
74   - struct pt_regs *, regs)
  73 +SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address)
75 74 {
  75 + struct pt_regs *regs = current_pt_regs();
  76 +
76 77 if (address >= PAGE_OFFSET)
77 78 force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR,
78 79 address, INT_DTLB_MISS, current, regs);