1fa697140SDominik Brodowski /* SPDX-License-Identifier: GPL-2.0 */
2fa697140SDominik Brodowski /*
3fa697140SDominik Brodowski  * syscall_wrapper.h - x86 specific wrappers to syscall definitions
4fa697140SDominik Brodowski  */
5fa697140SDominik Brodowski 
6fa697140SDominik Brodowski #ifndef _ASM_X86_SYSCALL_WRAPPER_H
7fa697140SDominik Brodowski #define _ASM_X86_SYSCALL_WRAPPER_H
8fa697140SDominik Brodowski 
9fa697140SDominik Brodowski /*
10fa697140SDominik Brodowski  * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes
11fa697140SDominik Brodowski  * struct pt_regs *regs as the only argument of the syscall stub named
12fa697140SDominik Brodowski  * sys_*(). It decodes just the registers it needs and passes them on to
13fa697140SDominik Brodowski  * the SyS_*() wrapper and then to the SYSC_*() function doing the actual job.
14fa697140SDominik Brodowski  * These wrappers and functions are inlined, meaning that the assembly looks
15fa697140SDominik Brodowski  * as follows (slightly re-ordered):
16fa697140SDominik Brodowski  *
17fa697140SDominik Brodowski  * <sys_recv>:			<-- syscall with 4 parameters
18fa697140SDominik Brodowski  *	callq	<__fentry__>
19fa697140SDominik Brodowski  *
20fa697140SDominik Brodowski  *	mov	0x70(%rdi),%rdi	<-- decode regs->di
21fa697140SDominik Brodowski  *	mov	0x68(%rdi),%rsi	<-- decode regs->si
22fa697140SDominik Brodowski  *	mov	0x60(%rdi),%rdx	<-- decode regs->dx
23fa697140SDominik Brodowski  *	mov	0x38(%rdi),%rcx	<-- decode regs->r10
24fa697140SDominik Brodowski  *
25fa697140SDominik Brodowski  *	xor	%r9d,%r9d	<-- clear %r9
26fa697140SDominik Brodowski  *	xor	%r8d,%r8d	<-- clear %r8
27fa697140SDominik Brodowski  *
28fa697140SDominik Brodowski  *	callq	__sys_recvfrom	<-- do the actual work in __sys_recvfrom()
29fa697140SDominik Brodowski  *				    which takes 6 arguments
30fa697140SDominik Brodowski  *
31fa697140SDominik Brodowski  *	cltq			<-- extend return value to 64-bit
32fa697140SDominik Brodowski  *	retq			<-- return
33fa697140SDominik Brodowski  *
34fa697140SDominik Brodowski  * This approach avoids leaking random user-provided register content down
35fa697140SDominik Brodowski  * the call chain.
36fa697140SDominik Brodowski  *
37fa697140SDominik Brodowski  * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for
38fa697140SDominik Brodowski  * obvious reasons, and passing struct pt_regs *regs to it in %rdi does not
39fa697140SDominik Brodowski  * hurt, there is no need to override it.
40fa697140SDominik Brodowski  */
41fa697140SDominik Brodowski #define __SYSCALL_DEFINEx(x, name, ...)					\
42fa697140SDominik Brodowski 	asmlinkage long sys##name(const struct pt_regs *regs);		\
43fa697140SDominik Brodowski 	ALLOW_ERROR_INJECTION(sys##name, ERRNO);			\
44fa697140SDominik Brodowski 	static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));		\
45fa697140SDominik Brodowski 	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
46fa697140SDominik Brodowski 	asmlinkage long sys##name(const struct pt_regs *regs)		\
47fa697140SDominik Brodowski 	{								\
48fa697140SDominik Brodowski 		return SyS##name(__MAP(x,__SC_ARGS			\
49fa697140SDominik Brodowski 			,,regs->di,,regs->si,,regs->dx			\
50fa697140SDominik Brodowski 			,,regs->r10,,regs->r8,,regs->r9));		\
51fa697140SDominik Brodowski 	}								\
52fa697140SDominik Brodowski 	static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))		\
53fa697140SDominik Brodowski 	{								\
54fa697140SDominik Brodowski 		long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
55fa697140SDominik Brodowski 		__MAP(x,__SC_TEST,__VA_ARGS__);				\
56fa697140SDominik Brodowski 		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
57fa697140SDominik Brodowski 		return ret;						\
58fa697140SDominik Brodowski 	}								\
59fa697140SDominik Brodowski 	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
60fa697140SDominik Brodowski 
61fa697140SDominik Brodowski /*
62fa697140SDominik Brodowski  * For VSYSCALLS, we need to declare these three syscalls with the new
63fa697140SDominik Brodowski  * pt_regs-based calling convention for in-kernel use.
64fa697140SDominik Brodowski  */
65fa697140SDominik Brodowski struct pt_regs;
66fa697140SDominik Brodowski asmlinkage long sys_getcpu(const struct pt_regs *regs);		/* di,si,dx */
67fa697140SDominik Brodowski asmlinkage long sys_gettimeofday(const struct pt_regs *regs);	/* di,si */
68fa697140SDominik Brodowski asmlinkage long sys_time(const struct pt_regs *regs);		/* di */
69fa697140SDominik Brodowski 
70fa697140SDominik Brodowski #endif /* _ASM_X86_SYSCALL_WRAPPER_H */
71