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 COMPAT_SYSCALL_DEFINEx(x, name, ...)						\
67 	long __s390_compat_sys##name(struct pt_regs *regs);				\
68 	ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO);				\
69 	static inline long __se_compat_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__));	\
70 	static inline long __do_compat_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__));	\
71 	long __s390_compat_sys##name(struct pt_regs *regs)				\
72 	{										\
73 		return __se_compat_sys##name(SC_S390_REGS_TO_ARGS(x, __VA_ARGS__));	\
74 	}										\
75 	static inline long __se_compat_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__))	\
76 	{										\
77 		__MAP(x, __SC_TEST, __VA_ARGS__);					\
78 		return __do_compat_sys##name(__MAP(x, __SC_DELOUSE, __VA_ARGS__));	\
79 	}										\
80 	static inline long __do_compat_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__))
81 
82 /*
83  * As some compat syscalls may not be implemented, we need to expand
84  * COND_SYSCALL_COMPAT in kernel/sys_ni.c to cover this case as well.
85  */
86 #define COND_SYSCALL_COMPAT(name)					\
87 	cond_syscall(__s390_compat_sys_##name)
88 
89 #define __S390_SYS_STUBx(x, name, ...)						\
90 	long __s390_sys##name(struct pt_regs *regs);				\
91 	ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO);				\
92 	static inline long ___se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__));	\
93 	long __s390_sys##name(struct pt_regs *regs)				\
94 	{									\
95 		return ___se_sys##name(SC_S390_REGS_TO_ARGS(x, __VA_ARGS__));	\
96 	}									\
97 	static inline long ___se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__))	\
98 	{									\
99 		__MAP(x, __SC_TEST, __VA_ARGS__);				\
100 		return __do_sys##name(__MAP(x, __SC_COMPAT_CAST, __VA_ARGS__));	\
101 	}
102 
103 #else /* CONFIG_COMPAT */
104 
105 #define SYSCALL_DEFINE0(sname)						\
106 	SYSCALL_METADATA(_##sname, 0);					\
107 	long __s390x_sys_##sname(void);					\
108 	ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO);		\
109 	static inline long __do_sys_##sname(void);			\
110 	long __s390x_sys_##sname(void)					\
111 	{								\
112 		return __do_sys_##sname();				\
113 	}								\
114 	static inline long __do_sys_##sname(void)
115 
116 #define COND_SYSCALL(name)						\
117 	cond_syscall(__s390x_sys_##name)
118 
119 #define __S390_SYS_STUBx(x, fullname, name, ...)
120 
121 #endif /* CONFIG_COMPAT */
122 
123 #define __SYSCALL_DEFINEx(x, name, ...)						\
124 	long __s390x_sys##name(struct pt_regs *regs);				\
125 	ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO);			\
126 	static inline long __se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__));	\
127 	static inline long __do_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__));	\
128 	__S390_SYS_STUBx(x, name, __VA_ARGS__);					\
129 	long __s390x_sys##name(struct pt_regs *regs)				\
130 	{									\
131 		return __se_sys##name(SC_S390_REGS_TO_ARGS(x, __VA_ARGS__));	\
132 	}									\
133 	static inline long __se_sys##name(__MAP(x, __SC_LONG, __VA_ARGS__))	\
134 	{									\
135 		__MAP(x, __SC_TEST, __VA_ARGS__);				\
136 		return __do_sys##name(__MAP(x, __SC_CAST, __VA_ARGS__));	\
137 	}									\
138 	static inline long __do_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__))
139 
140 #endif /* _ASM_S390_SYSCALL_WRAPPER_H */
141