Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390: pass struct pt_regs instead of registers to syscalls

Instead of fetching all registers from struct pt_regs and passing
them to the syscall wrappers, let the system call wrappers only
fetch the values really required.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Sven Schnelle and committed by
Vasily Gorbik
3a790cc1 39589ada

+75 -51
+1 -3
arch/s390/include/asm/processor.h
··· 40 40 #include <asm/fpu/internal.h> 41 41 #include <asm/irqflags.h> 42 42 43 - typedef long (*sys_call_ptr_t)(unsigned long, unsigned long, 44 - unsigned long, unsigned long, 45 - unsigned long, unsigned long); 43 + typedef long (*sys_call_ptr_t)(struct pt_regs *regs); 46 44 47 45 static inline void set_cpu_flag(int flag) 48 46 {
+72 -42
arch/s390/include/asm/syscall_wrapper.h
··· 7 7 #ifndef _ASM_S390_SYSCALL_WRAPPER_H 8 8 #define _ASM_S390_SYSCALL_WRAPPER_H 9 9 10 + #define __SC_TYPE(t, a) t 11 + 12 + #define SYSCALL_PT_ARG6(regs, m, t1, t2, t3, t4, t5, t6)\ 13 + SYSCALL_PT_ARG5(regs, m, t1, t2, t3, t4, t5), \ 14 + m(t6, (regs->gprs[7])) 15 + 16 + #define SYSCALL_PT_ARG5(regs, m, t1, t2, t3, t4, t5) \ 17 + SYSCALL_PT_ARG4(regs, m, t1, t2, t3, t4), \ 18 + m(t5, (regs->gprs[6])) 19 + 20 + #define SYSCALL_PT_ARG4(regs, m, t1, t2, t3, t4) \ 21 + SYSCALL_PT_ARG3(regs, m, t1, t2, t3), \ 22 + m(t4, (regs->gprs[5])) 23 + 24 + #define SYSCALL_PT_ARG3(regs, m, t1, t2, t3) \ 25 + SYSCALL_PT_ARG2(regs, m, t1, t2), \ 26 + m(t3, (regs->gprs[4])) 27 + 28 + #define SYSCALL_PT_ARG2(regs, m, t1, t2) \ 29 + SYSCALL_PT_ARG1(regs, m, t1), \ 30 + m(t2, (regs->gprs[3])) 31 + 32 + #define SYSCALL_PT_ARG1(regs, m, t1) \ 33 + m(t1, (regs->orig_gpr2)) 34 + 35 + #define SYSCALL_PT_ARGS(x, ...) SYSCALL_PT_ARG##x(__VA_ARGS__) 36 + 10 37 #ifdef CONFIG_COMPAT 11 38 #define __SC_COMPAT_TYPE(t, a) \ 12 39 __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a ··· 56 29 (t)__ReS; \ 57 30 }) 58 31 59 - #define __S390_SYS_STUBx(x, name, ...) \ 60 - long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ 61 - ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \ 62 - long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ 63 - { \ 64 - long ret = __s390x_sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));\ 65 - __MAP(x,__SC_TEST,__VA_ARGS__); \ 66 - return ret; \ 32 + #define __S390_SYS_STUBx(x, name, ...) \ 33 + long __s390_sys##name(struct pt_regs *regs); \ 34 + ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \ 35 + long __s390_sys##name(struct pt_regs *regs) \ 36 + { \ 37 + long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs, \ 38 + __SC_COMPAT_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__))); \ 39 + __MAP(x,__SC_TEST,__VA_ARGS__); \ 40 + return ret; \ 67 41 } 68 42 69 43 /* ··· 93 65 SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers); \ 94 66 SYSCALL_ALIAS(__s390_sys_##name, sys_ni_posix_timers) 95 67 96 - #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ 97 - __diag_push(); \ 98 - __diag_ignore(GCC, 8, "-Wattribute-alias", \ 99 - "Type aliasing is used to sanitize syscall arguments");\ 100 - long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 101 - long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ 102 - __attribute__((alias(__stringify(__se_compat_sys##name)))); \ 103 - ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO); \ 104 - static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ 105 - long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ 106 - long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ 107 - { \ 108 - long ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\ 109 - __MAP(x,__SC_TEST,__VA_ARGS__); \ 110 - return ret; \ 111 - } \ 112 - __diag_pop(); \ 68 + #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ 69 + __diag_push(); \ 70 + __diag_ignore(GCC, 8, "-Wattribute-alias", \ 71 + "Type aliasing is used to sanitize syscall arguments"); \ 72 + long __s390_compat_sys##name(struct pt_regs *regs); \ 73 + long __s390_compat_sys##name(struct pt_regs *regs) \ 74 + __attribute__((alias(__stringify(__se_compat_sys##name)))); \ 75 + ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO); \ 76 + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 77 + long __se_compat_sys##name(struct pt_regs *regs); \ 78 + long __se_compat_sys##name(struct pt_regs *regs) \ 79 + { \ 80 + long ret = __do_compat_sys##name(SYSCALL_PT_ARGS(x, regs, __SC_DELOUSE, \ 81 + __MAP(x, __SC_TYPE, __VA_ARGS__))); \ 82 + __MAP(x,__SC_TEST,__VA_ARGS__); \ 83 + return ret; \ 84 + } \ 85 + __diag_pop(); \ 113 86 static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 114 87 115 88 /* ··· 142 113 143 114 #endif /* CONFIG_COMPAT */ 144 115 145 - #define __SYSCALL_DEFINEx(x, name, ...) \ 146 - __diag_push(); \ 147 - __diag_ignore(GCC, 8, "-Wattribute-alias", \ 148 - "Type aliasing is used to sanitize syscall arguments");\ 149 - long __s390x_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ 150 - __attribute__((alias(__stringify(__se_sys##name)))); \ 151 - ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO); \ 152 - long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ 153 - static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 154 - __S390_SYS_STUBx(x, name, __VA_ARGS__) \ 155 - long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ 156 - { \ 157 - long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ 158 - __MAP(x,__SC_TEST,__VA_ARGS__); \ 159 - return ret; \ 160 - } \ 161 - __diag_pop(); \ 116 + #define __SYSCALL_DEFINEx(x, name, ...) \ 117 + __diag_push(); \ 118 + __diag_ignore(GCC, 8, "-Wattribute-alias", \ 119 + "Type aliasing is used to sanitize syscall arguments"); \ 120 + long __s390x_sys##name(struct pt_regs *regs) \ 121 + __attribute__((alias(__stringify(__se_sys##name)))); \ 122 + ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO); \ 123 + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 124 + long __se_sys##name(struct pt_regs *regs); \ 125 + __S390_SYS_STUBx(x, name, __VA_ARGS__) \ 126 + long __se_sys##name(struct pt_regs *regs) \ 127 + { \ 128 + long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs, \ 129 + __SC_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__))); \ 130 + __MAP(x,__SC_TEST,__VA_ARGS__); \ 131 + return ret; \ 132 + } \ 133 + __diag_pop(); \ 162 134 static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 163 135 164 136 #endif /* _ASM_X86_SYSCALL_WRAPPER_H */
+2 -6
arch/s390/kernel/syscall.c
··· 132 132 */ 133 133 if (!test_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)) { 134 134 regs->gprs[2] = -ENOSYS; 135 - if (likely(nr < NR_syscalls)) { 136 - regs->gprs[2] = current->thread.sys_call_table[nr]( 137 - regs->orig_gpr2, regs->gprs[3], 138 - regs->gprs[4], regs->gprs[5], 139 - regs->gprs[6], regs->gprs[7]); 140 - } 135 + if (likely(nr < NR_syscalls)) 136 + regs->gprs[2] = current->thread.sys_call_table[nr](regs); 141 137 } else { 142 138 clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET); 143 139 }