Commit | Line | Data |
---|---|---|
0b73214f | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
753c4dd6 MS |
2 | /* |
3 | * Access to user system call parameters and results | |
4 | * | |
5 | * Copyright IBM Corp. 2008 | |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | |
753c4dd6 MS |
7 | */ |
8 | ||
9 | #ifndef _ASM_SYSCALL_H | |
10 | #define _ASM_SYSCALL_H 1 | |
11 | ||
579ec9e1 | 12 | #include <uapi/linux/audit.h> |
9bf1226b | 13 | #include <linux/sched.h> |
20b40a79 | 14 | #include <linux/err.h> |
753c4dd6 MS |
15 | #include <asm/ptrace.h> |
16 | ||
56e62a73 SS |
17 | extern const sys_call_ptr_t sys_call_table[]; |
18 | extern const sys_call_ptr_t sys_call_table_emu[]; | |
e7b8e675 | 19 | |
753c4dd6 MS |
20 | static inline long syscall_get_nr(struct task_struct *task, |
21 | struct pt_regs *regs) | |
22 | { | |
d3a73acb | 23 | return test_pt_regs_flag(regs, PIF_SYSCALL) ? |
aa33c8cb | 24 | (regs->int_code & 0xffff) : -1; |
753c4dd6 MS |
25 | } |
26 | ||
cc662273 DL |
27 | static inline void syscall_set_nr(struct task_struct *task, |
28 | struct pt_regs *regs, | |
29 | int nr) | |
30 | { | |
31 | /* | |
32 | * Unlike syscall_get_nr(), syscall_set_nr() can be called only when | |
33 | * the target task is stopped for tracing on entering syscall, so | |
34 | * there is no need to have the same check syscall_get_nr() has. | |
35 | */ | |
36 | regs->int_code = (regs->int_code & ~0xffff) | (nr & 0xffff); | |
37 | } | |
38 | ||
753c4dd6 MS |
39 | static inline void syscall_rollback(struct task_struct *task, |
40 | struct pt_regs *regs) | |
41 | { | |
42 | regs->gprs[2] = regs->orig_gpr2; | |
43 | } | |
44 | ||
45 | static inline long syscall_get_error(struct task_struct *task, | |
46 | struct pt_regs *regs) | |
47 | { | |
b3583fca DL |
48 | unsigned long error = regs->gprs[2]; |
49 | #ifdef CONFIG_COMPAT | |
50 | if (test_tsk_thread_flag(task, TIF_31BIT)) { | |
51 | /* | |
52 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO | |
53 | * and will match correctly in comparisons. | |
54 | */ | |
55 | error = (long)(int)error; | |
56 | } | |
57 | #endif | |
58 | return IS_ERR_VALUE(error) ? error : 0; | |
753c4dd6 MS |
59 | } |
60 | ||
61 | static inline long syscall_get_return_value(struct task_struct *task, | |
62 | struct pt_regs *regs) | |
63 | { | |
64 | return regs->gprs[2]; | |
65 | } | |
66 | ||
67 | static inline void syscall_set_return_value(struct task_struct *task, | |
68 | struct pt_regs *regs, | |
69 | int error, long val) | |
70 | { | |
56e62a73 | 71 | set_pt_regs_flag(regs, PIF_SYSCALL_RET_SET); |
dc295880 | 72 | regs->gprs[2] = error ? error : val; |
753c4dd6 MS |
73 | } |
74 | ||
75 | static inline void syscall_get_arguments(struct task_struct *task, | |
76 | struct pt_regs *regs, | |
753c4dd6 MS |
77 | unsigned long *args) |
78 | { | |
59da2139 MS |
79 | unsigned long mask = -1UL; |
80 | ||
753c4dd6 | 81 | #ifdef CONFIG_COMPAT |
59da2139 MS |
82 | if (test_tsk_thread_flag(task, TIF_31BIT)) |
83 | mask = 0xffffffff; | |
753c4dd6 | 84 | #endif |
8751b6e9 SS |
85 | for (int i = 1; i < 6; i++) |
86 | args[i] = regs->gprs[2 + i] & mask; | |
b35f549d SRRH |
87 | |
88 | args[0] = regs->orig_gpr2 & mask; | |
753c4dd6 MS |
89 | } |
90 | ||
17fc7b8f DL |
91 | static inline void syscall_set_arguments(struct task_struct *task, |
92 | struct pt_regs *regs, | |
93 | const unsigned long *args) | |
94 | { | |
95 | regs->orig_gpr2 = args[0]; | |
96 | for (int n = 1; n < 6; n++) | |
97 | regs->gprs[2 + n] = args[n]; | |
98 | } | |
99 | ||
16add411 | 100 | static inline int syscall_get_arch(struct task_struct *task) |
c63cb468 HC |
101 | { |
102 | #ifdef CONFIG_COMPAT | |
16add411 | 103 | if (test_tsk_thread_flag(task, TIF_31BIT)) |
c63cb468 HC |
104 | return AUDIT_ARCH_S390; |
105 | #endif | |
1a327ffd | 106 | return AUDIT_ARCH_S390X; |
c63cb468 | 107 | } |
56e62a73 SS |
108 | |
109 | static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs) | |
110 | { | |
111 | return false; | |
112 | } | |
113 | ||
91f05c27 HC |
114 | #define SYSCALL_FMT_0 |
115 | #define SYSCALL_FMT_1 , "0" (r2) | |
116 | #define SYSCALL_FMT_2 , "d" (r3) SYSCALL_FMT_1 | |
117 | #define SYSCALL_FMT_3 , "d" (r4) SYSCALL_FMT_2 | |
118 | #define SYSCALL_FMT_4 , "d" (r5) SYSCALL_FMT_3 | |
119 | #define SYSCALL_FMT_5 , "d" (r6) SYSCALL_FMT_4 | |
120 | #define SYSCALL_FMT_6 , "d" (r7) SYSCALL_FMT_5 | |
121 | ||
122 | #define SYSCALL_PARM_0 | |
123 | #define SYSCALL_PARM_1 , long arg1 | |
124 | #define SYSCALL_PARM_2 SYSCALL_PARM_1, long arg2 | |
125 | #define SYSCALL_PARM_3 SYSCALL_PARM_2, long arg3 | |
126 | #define SYSCALL_PARM_4 SYSCALL_PARM_3, long arg4 | |
127 | #define SYSCALL_PARM_5 SYSCALL_PARM_4, long arg5 | |
128 | #define SYSCALL_PARM_6 SYSCALL_PARM_5, long arg6 | |
129 | ||
130 | #define SYSCALL_REGS_0 | |
131 | #define SYSCALL_REGS_1 \ | |
132 | register long r2 asm("2") = arg1 | |
133 | #define SYSCALL_REGS_2 \ | |
134 | SYSCALL_REGS_1; \ | |
135 | register long r3 asm("3") = arg2 | |
136 | #define SYSCALL_REGS_3 \ | |
137 | SYSCALL_REGS_2; \ | |
138 | register long r4 asm("4") = arg3 | |
139 | #define SYSCALL_REGS_4 \ | |
140 | SYSCALL_REGS_3; \ | |
141 | register long r5 asm("5") = arg4 | |
142 | #define SYSCALL_REGS_5 \ | |
143 | SYSCALL_REGS_4; \ | |
144 | register long r6 asm("6") = arg5 | |
145 | #define SYSCALL_REGS_6 \ | |
146 | SYSCALL_REGS_5; \ | |
147 | register long r7 asm("7") = arg6 | |
148 | ||
149 | #define GENERATE_SYSCALL_FUNC(nr) \ | |
150 | static __always_inline \ | |
151 | long syscall##nr(unsigned long syscall SYSCALL_PARM_##nr) \ | |
152 | { \ | |
153 | register unsigned long r1 asm ("1") = syscall; \ | |
154 | register long rc asm ("2"); \ | |
155 | SYSCALL_REGS_##nr; \ | |
156 | \ | |
157 | asm volatile ( \ | |
158 | " svc 0\n" \ | |
159 | : "=d" (rc) \ | |
160 | : "d" (r1) SYSCALL_FMT_##nr \ | |
161 | : "memory"); \ | |
162 | return rc; \ | |
163 | } | |
164 | ||
165 | GENERATE_SYSCALL_FUNC(0) | |
166 | GENERATE_SYSCALL_FUNC(1) | |
167 | GENERATE_SYSCALL_FUNC(2) | |
168 | GENERATE_SYSCALL_FUNC(3) | |
169 | GENERATE_SYSCALL_FUNC(4) | |
170 | GENERATE_SYSCALL_FUNC(5) | |
171 | GENERATE_SYSCALL_FUNC(6) | |
172 | ||
753c4dd6 | 173 | #endif /* _ASM_SYSCALL_H */ |