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 /* Mapping of registers to parameters for syscalls */
11 #define SC_S390_REGS_TO_ARGS(x, ...)					\
12 	__MAP(x, __SC_ARGS						\
13 	      ,, regs->orig_gpr2,, regs->gprs[3],, regs->gprs[4]	\
14 	      ,, regs->gprs[5],, regs->gprs[6],, regs->gprs[7])
15 
16 #ifdef CONFIG_COMPAT
17 
18 #define __SC_COMPAT_CAST(t, a)						\
19 ({									\
20 	long __ReS = a;							\
21 									\
22 	BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&		\
23 		     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&		\
24 		     !__TYPE_IS_LL(t));					\
25 	if (__TYPE_IS_L(t))						\
26 		__ReS = (s32)a;						\
27 	if (__TYPE_IS_UL(t))						\
28 		__ReS = (u32)a;						\
29 	if (__TYPE_IS_PTR(t))						\
30 		__ReS = a & 0x7fffffff;					\
31 	if (__TYPE_IS_LL(t))						\
32 		return -ENOSYS;						\
33 	(t)__ReS;							\
34 })
35 
36 /*
37  * To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias
38  * named __s390x_sys_*()
39  */
40 #define COMPAT_SYSCALL_DEFINE0(sname)					\
41 	long __s390_compat_sys_##sname(void);				\
42 	ALLOW_ERROR_INJECTION(__s390_compat_sys_##sname, ERRNO);	\
43 	long __s390_compat_sys_##sname(void)
44 
45 #define SYSCALL_DEFINE0(sname)						\
46 	SYSCALL_METADATA(_##sname, 0);					\
47 	long __s390_sys_##sname(void);					\
48 	ALLOW_ERROR_INJECTION(__s390_sys_##sname, ERRNO);		\
49 	long __s390x_sys_##sname(void);					\
50 	ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO);		\
51 	static inline long __do_sys_##sname(void);			\
52 	long __s390_sys_##sname(void)					\
53 	{								\
54 		return __do_sys_##sname();				\
55 	}								\
56 	long __s390x_sys_##sname(void)					\
57 	{								\
58 		return __do_sys_##sname();				\
59 	}								\
60 	static inline long __do_sys_##sname(void)
61 
62 #define COND_SYSCALL(name)						\
63 	cond_syscall(__s390x_sys_##name);				\
64 	cond_syscall(__s390_sys_##name)
65 
66 #define SYS_NI(name)							\
67 	SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers);		\
68 	SYSCALL_ALIAS(__s390_sys_##name, sys_ni_posix_timers)
69 
70 #define COMPAT_SYSCALL_DEFINEx(x, name, ...)						\
71 	long __s390_compat_sys##name(struct pt_regs *regs);				\
72 	ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO);				\
73 	static inline long __se_compat_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__));	\
74 	static inline long __do_compat_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__));	\
75 	long __s390_compat_sys##name(struct pt_regs *regs)				\
76 	{										\
77 		return __se_compat_sys##name(SC_S390_REGS_TO_ARGS(x, __VA_ARGS__));	\
78 	}										\
79 	static inline long __se_compat_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__))	\
80 	{										\
81 		__MAP(x, __SC_TEST, __VA_ARGS__);					\
82 		return __do_compat_sys##name(__MAP(x, __SC_DELOUSE, __VA_ARGS__));	\
83 	}										\
84 	static inline long __do_compat_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__))
85 
86 /*
87  * As some compat syscalls may not be implemented, we need to expand
88  * COND_SYSCALL_COMPAT in kernel/sys_ni.c and COMPAT_SYS_NI in
89  * kernel/time/posix-stubs.c to cover this case as well.
90  */
91 #define COND_SYSCALL_COMPAT(name)					\
92 	cond_syscall(__s390_compat_sys_##name)
93 
94 #define COMPAT_SYS_NI(name)						\
95 	SYSCALL_ALIAS(__s390_compat_sys_##name, sys_ni_posix_timers)
96 
97 #define __S390_SYS_STUBx(x, name, ...)						\
98 	long __s390_sys##name(struct pt_regs *regs);				\
99 	ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO);				\
100 	static inline long ___se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__));	\
101 	long __s390_sys##name(struct pt_regs *regs)				\
102 	{									\
103 		return ___se_sys##name(SC_S390_REGS_TO_ARGS(x, __VA_ARGS__));	\
104 	}									\
105 	static inline long ___se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__))	\
106 	{									\
107 		__MAP(x, __SC_TEST, __VA_ARGS__);				\
108 		return __do_sys##name(__MAP(x, __SC_COMPAT_CAST, __VA_ARGS__));	\
109 	}
110 
111 #else /* CONFIG_COMPAT */
112 
113 #define SYSCALL_DEFINE0(sname)						\
114 	SYSCALL_METADATA(_##sname, 0);					\
115 	long __s390x_sys_##sname(void);					\
116 	ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO);		\
117 	static inline long __do_sys_##sname(void);			\
118 	long __s390x_sys_##sname(void)					\
119 	{								\
120 		return __do_sys_##sname();				\
121 	}								\
122 	static inline long __do_sys_##sname(void)
123 
124 #define COND_SYSCALL(name)						\
125 	cond_syscall(__s390x_sys_##name)
126 
127 #define SYS_NI(name)							\
128 	SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers)
129 
130 #define __S390_SYS_STUBx(x, fullname, name, ...)
131 
132 #endif /* CONFIG_COMPAT */
133 
134 #define __SYSCALL_DEFINEx(x, name, ...)						\
135 	long __s390x_sys##name(struct pt_regs *regs);				\
136 	ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO);			\
137 	static inline long __se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__));	\
138 	static inline long __do_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__));	\
139 	__S390_SYS_STUBx(x, name, __VA_ARGS__);					\
140 	long __s390x_sys##name(struct pt_regs *regs)				\
141 	{									\
142 		return __se_sys##name(SC_S390_REGS_TO_ARGS(x, __VA_ARGS__));	\
143 	}									\
144 	static inline long __se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__))	\
145 	{									\
146 		__MAP(x, __SC_TEST, __VA_ARGS__);				\
147 		return __do_sys##name(__MAP(x, __SC_CAST, __VA_ARGS__));	\
148 	}									\
149 	static inline long __do_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__))
150 
151 #endif /* _ASM_S390_SYSCALL_WRAPPER_H */
152