1*01e8a6d0SThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2*01e8a6d0SThomas Weißschuh /* 3*01e8a6d0SThomas Weißschuh * ARM64 specific definitions for NOLIBC 4*01e8a6d0SThomas Weißschuh * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu> 5*01e8a6d0SThomas Weißschuh */ 6*01e8a6d0SThomas Weißschuh 7*01e8a6d0SThomas Weißschuh #ifndef _NOLIBC_ARCH_ARM64_H 8*01e8a6d0SThomas Weißschuh #define _NOLIBC_ARCH_ARM64_H 9*01e8a6d0SThomas Weißschuh 10*01e8a6d0SThomas Weißschuh #include "compiler.h" 11*01e8a6d0SThomas Weißschuh #include "crt.h" 12*01e8a6d0SThomas Weißschuh 13*01e8a6d0SThomas Weißschuh /* Syscalls for ARM64 : 14*01e8a6d0SThomas Weißschuh * - registers are 64-bit 15*01e8a6d0SThomas Weißschuh * - stack is 16-byte aligned 16*01e8a6d0SThomas Weißschuh * - syscall number is passed in x8 17*01e8a6d0SThomas Weißschuh * - arguments are in x0, x1, x2, x3, x4, x5 18*01e8a6d0SThomas Weißschuh * - the system call is performed by calling svc 0 19*01e8a6d0SThomas Weißschuh * - syscall return comes in x0. 20*01e8a6d0SThomas Weißschuh * - the arguments are cast to long and assigned into the target registers 21*01e8a6d0SThomas Weißschuh * which are then simply passed as registers to the asm code, so that we 22*01e8a6d0SThomas Weißschuh * don't have to experience issues with register constraints. 23*01e8a6d0SThomas Weißschuh */ 24*01e8a6d0SThomas Weißschuh 25*01e8a6d0SThomas Weißschuh #define my_syscall0(num) \ 26*01e8a6d0SThomas Weißschuh ({ \ 27*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 28*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0"); \ 29*01e8a6d0SThomas Weißschuh \ 30*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 31*01e8a6d0SThomas Weißschuh "svc #0\n" \ 32*01e8a6d0SThomas Weißschuh : "=r"(_arg1) \ 33*01e8a6d0SThomas Weißschuh : "r"(_num) \ 34*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 35*01e8a6d0SThomas Weißschuh ); \ 36*01e8a6d0SThomas Weißschuh _arg1; \ 37*01e8a6d0SThomas Weißschuh }) 38*01e8a6d0SThomas Weißschuh 39*01e8a6d0SThomas Weißschuh #define my_syscall1(num, arg1) \ 40*01e8a6d0SThomas Weißschuh ({ \ 41*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 42*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0") = (long)(arg1); \ 43*01e8a6d0SThomas Weißschuh \ 44*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 45*01e8a6d0SThomas Weißschuh "svc #0\n" \ 46*01e8a6d0SThomas Weißschuh : "=r"(_arg1) \ 47*01e8a6d0SThomas Weißschuh : "r"(_arg1), \ 48*01e8a6d0SThomas Weißschuh "r"(_num) \ 49*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 50*01e8a6d0SThomas Weißschuh ); \ 51*01e8a6d0SThomas Weißschuh _arg1; \ 52*01e8a6d0SThomas Weißschuh }) 53*01e8a6d0SThomas Weißschuh 54*01e8a6d0SThomas Weißschuh #define my_syscall2(num, arg1, arg2) \ 55*01e8a6d0SThomas Weißschuh ({ \ 56*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 57*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0") = (long)(arg1); \ 58*01e8a6d0SThomas Weißschuh register long _arg2 __asm__ ("x1") = (long)(arg2); \ 59*01e8a6d0SThomas Weißschuh \ 60*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 61*01e8a6d0SThomas Weißschuh "svc #0\n" \ 62*01e8a6d0SThomas Weißschuh : "=r"(_arg1) \ 63*01e8a6d0SThomas Weißschuh : "r"(_arg1), "r"(_arg2), \ 64*01e8a6d0SThomas Weißschuh "r"(_num) \ 65*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 66*01e8a6d0SThomas Weißschuh ); \ 67*01e8a6d0SThomas Weißschuh _arg1; \ 68*01e8a6d0SThomas Weißschuh }) 69*01e8a6d0SThomas Weißschuh 70*01e8a6d0SThomas Weißschuh #define my_syscall3(num, arg1, arg2, arg3) \ 71*01e8a6d0SThomas Weißschuh ({ \ 72*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 73*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0") = (long)(arg1); \ 74*01e8a6d0SThomas Weißschuh register long _arg2 __asm__ ("x1") = (long)(arg2); \ 75*01e8a6d0SThomas Weißschuh register long _arg3 __asm__ ("x2") = (long)(arg3); \ 76*01e8a6d0SThomas Weißschuh \ 77*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 78*01e8a6d0SThomas Weißschuh "svc #0\n" \ 79*01e8a6d0SThomas Weißschuh : "=r"(_arg1) \ 80*01e8a6d0SThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 81*01e8a6d0SThomas Weißschuh "r"(_num) \ 82*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 83*01e8a6d0SThomas Weißschuh ); \ 84*01e8a6d0SThomas Weißschuh _arg1; \ 85*01e8a6d0SThomas Weißschuh }) 86*01e8a6d0SThomas Weißschuh 87*01e8a6d0SThomas Weißschuh #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 88*01e8a6d0SThomas Weißschuh ({ \ 89*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 90*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0") = (long)(arg1); \ 91*01e8a6d0SThomas Weißschuh register long _arg2 __asm__ ("x1") = (long)(arg2); \ 92*01e8a6d0SThomas Weißschuh register long _arg3 __asm__ ("x2") = (long)(arg3); \ 93*01e8a6d0SThomas Weißschuh register long _arg4 __asm__ ("x3") = (long)(arg4); \ 94*01e8a6d0SThomas Weißschuh \ 95*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 96*01e8a6d0SThomas Weißschuh "svc #0\n" \ 97*01e8a6d0SThomas Weißschuh : "=r"(_arg1) \ 98*01e8a6d0SThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 99*01e8a6d0SThomas Weißschuh "r"(_num) \ 100*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 101*01e8a6d0SThomas Weißschuh ); \ 102*01e8a6d0SThomas Weißschuh _arg1; \ 103*01e8a6d0SThomas Weißschuh }) 104*01e8a6d0SThomas Weißschuh 105*01e8a6d0SThomas Weißschuh #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 106*01e8a6d0SThomas Weißschuh ({ \ 107*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 108*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0") = (long)(arg1); \ 109*01e8a6d0SThomas Weißschuh register long _arg2 __asm__ ("x1") = (long)(arg2); \ 110*01e8a6d0SThomas Weißschuh register long _arg3 __asm__ ("x2") = (long)(arg3); \ 111*01e8a6d0SThomas Weißschuh register long _arg4 __asm__ ("x3") = (long)(arg4); \ 112*01e8a6d0SThomas Weißschuh register long _arg5 __asm__ ("x4") = (long)(arg5); \ 113*01e8a6d0SThomas Weißschuh \ 114*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 115*01e8a6d0SThomas Weißschuh "svc #0\n" \ 116*01e8a6d0SThomas Weißschuh : "=r" (_arg1) \ 117*01e8a6d0SThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 118*01e8a6d0SThomas Weißschuh "r"(_num) \ 119*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 120*01e8a6d0SThomas Weißschuh ); \ 121*01e8a6d0SThomas Weißschuh _arg1; \ 122*01e8a6d0SThomas Weißschuh }) 123*01e8a6d0SThomas Weißschuh 124*01e8a6d0SThomas Weißschuh #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 125*01e8a6d0SThomas Weißschuh ({ \ 126*01e8a6d0SThomas Weißschuh register long _num __asm__ ("x8") = (num); \ 127*01e8a6d0SThomas Weißschuh register long _arg1 __asm__ ("x0") = (long)(arg1); \ 128*01e8a6d0SThomas Weißschuh register long _arg2 __asm__ ("x1") = (long)(arg2); \ 129*01e8a6d0SThomas Weißschuh register long _arg3 __asm__ ("x2") = (long)(arg3); \ 130*01e8a6d0SThomas Weißschuh register long _arg4 __asm__ ("x3") = (long)(arg4); \ 131*01e8a6d0SThomas Weißschuh register long _arg5 __asm__ ("x4") = (long)(arg5); \ 132*01e8a6d0SThomas Weißschuh register long _arg6 __asm__ ("x5") = (long)(arg6); \ 133*01e8a6d0SThomas Weißschuh \ 134*01e8a6d0SThomas Weißschuh __asm__ volatile ( \ 135*01e8a6d0SThomas Weißschuh "svc #0\n" \ 136*01e8a6d0SThomas Weißschuh : "=r" (_arg1) \ 137*01e8a6d0SThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 138*01e8a6d0SThomas Weißschuh "r"(_arg6), "r"(_num) \ 139*01e8a6d0SThomas Weißschuh : "memory", "cc" \ 140*01e8a6d0SThomas Weißschuh ); \ 141*01e8a6d0SThomas Weißschuh _arg1; \ 142*01e8a6d0SThomas Weißschuh }) 143*01e8a6d0SThomas Weißschuh 144*01e8a6d0SThomas Weißschuh /* startup code */ 145*01e8a6d0SThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) 146*01e8a6d0SThomas Weißschuh { 147*01e8a6d0SThomas Weißschuh __asm__ volatile ( 148*01e8a6d0SThomas Weißschuh "mov x0, sp\n" /* save stack pointer to x0, as arg1 of _start_c */ 149*01e8a6d0SThomas Weißschuh "bl _start_c\n" /* transfer to c runtime */ 150*01e8a6d0SThomas Weißschuh ); 151*01e8a6d0SThomas Weißschuh __nolibc_entrypoint_epilogue(); 152*01e8a6d0SThomas Weißschuh } 153*01e8a6d0SThomas Weißschuh #endif /* _NOLIBC_ARCH_ARM64_H */ 154