1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Macros for issuing an inline system call from the vDSO. 4 */ 5 6 #ifndef X86_ASM_VDSO_SYS_CALL_H 7 #define X86_ASM_VDSO_SYS_CALL_H 8 9 #include <linux/compiler.h> 10 #include <asm/cpufeatures.h> 11 #include <asm/alternative.h> 12 13 #ifdef CONFIG_X86_64 14 # define __sys_instr "syscall" 15 # define __sys_clobber "rcx", "r11", "memory" 16 # define __sys_nr(x,y) __NR_ ## x 17 # define __sys_reg1 "rdi" 18 # define __sys_reg2 "rsi" 19 # define __sys_reg3 "rdx" 20 # define __sys_reg4 "r10" 21 # define __sys_reg5 "r8" 22 #else 23 # define __sys_instr "call __kernel_vsyscall" 24 # define __sys_clobber "memory" 25 # define __sys_nr(x,y) __NR_ ## x ## y 26 # define __sys_reg1 "ebx" 27 # define __sys_reg2 "ecx" 28 # define __sys_reg3 "edx" 29 # define __sys_reg4 "esi" 30 # define __sys_reg5 "edi" 31 #endif 32 33 /* 34 * Example usage: 35 * 36 * result = VDSO_SYSCALL3(foo,64,x,y,z); 37 * 38 * ... calls foo(x,y,z) on 64 bits, and foo64(x,y,z) on 32 bits. 39 * 40 * VDSO_SYSCALL6() is currently missing, because it would require 41 * special handling for %ebp on 32 bits when the vdso is compiled with 42 * frame pointers enabled (the default on 32 bits.) Add it as a special 43 * case when and if it becomes necessary. 44 */ 45 #define _VDSO_SYSCALL(name,suf32,...) \ 46 ({ \ 47 long _sys_num_ret = __sys_nr(name,suf32); \ 48 asm_inline volatile( \ 49 __sys_instr \ 50 : "+a" (_sys_num_ret) \ 51 : __VA_ARGS__ \ 52 : __sys_clobber); \ 53 _sys_num_ret; \ 54 }) 55 56 #define VDSO_SYSCALL0(name,suf32) \ 57 _VDSO_SYSCALL(name,suf32) 58 #define VDSO_SYSCALL1(name,suf32,a1) \ 59 ({ \ 60 register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \ 61 _VDSO_SYSCALL(name,suf32, \ 62 "r" (_sys_arg1)); \ 63 }) 64 #define VDSO_SYSCALL2(name,suf32,a1,a2) \ 65 ({ \ 66 register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \ 67 register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \ 68 _VDSO_SYSCALL(name,suf32, \ 69 "r" (_sys_arg1), "r" (_sys_arg2)); \ 70 }) 71 #define VDSO_SYSCALL3(name,suf32,a1,a2,a3) \ 72 ({ \ 73 register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \ 74 register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \ 75 register long _sys_arg3 asm(__sys_reg3) = (long)(a3); \ 76 _VDSO_SYSCALL(name,suf32, \ 77 "r" (_sys_arg1), "r" (_sys_arg2), \ 78 "r" (_sys_arg3)); \ 79 }) 80 #define VDSO_SYSCALL4(name,suf32,a1,a2,a3,a4) \ 81 ({ \ 82 register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \ 83 register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \ 84 register long _sys_arg3 asm(__sys_reg3) = (long)(a3); \ 85 register long _sys_arg4 asm(__sys_reg4) = (long)(a4); \ 86 _VDSO_SYSCALL(name,suf32, \ 87 "r" (_sys_arg1), "r" (_sys_arg2), \ 88 "r" (_sys_arg3), "r" (_sys_arg4)); \ 89 }) 90 #define VDSO_SYSCALL5(name,suf32,a1,a2,a3,a4,a5) \ 91 ({ \ 92 register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \ 93 register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \ 94 register long _sys_arg3 asm(__sys_reg3) = (long)(a3); \ 95 register long _sys_arg4 asm(__sys_reg4) = (long)(a4); \ 96 register long _sys_arg5 asm(__sys_reg5) = (long)(a5); \ 97 _VDSO_SYSCALL(name,suf32, \ 98 "r" (_sys_arg1), "r" (_sys_arg2), \ 99 "r" (_sys_arg3), "r" (_sys_arg4), \ 100 "r" (_sys_arg5)); \ 101 }) 102 103 #endif /* X86_VDSO_SYS_CALL_H */ 104