1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * syscall_wrapper.h - s390 specific wrappers to syscall definitions 4 * 5 */ 6 7 #ifndef _ASM_S390_SYSCALL_WRAPPER_H 8 #define _ASM_S390_SYSCALL_WRAPPER_H 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 37 #ifdef CONFIG_COMPAT 38 #define __SC_COMPAT_TYPE(t, a) \ 39 __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a 40 41 #define __SC_COMPAT_CAST(t, a) \ 42 ({ \ 43 long __ReS = a; \ 44 \ 45 BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \ 46 !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) && \ 47 !__TYPE_IS_LL(t)); \ 48 if (__TYPE_IS_L(t)) \ 49 __ReS = (s32)a; \ 50 if (__TYPE_IS_UL(t)) \ 51 __ReS = (u32)a; \ 52 if (__TYPE_IS_PTR(t)) \ 53 __ReS = a & 0x7fffffff; \ 54 if (__TYPE_IS_LL(t)) \ 55 return -ENOSYS; \ 56 (t)__ReS; \ 57 }) 58 59 #define __S390_SYS_STUBx(x, name, ...) \ 60 long __s390_sys##name(struct pt_regs *regs); \ 61 ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \ 62 long __s390_sys##name(struct pt_regs *regs) \ 63 { \ 64 long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs, \ 65 __SC_COMPAT_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__))); \ 66 __MAP(x,__SC_TEST,__VA_ARGS__); \ 67 return ret; \ 68 } 69 70 /* 71 * To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias 72 * named __s390x_sys_*() 73 */ 74 #define COMPAT_SYSCALL_DEFINE0(sname) \ 75 SYSCALL_METADATA(_##sname, 0); \ 76 long __s390_compat_sys_##sname(void); \ 77 ALLOW_ERROR_INJECTION(__s390_compat_sys_##sname, ERRNO); \ 78 long __s390_compat_sys_##sname(void) 79 80 #define SYSCALL_DEFINE0(sname) \ 81 SYSCALL_METADATA(_##sname, 0); \ 82 long __s390x_sys_##sname(void); \ 83 ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO); \ 84 long __s390_sys_##sname(void) \ 85 __attribute__((alias(__stringify(__s390x_sys_##sname)))); \ 86 long __s390x_sys_##sname(void) 87 88 #define COND_SYSCALL(name) \ 89 cond_syscall(__s390x_sys_##name); \ 90 cond_syscall(__s390_sys_##name) 91 92 #define SYS_NI(name) \ 93 SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers); \ 94 SYSCALL_ALIAS(__s390_sys_##name, sys_ni_posix_timers) 95 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(struct pt_regs *regs); \ 101 long __s390_compat_sys##name(struct pt_regs *regs) \ 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(struct pt_regs *regs); \ 106 long __se_compat_sys##name(struct pt_regs *regs) \ 107 { \ 108 long ret = __do_compat_sys##name(SYSCALL_PT_ARGS(x, regs, __SC_DELOUSE, \ 109 __MAP(x, __SC_TYPE, __VA_ARGS__))); \ 110 __MAP(x,__SC_TEST,__VA_ARGS__); \ 111 return ret; \ 112 } \ 113 __diag_pop(); \ 114 static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 115 116 /* 117 * As some compat syscalls may not be implemented, we need to expand 118 * COND_SYSCALL_COMPAT in kernel/sys_ni.c and COMPAT_SYS_NI in 119 * kernel/time/posix-stubs.c to cover this case as well. 120 */ 121 #define COND_SYSCALL_COMPAT(name) \ 122 cond_syscall(__s390_compat_sys_##name) 123 124 #define COMPAT_SYS_NI(name) \ 125 SYSCALL_ALIAS(__s390_compat_sys_##name, sys_ni_posix_timers) 126 127 #else /* CONFIG_COMPAT */ 128 129 #define __S390_SYS_STUBx(x, fullname, name, ...) 130 131 #define SYSCALL_DEFINE0(sname) \ 132 SYSCALL_METADATA(_##sname, 0); \ 133 long __s390x_sys_##sname(void); \ 134 ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO); \ 135 long __s390x_sys_##sname(void) 136 137 #define COND_SYSCALL(name) \ 138 cond_syscall(__s390x_sys_##name) 139 140 #define SYS_NI(name) \ 141 SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers); 142 143 #endif /* CONFIG_COMPAT */ 144 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(struct pt_regs *regs) \ 150 __attribute__((alias(__stringify(__se_sys##name)))); \ 151 ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO); \ 152 static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 153 long __se_sys##name(struct pt_regs *regs); \ 154 __S390_SYS_STUBx(x, name, __VA_ARGS__) \ 155 long __se_sys##name(struct pt_regs *regs) \ 156 { \ 157 long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs, \ 158 __SC_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__))); \ 159 __MAP(x,__SC_TEST,__VA_ARGS__); \ 160 return ret; \ 161 } \ 162 __diag_pop(); \ 163 static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 164 165 #endif /* _ASM_S390_SYSCALL_WRAPPER_H */ 166