aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/include/asm/syscall_wrapper.h
blob: ad2c996e7e93dda9e7560256f6d825d15b3d87d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * syscall_wrapper.h - s390 specific wrappers to syscall definitions
 *
 */

#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

#define __SC_COMPAT_CAST(t, a)						\
({									\
	long __ReS = a;							\
									\
	BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&		\
		     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&		\
		     !__TYPE_IS_LL(t));					\
	if (__TYPE_IS_L(t))						\
		__ReS = (s32)a;						\
	if (__TYPE_IS_UL(t))						\
		__ReS = (u32)a;						\
	if (__TYPE_IS_PTR(t))						\
		__ReS = a & 0x7fffffff;					\
	if (__TYPE_IS_LL(t))						\
		return -ENOSYS;						\
	(t)__ReS;							\
})

#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;							\
	}

/*
 * To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias
 * named __s390x_sys_*()
 */
#define COMPAT_SYSCALL_DEFINE0(sname)					\
	SYSCALL_METADATA(_##sname, 0);					\
	long __s390_compat_sys_##sname(void);				\
	ALLOW_ERROR_INJECTION(__s390_compat_sys_##sname, ERRNO);	\
	long __s390_compat_sys_##sname(void)

#define SYSCALL_DEFINE0(sname)						\
	SYSCALL_METADATA(_##sname, 0);					\
	long __s390x_sys_##sname(void);					\
	ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO);		\
	long __s390_sys_##sname(void)					\
		__attribute__((alias(__stringify(__s390x_sys_##sname)))); \
	long __s390x_sys_##sname(void)

#define COND_SYSCALL(name)						\
	cond_syscall(__s390x_sys_##name);				\
	cond_syscall(__s390_sys_##name)

#define SYS_NI(name)							\
	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(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__))

/*
 * As some compat syscalls may not be implemented, we need to expand
 * COND_SYSCALL_COMPAT in kernel/sys_ni.c and COMPAT_SYS_NI in
 * kernel/time/posix-stubs.c to cover this case as well.
 */
#define COND_SYSCALL_COMPAT(name)					\
	cond_syscall(__s390_compat_sys_##name)

#define COMPAT_SYS_NI(name)						\
	SYSCALL_ALIAS(__s390_compat_sys_##name, sys_ni_posix_timers)

#else /* CONFIG_COMPAT */

#define __S390_SYS_STUBx(x, fullname, name, ...)

#define SYSCALL_DEFINE0(sname)						\
	SYSCALL_METADATA(_##sname, 0);					\
	long __s390x_sys_##sname(void);					\
	ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO);		\
	long __s390x_sys_##sname(void)

#define COND_SYSCALL(name)						\
	cond_syscall(__s390x_sys_##name)

#define SYS_NI(name)							\
	SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers);

#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(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 */