Created
October 19, 2021 01:24
-
-
Save paranlee/23ae512aa68bc162691a7c9e79a1174d to your computer and use it in GitHub Desktop.
from kernel to user syscall `open()` syscall in linux kernel 5.14.13 on arm64 and riscv.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* https://elixir.bootlin.com/linux/v5.14.13/source/fs/open.c#L1224 */ | |
| SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) | |
| { | |
| if (force_o_largefile()) | |
| flags |= O_LARGEFILE; | |
| return do_sys_open(AT_FDCWD, filename, flags, mode); | |
| } | |
| #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) | |
| /* /include/linux/syscalls.h */ | |
| #ifdef CONFIG_FTRACE_SYSCALLS | |
| #define SYSCALL_DEFINEx(x, sname, ...) \ | |
| static const char *types_##sname[] = { \ | |
| __SC_STR_TDECL##x(__VA_ARGS__) \ | |
| }; \ | |
| static const char *args_##sname[] = { \ | |
| __SC_STR_ADECL##x(__VA_ARGS__) \ | |
| }; \ | |
| SYSCALL_METADATA(sname, x); \ | |
| __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) | |
| #else | |
| #define SYSCALL_DEFINEx(x, sname, ...) \ | |
| __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) | |
| #endif | |
| /* /include/linux/syscalls.h */ | |
| #define __SYSCALL_DEFINEx(x, name, ...) \ | |
| asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__)); \ | |
| static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__)); \ | |
| asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__)) \ | |
| { \ | |
| __SC_TEST##x(__VA_ARGS__); \ | |
| return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__)); \ | |
| } \ | |
| SYSCALL_ALIAS(sys##name, SyS##name); \ | |
| static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__)) | |
| /* https://elixir.bootlin.com/linux/latest/source/tools/include/nolibc/nolibc.h#L2114 */ | |
| static __attribute__((unused)) | |
| int open(const char *path, int flags, mode_t mode) | |
| { | |
| int ret = sys_open(path, flags, mode); | |
| if (ret < 0) { | |
| SET_ERRNO(-ret); | |
| ret = -1; | |
| } | |
| return ret; | |
| } | |
| /* https://elixir.bootlin.com/linux/latest/source/tools/include/nolibc/nolibc.h#L1625 */ | |
| static __attribute__((unused)) | |
| int sys_open(const char *path, int flags, mode_t mode) | |
| { | |
| #ifdef __NR_openat | |
| return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); | |
| #elif defined(__NR_open) | |
| return my_syscall3(__NR_open, path, flags, mode); | |
| #else | |
| #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open() | |
| #endif | |
| } | |
| /* arm64 */ | |
| #define my_syscall3(num, arg1, arg2, arg3) \ | |
| ({ \ | |
| register long _num asm("x8") = (num); \ | |
| register long _arg1 asm("x0") = (long)(arg1); \ | |
| register long _arg2 asm("x1") = (long)(arg2); \ | |
| register long _arg3 asm("x2") = (long)(arg3); \ | |
| \ | |
| asm volatile ( \ | |
| "svc #0\n" \ | |
| : "=r"(_arg1) \ | |
| : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ | |
| "r"(_num) \ | |
| : "memory", "cc" \ | |
| ); \ | |
| _arg1; \ | |
| }) | |
| #define my_syscall4(num, arg1, arg2, arg3, arg4) \ | |
| ({ \ | |
| register long _num asm("x8") = (num); \ | |
| register long _arg1 asm("x0") = (long)(arg1); \ | |
| register long _arg2 asm("x1") = (long)(arg2); \ | |
| register long _arg3 asm("x2") = (long)(arg3); \ | |
| register long _arg4 asm("x3") = (long)(arg4); \ | |
| \ | |
| asm volatile ( \ | |
| "svc #0\n" \ | |
| : "=r"(_arg1) \ | |
| : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ | |
| "r"(_num) \ | |
| : "memory", "cc" \ | |
| ); \ | |
| _arg1; \ | |
| }) | |
| /* Syscalls for AARCH64 : | |
| * - registers are 64-bit | |
| * - stack is 16-byte aligned | |
| * - syscall number is passed in x8 | |
| * - arguments are in x0, x1, x2, x3, x4, x5 | |
| * - the system call is performed by calling svc 0 | |
| * - syscall return comes in x0. | |
| * - the arguments are cast to long and assigned into the target registers | |
| * which are then simply passed as registers to the asm code, so that we | |
| * don't have to experience issues with register constraints. | |
| * | |
| * On aarch64, select() is not implemented so we have to use pselect6(). | |
| */ | |
| /* riscv */ | |
| #if __riscv_xlen == 64 | |
| #define PTRLOG "3" | |
| #define SZREG "8" | |
| #elif __riscv_xlen == 32 | |
| #define PTRLOG "2" | |
| #define SZREG "4" | |
| #endif | |
| /* Syscalls for RISCV : | |
| * - stack is 16-byte aligned | |
| * - syscall number is passed in a7 | |
| * - arguments are in a0, a1, a2, a3, a4, a5 | |
| * - the system call is performed by calling ecall | |
| * - syscall return comes in a0 | |
| * - the arguments are cast to long and assigned into the target | |
| * registers which are then simply passed as registers to the asm code, | |
| * so that we don't have to experience issues with register constraints. | |
| */ | |
| /* https://elixir.bootlin.com/linux/latest/source/tools/include/nolibc/nolibc.h#L1288 */ | |
| #define my_syscall3(num, arg1, arg2, arg3) \ | |
| ({ \ | |
| register long _num asm("a7") = (num); \ | |
| register long _arg1 asm("a0") = (long)(arg1); \ | |
| register long _arg2 asm("a1") = (long)(arg2); \ | |
| register long _arg3 asm("a2") = (long)(arg3); \ | |
| \ | |
| asm volatile ( \ | |
| "ecall\n\t" \ | |
| : "+r"(_arg1) \ | |
| : "r"(_arg2), "r"(_arg3), \ | |
| "r"(_num) \ | |
| : "memory", "cc" \ | |
| ); \ | |
| _arg1; \ | |
| }) | |
| #define my_syscall4(num, arg1, arg2, arg3, arg4) \ | |
| ({ \ | |
| register long _num asm("a7") = (num); \ | |
| register long _arg1 asm("a0") = (long)(arg1); \ | |
| register long _arg2 asm("a1") = (long)(arg2); \ | |
| register long _arg3 asm("a2") = (long)(arg3); \ | |
| register long _arg4 asm("a3") = (long)(arg4); \ | |
| \ | |
| asm volatile ( \ | |
| "ecall\n" \ | |
| : "+r"(_arg1) \ | |
| : "r"(_arg2), "r"(_arg3), "r"(_arg4), \ | |
| "r"(_num) \ | |
| : "memory", "cc" \ | |
| ); \ | |
| _arg1; \ | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment