s390: pass struct pt_regs instead of registers to syscalls
authorSven Schnelle <svens@linux.ibm.com>
Mon, 18 Jan 2021 08:35:38 +0000 (09:35 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 19 Jan 2021 11:29:27 +0000 (12:29 +0100)
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>
arch/s390/include/asm/processor.h
arch/s390/include/asm/syscall_wrapper.h
arch/s390/kernel/syscall.c

index fa67b66bf14470d3774660d7c091fdc4f7978985..023a15dc25a33f3b9d57f52cad28382f6302d7a0 100644 (file)
@@ -40,9 +40,7 @@
 #include <asm/fpu/internal.h>
 #include <asm/irqflags.h>
 
-typedef long (*sys_call_ptr_t)(unsigned long, unsigned long,
-                              unsigned long, unsigned long,
-                              unsigned long, unsigned long);
+typedef long (*sys_call_ptr_t)(struct pt_regs *regs);
 
 static inline void set_cpu_flag(int flag)
 {
index 5364bfc866e013245544a5c636b4b5145529dd0c..ad2c996e7e93dda9e7560256f6d825d15b3d87d0 100644 (file)
@@ -7,6 +7,33 @@
 #ifndef _ASM_S390_SYSCALL_WRAPPER_H
 #define _ASM_S390_SYSCALL_WRAPPER_H
 
+#define __SC_TYPE(t, a) t
+
+#define SYSCALL_PT_ARG6(regs, m, t1, t2, t3, t4, t5, t6)\
+       SYSCALL_PT_ARG5(regs, m, t1, t2, t3, t4, t5),   \
+               m(t6, (regs->gprs[7]))
+
+#define SYSCALL_PT_ARG5(regs, m, t1, t2, t3, t4, t5)   \
+       SYSCALL_PT_ARG4(regs, m, t1, t2, t3, t4),       \
+               m(t5, (regs->gprs[6]))
+
+#define SYSCALL_PT_ARG4(regs, m, t1, t2, t3, t4)       \
+       SYSCALL_PT_ARG3(regs, m, t1, t2, t3),           \
+               m(t4, (regs->gprs[5]))
+
+#define SYSCALL_PT_ARG3(regs, m, t1, t2, t3)           \
+       SYSCALL_PT_ARG2(regs, m, t1, t2),               \
+               m(t3, (regs->gprs[4]))
+
+#define SYSCALL_PT_ARG2(regs, m, t1, t2)               \
+       SYSCALL_PT_ARG1(regs, m, t1),                   \
+               m(t2, (regs->gprs[3]))
+
+#define SYSCALL_PT_ARG1(regs, m, t1)                   \
+               m(t1, (regs->orig_gpr2))
+
+#define SYSCALL_PT_ARGS(x, ...) SYSCALL_PT_ARG##x(__VA_ARGS__)
+
 #ifdef CONFIG_COMPAT
 #define __SC_COMPAT_TYPE(t, a) \
        __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
        (t)__ReS;                                                       \
 })
 
-#define __S390_SYS_STUBx(x, name, ...)                                 \
-       long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));          \
-       ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO);                 \
-       long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))           \
-       {                                                               \
-               long ret = __s390x_sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));\
-               __MAP(x,__SC_TEST,__VA_ARGS__);                         \
-               return ret;                                             \
+#define __S390_SYS_STUBx(x, name, ...)                                         \
+       long __s390_sys##name(struct pt_regs *regs);                            \
+       ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO);                         \
+       long __s390_sys##name(struct pt_regs *regs)                             \
+       {                                                                       \
+               long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs,              \
+                       __SC_COMPAT_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__)));   \
+               __MAP(x,__SC_TEST,__VA_ARGS__);                                 \
+               return ret;                                                     \
        }
 
 /*
        SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers);         \
        SYSCALL_ALIAS(__s390_sys_##name, sys_ni_posix_timers)
 
-#define COMPAT_SYSCALL_DEFINEx(x, name, ...)                                   \
-       __diag_push();                                                          \
-       __diag_ignore(GCC, 8, "-Wattribute-alias",                              \
-                     "Type aliasing is used to sanitize syscall arguments");\
-       long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));           \
-       long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))            \
-               __attribute__((alias(__stringify(__se_compat_sys##name))));     \
-       ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO);                  \
-       static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
-       long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));             \
-       long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))              \
-       {                                                                       \
-               long ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\
-               __MAP(x,__SC_TEST,__VA_ARGS__);                                 \
-               return ret;                                                     \
-       }                                                                       \
-       __diag_pop();                                                           \
+#define COMPAT_SYSCALL_DEFINEx(x, name, ...)                                           \
+       __diag_push();                                                                  \
+       __diag_ignore(GCC, 8, "-Wattribute-alias",                                      \
+                     "Type aliasing is used to sanitize syscall arguments");           \
+       long __s390_compat_sys##name(struct pt_regs *regs);                             \
+       long __s390_compat_sys##name(struct pt_regs *regs)                              \
+               __attribute__((alias(__stringify(__se_compat_sys##name))));             \
+       ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO);                          \
+       static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));       \
+       long __se_compat_sys##name(struct pt_regs *regs);                               \
+       long __se_compat_sys##name(struct pt_regs *regs)                                \
+       {                                                                               \
+               long ret = __do_compat_sys##name(SYSCALL_PT_ARGS(x, regs, __SC_DELOUSE, \
+                                                __MAP(x, __SC_TYPE, __VA_ARGS__)));    \
+               __MAP(x,__SC_TEST,__VA_ARGS__);                                         \
+               return ret;                                                             \
+       }                                                                               \
+       __diag_pop();                                                                   \
        static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
 /*
 
 #endif /* CONFIG_COMPAT */
 
-#define __SYSCALL_DEFINEx(x, name, ...)                                                \
-       __diag_push();                                                          \
-       __diag_ignore(GCC, 8, "-Wattribute-alias",                              \
-                     "Type aliasing is used to sanitize syscall arguments");\
-       long __s390x_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))                  \
-               __attribute__((alias(__stringify(__se_sys##name))));            \
-       ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO);                        \
-       long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));                    \
-       static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));      \
-       __S390_SYS_STUBx(x, name, __VA_ARGS__)                                  \
-       long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))                     \
-       {                                                                       \
-               long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));      \
-               __MAP(x,__SC_TEST,__VA_ARGS__);                                 \
-               return ret;                                                     \
-       }                                                                       \
-       __diag_pop();                                                           \
+#define __SYSCALL_DEFINEx(x, name, ...)                                                        \
+       __diag_push();                                                                  \
+       __diag_ignore(GCC, 8, "-Wattribute-alias",                                      \
+                     "Type aliasing is used to sanitize syscall arguments");           \
+       long __s390x_sys##name(struct pt_regs *regs)                                    \
+               __attribute__((alias(__stringify(__se_sys##name))));                    \
+       ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO);                                \
+       static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));              \
+       long __se_sys##name(struct pt_regs *regs);                                      \
+       __S390_SYS_STUBx(x, name, __VA_ARGS__)                                          \
+       long __se_sys##name(struct pt_regs *regs)                                       \
+       {                                                                               \
+               long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs,                      \
+                                   __SC_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__)));      \
+               __MAP(x,__SC_TEST,__VA_ARGS__);                                         \
+               return ret;                                                             \
+       }                                                                               \
+       __diag_pop();                                                                   \
        static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
 #endif /* _ASM_X86_SYSCALL_WRAPPER_H */
index 25c0fb19b0a5bee6f5f158741bfa222557ffcdc0..bc8e650e377d3adb43f672372c1e5936f5f74b8b 100644 (file)
@@ -132,12 +132,8 @@ void do_syscall(struct pt_regs *regs)
         */
        if (!test_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)) {
                regs->gprs[2] = -ENOSYS;
-               if (likely(nr < NR_syscalls)) {
-                       regs->gprs[2] = current->thread.sys_call_table[nr](
-                                       regs->orig_gpr2, regs->gprs[3],
-                                       regs->gprs[4], regs->gprs[5],
-                                       regs->gprs[6], regs->gprs[7]);
-               }
+               if (likely(nr < NR_syscalls))
+                       regs->gprs[2] = current->thread.sys_call_table[nr](regs);
        } else {
                clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET);
        }