1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* 2 /* 3 * AARCH64 specific definitions for NOLIBC 3 * AARCH64 specific definitions for NOLIBC 4 * Copyright (C) 2017-2022 Willy Tarreau <w@1w 4 * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu> 5 */ 5 */ 6 6 7 #ifndef _NOLIBC_ARCH_AARCH64_H 7 #ifndef _NOLIBC_ARCH_AARCH64_H 8 #define _NOLIBC_ARCH_AARCH64_H 8 #define _NOLIBC_ARCH_AARCH64_H 9 9 10 #include "compiler.h" !! 10 /* O_* macros for fcntl/open are architecture-specific */ 11 #include "crt.h" !! 11 #define O_RDONLY 0 >> 12 #define O_WRONLY 1 >> 13 #define O_RDWR 2 >> 14 #define O_CREAT 0x40 >> 15 #define O_EXCL 0x80 >> 16 #define O_NOCTTY 0x100 >> 17 #define O_TRUNC 0x200 >> 18 #define O_APPEND 0x400 >> 19 #define O_NONBLOCK 0x800 >> 20 #define O_DIRECTORY 0x4000 >> 21 >> 22 /* The struct returned by the newfstatat() syscall. Differs slightly from the >> 23 * x86_64's stat one by field ordering, so be careful. >> 24 */ >> 25 struct sys_stat_struct { >> 26 unsigned long st_dev; >> 27 unsigned long st_ino; >> 28 unsigned int st_mode; >> 29 unsigned int st_nlink; >> 30 unsigned int st_uid; >> 31 unsigned int st_gid; >> 32 >> 33 unsigned long st_rdev; >> 34 unsigned long __pad1; >> 35 long st_size; >> 36 int st_blksize; >> 37 int __pad2; >> 38 >> 39 long st_blocks; >> 40 long st_atime; >> 41 unsigned long st_atime_nsec; >> 42 long st_mtime; >> 43 >> 44 unsigned long st_mtime_nsec; >> 45 long st_ctime; >> 46 unsigned long st_ctime_nsec; >> 47 unsigned int __unused[2]; >> 48 }; 12 49 13 /* Syscalls for AARCH64 : 50 /* Syscalls for AARCH64 : 14 * - registers are 64-bit 51 * - registers are 64-bit 15 * - stack is 16-byte aligned 52 * - stack is 16-byte aligned 16 * - syscall number is passed in x8 53 * - syscall number is passed in x8 17 * - arguments are in x0, x1, x2, x3, x4, x5 54 * - arguments are in x0, x1, x2, x3, x4, x5 18 * - the system call is performed by calling 55 * - the system call is performed by calling svc 0 19 * - syscall return comes in x0. 56 * - syscall return comes in x0. 20 * - the arguments are cast to long and assi 57 * - the arguments are cast to long and assigned into the target registers 21 * which are then simply passed as registe 58 * which are then simply passed as registers to the asm code, so that we 22 * don't have to experience issues with re 59 * don't have to experience issues with register constraints. >> 60 * >> 61 * On aarch64, select() is not implemented so we have to use pselect6(). 23 */ 62 */ >> 63 #define __ARCH_WANT_SYS_PSELECT6 24 64 25 #define my_syscall0(num) 65 #define my_syscall0(num) \ 26 ({ 66 ({ \ 27 register long _num __asm__ ("x8") = ( 67 register long _num __asm__ ("x8") = (num); \ 28 register long _arg1 __asm__ ("x0"); 68 register long _arg1 __asm__ ("x0"); \ 29 !! 69 \ 30 __asm__ volatile ( !! 70 __asm__ volatile ( \ 31 "svc #0\n" 71 "svc #0\n" \ 32 : "=r"(_arg1) 72 : "=r"(_arg1) \ 33 : "r"(_num) 73 : "r"(_num) \ 34 : "memory", "cc" 74 : "memory", "cc" \ 35 ); 75 ); \ 36 _arg1; 76 _arg1; \ 37 }) 77 }) 38 78 39 #define my_syscall1(num, arg1) 79 #define my_syscall1(num, arg1) \ 40 ({ 80 ({ \ 41 register long _num __asm__ ("x8") = ( 81 register long _num __asm__ ("x8") = (num); \ 42 register long _arg1 __asm__ ("x0") = ( 82 register long _arg1 __asm__ ("x0") = (long)(arg1); \ 43 !! 83 \ 44 __asm__ volatile ( !! 84 __asm__ volatile ( \ 45 "svc #0\n" 85 "svc #0\n" \ 46 : "=r"(_arg1) 86 : "=r"(_arg1) \ 47 : "r"(_arg1), 87 : "r"(_arg1), \ 48 "r"(_num) 88 "r"(_num) \ 49 : "memory", "cc" 89 : "memory", "cc" \ 50 ); 90 ); \ 51 _arg1; 91 _arg1; \ 52 }) 92 }) 53 93 54 #define my_syscall2(num, arg1, arg2) 94 #define my_syscall2(num, arg1, arg2) \ 55 ({ 95 ({ \ 56 register long _num __asm__ ("x8") = ( 96 register long _num __asm__ ("x8") = (num); \ 57 register long _arg1 __asm__ ("x0") = ( 97 register long _arg1 __asm__ ("x0") = (long)(arg1); \ 58 register long _arg2 __asm__ ("x1") = ( 98 register long _arg2 __asm__ ("x1") = (long)(arg2); \ 59 !! 99 \ 60 __asm__ volatile ( !! 100 __asm__ volatile ( \ 61 "svc #0\n" 101 "svc #0\n" \ 62 : "=r"(_arg1) 102 : "=r"(_arg1) \ 63 : "r"(_arg1), "r"(_arg2), 103 : "r"(_arg1), "r"(_arg2), \ 64 "r"(_num) 104 "r"(_num) \ 65 : "memory", "cc" 105 : "memory", "cc" \ 66 ); 106 ); \ 67 _arg1; 107 _arg1; \ 68 }) 108 }) 69 109 70 #define my_syscall3(num, arg1, arg2, arg3) 110 #define my_syscall3(num, arg1, arg2, arg3) \ 71 ({ 111 ({ \ 72 register long _num __asm__ ("x8") = ( 112 register long _num __asm__ ("x8") = (num); \ 73 register long _arg1 __asm__ ("x0") = ( 113 register long _arg1 __asm__ ("x0") = (long)(arg1); \ 74 register long _arg2 __asm__ ("x1") = ( 114 register long _arg2 __asm__ ("x1") = (long)(arg2); \ 75 register long _arg3 __asm__ ("x2") = ( 115 register long _arg3 __asm__ ("x2") = (long)(arg3); \ 76 !! 116 \ 77 __asm__ volatile ( !! 117 __asm__ volatile ( \ 78 "svc #0\n" 118 "svc #0\n" \ 79 : "=r"(_arg1) 119 : "=r"(_arg1) \ 80 : "r"(_arg1), "r"(_arg2), "r"( 120 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 81 "r"(_num) 121 "r"(_num) \ 82 : "memory", "cc" 122 : "memory", "cc" \ 83 ); 123 ); \ 84 _arg1; 124 _arg1; \ 85 }) 125 }) 86 126 87 #define my_syscall4(num, arg1, arg2, arg3, arg 127 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 88 ({ 128 ({ \ 89 register long _num __asm__ ("x8") = ( 129 register long _num __asm__ ("x8") = (num); \ 90 register long _arg1 __asm__ ("x0") = ( 130 register long _arg1 __asm__ ("x0") = (long)(arg1); \ 91 register long _arg2 __asm__ ("x1") = ( 131 register long _arg2 __asm__ ("x1") = (long)(arg2); \ 92 register long _arg3 __asm__ ("x2") = ( 132 register long _arg3 __asm__ ("x2") = (long)(arg3); \ 93 register long _arg4 __asm__ ("x3") = ( 133 register long _arg4 __asm__ ("x3") = (long)(arg4); \ 94 !! 134 \ 95 __asm__ volatile ( !! 135 __asm__ volatile ( \ 96 "svc #0\n" 136 "svc #0\n" \ 97 : "=r"(_arg1) 137 : "=r"(_arg1) \ 98 : "r"(_arg1), "r"(_arg2), "r"( 138 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 99 "r"(_num) 139 "r"(_num) \ 100 : "memory", "cc" 140 : "memory", "cc" \ 101 ); 141 ); \ 102 _arg1; 142 _arg1; \ 103 }) 143 }) 104 144 105 #define my_syscall5(num, arg1, arg2, arg3, arg 145 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 106 ({ 146 ({ \ 107 register long _num __asm__ ("x8") = ( 147 register long _num __asm__ ("x8") = (num); \ 108 register long _arg1 __asm__ ("x0") = ( 148 register long _arg1 __asm__ ("x0") = (long)(arg1); \ 109 register long _arg2 __asm__ ("x1") = ( 149 register long _arg2 __asm__ ("x1") = (long)(arg2); \ 110 register long _arg3 __asm__ ("x2") = ( 150 register long _arg3 __asm__ ("x2") = (long)(arg3); \ 111 register long _arg4 __asm__ ("x3") = ( 151 register long _arg4 __asm__ ("x3") = (long)(arg4); \ 112 register long _arg5 __asm__ ("x4") = ( 152 register long _arg5 __asm__ ("x4") = (long)(arg5); \ 113 !! 153 \ 114 __asm__ volatile ( !! 154 __asm__ volatile ( \ 115 "svc #0\n" 155 "svc #0\n" \ 116 : "=r" (_arg1) 156 : "=r" (_arg1) \ 117 : "r"(_arg1), "r"(_arg2), "r"( 157 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 118 "r"(_num) 158 "r"(_num) \ 119 : "memory", "cc" 159 : "memory", "cc" \ 120 ); 160 ); \ 121 _arg1; 161 _arg1; \ 122 }) 162 }) 123 163 124 #define my_syscall6(num, arg1, arg2, arg3, arg 164 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 125 ({ 165 ({ \ 126 register long _num __asm__ ("x8") = ( 166 register long _num __asm__ ("x8") = (num); \ 127 register long _arg1 __asm__ ("x0") = ( 167 register long _arg1 __asm__ ("x0") = (long)(arg1); \ 128 register long _arg2 __asm__ ("x1") = ( 168 register long _arg2 __asm__ ("x1") = (long)(arg2); \ 129 register long _arg3 __asm__ ("x2") = ( 169 register long _arg3 __asm__ ("x2") = (long)(arg3); \ 130 register long _arg4 __asm__ ("x3") = ( 170 register long _arg4 __asm__ ("x3") = (long)(arg4); \ 131 register long _arg5 __asm__ ("x4") = ( 171 register long _arg5 __asm__ ("x4") = (long)(arg5); \ 132 register long _arg6 __asm__ ("x5") = ( 172 register long _arg6 __asm__ ("x5") = (long)(arg6); \ 133 !! 173 \ 134 __asm__ volatile ( !! 174 __asm__ volatile ( \ 135 "svc #0\n" 175 "svc #0\n" \ 136 : "=r" (_arg1) 176 : "=r" (_arg1) \ 137 : "r"(_arg1), "r"(_arg2), "r"( 177 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 138 "r"(_arg6), "r"(_num) 178 "r"(_arg6), "r"(_num) \ 139 : "memory", "cc" 179 : "memory", "cc" \ 140 ); 180 ); \ 141 _arg1; 181 _arg1; \ 142 }) 182 }) 143 183 144 /* startup code */ 184 /* startup code */ 145 void __attribute__((weak, noreturn)) __nolibc_ !! 185 __asm__ (".section .text\n" 146 { !! 186 ".weak _start\n" 147 __asm__ volatile ( !! 187 "_start:\n" 148 "mov x0, sp\n" /* sav !! 188 "ldr x0, [sp]\n" // argc (x0) was in the stack 149 "and sp, x0, -16\n" /* sp !! 189 "add x1, sp, 8\n" // argv (x1) = sp 150 "bl _start_c\n" /* tra !! 190 "lsl x2, x0, 3\n" // envp (x2) = 8*argc ... 151 ); !! 191 "add x2, x2, 8\n" // + 8 (skip null) 152 __nolibc_entrypoint_epilogue(); !! 192 "add x2, x2, x1\n" // + argv 153 } !! 193 "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee 154 #endif /* _NOLIBC_ARCH_AARCH64_H */ !! 194 "bl main\n" // main() returns the status code, we'll exit with it. >> 195 "mov x8, 93\n" // NR_exit == 93 >> 196 "svc #0\n" >> 197 ""); >> 198 >> 199 #endif // _NOLIBC_ARCH_AARCH64_H 155 200
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.