xref: /linux/tools/include/nolibc/arch-aarch64.h (revision 395b15778e8f1b580334c558c9a6e9f1b28fcc76)
1271661c1SWilly Tarreau /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2271661c1SWilly Tarreau /*
3271661c1SWilly Tarreau  * AARCH64 specific definitions for NOLIBC
4271661c1SWilly Tarreau  * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
5271661c1SWilly Tarreau  */
6271661c1SWilly Tarreau 
7271661c1SWilly Tarreau #ifndef _NOLIBC_ARCH_AARCH64_H
8271661c1SWilly Tarreau #define _NOLIBC_ARCH_AARCH64_H
9271661c1SWilly Tarreau 
10818924d1SThomas Weißschuh #include "compiler.h"
11ded8af47SZhangjin Wu #include "crt.h"
12818924d1SThomas Weißschuh 
13271661c1SWilly Tarreau /* Syscalls for AARCH64 :
14271661c1SWilly Tarreau  *   - registers are 64-bit
15271661c1SWilly Tarreau  *   - stack is 16-byte aligned
16271661c1SWilly Tarreau  *   - syscall number is passed in x8
17271661c1SWilly Tarreau  *   - arguments are in x0, x1, x2, x3, x4, x5
18271661c1SWilly Tarreau  *   - the system call is performed by calling svc 0
19271661c1SWilly Tarreau  *   - syscall return comes in x0.
20271661c1SWilly Tarreau  *   - the arguments are cast to long and assigned into the target registers
21271661c1SWilly Tarreau  *     which are then simply passed as registers to the asm code, so that we
22271661c1SWilly Tarreau  *     don't have to experience issues with register constraints.
23271661c1SWilly Tarreau  */
24271661c1SWilly Tarreau 
25271661c1SWilly Tarreau #define my_syscall0(num)                                                      \
26271661c1SWilly Tarreau ({                                                                            \
2737d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
2837d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0");                                   \
29271661c1SWilly Tarreau 									      \
3037d62758SAmmar Faizi 	__asm__ volatile (                                                    \
31271661c1SWilly Tarreau 		"svc #0\n"                                                    \
32271661c1SWilly Tarreau 		: "=r"(_arg1)                                                 \
33271661c1SWilly Tarreau 		: "r"(_num)                                                   \
34271661c1SWilly Tarreau 		: "memory", "cc"                                              \
35271661c1SWilly Tarreau 	);                                                                    \
36271661c1SWilly Tarreau 	_arg1;                                                                \
37271661c1SWilly Tarreau })
38271661c1SWilly Tarreau 
39271661c1SWilly Tarreau #define my_syscall1(num, arg1)                                                \
40271661c1SWilly Tarreau ({                                                                            \
4137d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
4237d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
43271661c1SWilly Tarreau 									      \
4437d62758SAmmar Faizi 	__asm__ volatile (                                                    \
45271661c1SWilly Tarreau 		"svc #0\n"                                                    \
46271661c1SWilly Tarreau 		: "=r"(_arg1)                                                 \
47271661c1SWilly Tarreau 		: "r"(_arg1),                                                 \
48271661c1SWilly Tarreau 		  "r"(_num)                                                   \
49271661c1SWilly Tarreau 		: "memory", "cc"                                              \
50271661c1SWilly Tarreau 	);                                                                    \
51271661c1SWilly Tarreau 	_arg1;                                                                \
52271661c1SWilly Tarreau })
53271661c1SWilly Tarreau 
54271661c1SWilly Tarreau #define my_syscall2(num, arg1, arg2)                                          \
55271661c1SWilly Tarreau ({                                                                            \
5637d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
5737d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
5837d62758SAmmar Faizi 	register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
59271661c1SWilly Tarreau 									      \
6037d62758SAmmar Faizi 	__asm__ volatile (                                                    \
61271661c1SWilly Tarreau 		"svc #0\n"                                                    \
62271661c1SWilly Tarreau 		: "=r"(_arg1)                                                 \
63271661c1SWilly Tarreau 		: "r"(_arg1), "r"(_arg2),                                     \
64271661c1SWilly Tarreau 		  "r"(_num)                                                   \
65271661c1SWilly Tarreau 		: "memory", "cc"                                              \
66271661c1SWilly Tarreau 	);                                                                    \
67271661c1SWilly Tarreau 	_arg1;                                                                \
68271661c1SWilly Tarreau })
69271661c1SWilly Tarreau 
70271661c1SWilly Tarreau #define my_syscall3(num, arg1, arg2, arg3)                                    \
71271661c1SWilly Tarreau ({                                                                            \
7237d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
7337d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
7437d62758SAmmar Faizi 	register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
7537d62758SAmmar Faizi 	register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
76271661c1SWilly Tarreau 									      \
7737d62758SAmmar Faizi 	__asm__ volatile (                                                    \
78271661c1SWilly Tarreau 		"svc #0\n"                                                    \
79271661c1SWilly Tarreau 		: "=r"(_arg1)                                                 \
80271661c1SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
81271661c1SWilly Tarreau 		  "r"(_num)                                                   \
82271661c1SWilly Tarreau 		: "memory", "cc"                                              \
83271661c1SWilly Tarreau 	);                                                                    \
84271661c1SWilly Tarreau 	_arg1;                                                                \
85271661c1SWilly Tarreau })
86271661c1SWilly Tarreau 
87271661c1SWilly Tarreau #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
88271661c1SWilly Tarreau ({                                                                            \
8937d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
9037d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
9137d62758SAmmar Faizi 	register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
9237d62758SAmmar Faizi 	register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
9337d62758SAmmar Faizi 	register long _arg4 __asm__ ("x3") = (long)(arg4);                    \
94271661c1SWilly Tarreau 									      \
9537d62758SAmmar Faizi 	__asm__ volatile (                                                    \
96271661c1SWilly Tarreau 		"svc #0\n"                                                    \
97271661c1SWilly Tarreau 		: "=r"(_arg1)                                                 \
98271661c1SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
99271661c1SWilly Tarreau 		  "r"(_num)                                                   \
100271661c1SWilly Tarreau 		: "memory", "cc"                                              \
101271661c1SWilly Tarreau 	);                                                                    \
102271661c1SWilly Tarreau 	_arg1;                                                                \
103271661c1SWilly Tarreau })
104271661c1SWilly Tarreau 
105271661c1SWilly Tarreau #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
106271661c1SWilly Tarreau ({                                                                            \
10737d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
10837d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
10937d62758SAmmar Faizi 	register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
11037d62758SAmmar Faizi 	register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
11137d62758SAmmar Faizi 	register long _arg4 __asm__ ("x3") = (long)(arg4);                    \
11237d62758SAmmar Faizi 	register long _arg5 __asm__ ("x4") = (long)(arg5);                    \
113271661c1SWilly Tarreau 									      \
11437d62758SAmmar Faizi 	__asm__ volatile (                                                    \
115271661c1SWilly Tarreau 		"svc #0\n"                                                    \
116271661c1SWilly Tarreau 		: "=r" (_arg1)                                                \
117271661c1SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
118271661c1SWilly Tarreau 		  "r"(_num)                                                   \
119271661c1SWilly Tarreau 		: "memory", "cc"                                              \
120271661c1SWilly Tarreau 	);                                                                    \
121271661c1SWilly Tarreau 	_arg1;                                                                \
122271661c1SWilly Tarreau })
123271661c1SWilly Tarreau 
124271661c1SWilly Tarreau #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
125271661c1SWilly Tarreau ({                                                                            \
12637d62758SAmmar Faizi 	register long _num  __asm__ ("x8") = (num);                           \
12737d62758SAmmar Faizi 	register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
12837d62758SAmmar Faizi 	register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
12937d62758SAmmar Faizi 	register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
13037d62758SAmmar Faizi 	register long _arg4 __asm__ ("x3") = (long)(arg4);                    \
13137d62758SAmmar Faizi 	register long _arg5 __asm__ ("x4") = (long)(arg5);                    \
13237d62758SAmmar Faizi 	register long _arg6 __asm__ ("x5") = (long)(arg6);                    \
133271661c1SWilly Tarreau 									      \
13437d62758SAmmar Faizi 	__asm__ volatile (                                                    \
135271661c1SWilly Tarreau 		"svc #0\n"                                                    \
136271661c1SWilly Tarreau 		: "=r" (_arg1)                                                \
137271661c1SWilly Tarreau 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
138271661c1SWilly Tarreau 		  "r"(_arg6), "r"(_num)                                       \
139271661c1SWilly Tarreau 		: "memory", "cc"                                              \
140271661c1SWilly Tarreau 	);                                                                    \
141271661c1SWilly Tarreau 	_arg1;                                                                \
142271661c1SWilly Tarreau })
143271661c1SWilly Tarreau 
144271661c1SWilly Tarreau /* startup code */
145*ef32e9b6SThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
1467f854858SWilly Tarreau {
1477f854858SWilly Tarreau 	__asm__ volatile (
148ded8af47SZhangjin Wu 		"mov x0, sp\n"          /* save stack pointer to x0, as arg1 of _start_c */
149ded8af47SZhangjin Wu 		"and sp, x0, -16\n"     /* sp must be 16-byte aligned in the callee      */
150ded8af47SZhangjin Wu 		"bl  _start_c\n"        /* transfer to c runtime                         */
1517f854858SWilly Tarreau 	);
152*ef32e9b6SThomas Weißschuh 	__nolibc_entrypoint_epilogue();
1537f854858SWilly Tarreau }
154fddc8f81SThomas Weißschuh #endif /* _NOLIBC_ARCH_AARCH64_H */
155