Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Access to user system call parameters and results
0004  *
0005  *  Copyright IBM Corp. 2008
0006  *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
0007  */
0008 
0009 #ifndef _ASM_SYSCALL_H
0010 #define _ASM_SYSCALL_H  1
0011 
0012 #include <uapi/linux/audit.h>
0013 #include <linux/sched.h>
0014 #include <linux/err.h>
0015 #include <asm/ptrace.h>
0016 
0017 extern const sys_call_ptr_t sys_call_table[];
0018 extern const sys_call_ptr_t sys_call_table_emu[];
0019 
0020 static inline long syscall_get_nr(struct task_struct *task,
0021                   struct pt_regs *regs)
0022 {
0023     return test_pt_regs_flag(regs, PIF_SYSCALL) ?
0024         (regs->int_code & 0xffff) : -1;
0025 }
0026 
0027 static inline void syscall_rollback(struct task_struct *task,
0028                     struct pt_regs *regs)
0029 {
0030     regs->gprs[2] = regs->orig_gpr2;
0031 }
0032 
0033 static inline long syscall_get_error(struct task_struct *task,
0034                      struct pt_regs *regs)
0035 {
0036     unsigned long error = regs->gprs[2];
0037 #ifdef CONFIG_COMPAT
0038     if (test_tsk_thread_flag(task, TIF_31BIT)) {
0039         /*
0040          * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
0041          * and will match correctly in comparisons.
0042          */
0043         error = (long)(int)error;
0044     }
0045 #endif
0046     return IS_ERR_VALUE(error) ? error : 0;
0047 }
0048 
0049 static inline long syscall_get_return_value(struct task_struct *task,
0050                         struct pt_regs *regs)
0051 {
0052     return regs->gprs[2];
0053 }
0054 
0055 static inline void syscall_set_return_value(struct task_struct *task,
0056                         struct pt_regs *regs,
0057                         int error, long val)
0058 {
0059     set_pt_regs_flag(regs, PIF_SYSCALL_RET_SET);
0060     regs->gprs[2] = error ? error : val;
0061 }
0062 
0063 static inline void syscall_get_arguments(struct task_struct *task,
0064                      struct pt_regs *regs,
0065                      unsigned long *args)
0066 {
0067     unsigned long mask = -1UL;
0068     unsigned int n = 6;
0069 
0070 #ifdef CONFIG_COMPAT
0071     if (test_tsk_thread_flag(task, TIF_31BIT))
0072         mask = 0xffffffff;
0073 #endif
0074     while (n-- > 0)
0075         if (n > 0)
0076             args[n] = regs->gprs[2 + n] & mask;
0077 
0078     args[0] = regs->orig_gpr2 & mask;
0079 }
0080 
0081 static inline int syscall_get_arch(struct task_struct *task)
0082 {
0083 #ifdef CONFIG_COMPAT
0084     if (test_tsk_thread_flag(task, TIF_31BIT))
0085         return AUDIT_ARCH_S390;
0086 #endif
0087     return AUDIT_ARCH_S390X;
0088 }
0089 
0090 static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
0091 {
0092     return false;
0093 }
0094 
0095 #define SYSCALL_FMT_0
0096 #define SYSCALL_FMT_1 , "0" (r2)
0097 #define SYSCALL_FMT_2 , "d" (r3) SYSCALL_FMT_1
0098 #define SYSCALL_FMT_3 , "d" (r4) SYSCALL_FMT_2
0099 #define SYSCALL_FMT_4 , "d" (r5) SYSCALL_FMT_3
0100 #define SYSCALL_FMT_5 , "d" (r6) SYSCALL_FMT_4
0101 #define SYSCALL_FMT_6 , "d" (r7) SYSCALL_FMT_5
0102 
0103 #define SYSCALL_PARM_0
0104 #define SYSCALL_PARM_1 , long arg1
0105 #define SYSCALL_PARM_2 SYSCALL_PARM_1, long arg2
0106 #define SYSCALL_PARM_3 SYSCALL_PARM_2, long arg3
0107 #define SYSCALL_PARM_4 SYSCALL_PARM_3, long arg4
0108 #define SYSCALL_PARM_5 SYSCALL_PARM_4, long arg5
0109 #define SYSCALL_PARM_6 SYSCALL_PARM_5, long arg6
0110 
0111 #define SYSCALL_REGS_0
0112 #define SYSCALL_REGS_1                          \
0113     register long r2 asm("2") = arg1
0114 #define SYSCALL_REGS_2                          \
0115     SYSCALL_REGS_1;                         \
0116     register long r3 asm("3") = arg2
0117 #define SYSCALL_REGS_3                          \
0118     SYSCALL_REGS_2;                         \
0119     register long r4 asm("4") = arg3
0120 #define SYSCALL_REGS_4                          \
0121     SYSCALL_REGS_3;                         \
0122     register long r5 asm("5") = arg4
0123 #define SYSCALL_REGS_5                          \
0124     SYSCALL_REGS_4;                         \
0125     register long r6 asm("6") = arg5
0126 #define SYSCALL_REGS_6                          \
0127     SYSCALL_REGS_5;                         \
0128     register long r7 asm("7") = arg6
0129 
0130 #define GENERATE_SYSCALL_FUNC(nr)                   \
0131 static __always_inline                          \
0132 long syscall##nr(unsigned long syscall SYSCALL_PARM_##nr)       \
0133 {                                   \
0134     register unsigned long r1 asm ("1") = syscall;          \
0135     register long rc asm ("2");                 \
0136     SYSCALL_REGS_##nr;                      \
0137                                     \
0138     asm volatile (                          \
0139         "   svc 0\n"                    \
0140         : "=d" (rc)                     \
0141         : "d" (r1) SYSCALL_FMT_##nr             \
0142         : "memory");                        \
0143     return rc;                          \
0144 }
0145 
0146 GENERATE_SYSCALL_FUNC(0)
0147 GENERATE_SYSCALL_FUNC(1)
0148 GENERATE_SYSCALL_FUNC(2)
0149 GENERATE_SYSCALL_FUNC(3)
0150 GENERATE_SYSCALL_FUNC(4)
0151 GENERATE_SYSCALL_FUNC(5)
0152 GENERATE_SYSCALL_FUNC(6)
0153 
0154 #endif  /* _ASM_SYSCALL_H */