Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
0002 /*
0003  * AARCH64 specific definitions for NOLIBC
0004  * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
0005  */
0006 
0007 #ifndef _NOLIBC_ARCH_AARCH64_H
0008 #define _NOLIBC_ARCH_AARCH64_H
0009 
0010 /* O_* macros for fcntl/open are architecture-specific */
0011 #define O_RDONLY            0
0012 #define O_WRONLY            1
0013 #define O_RDWR              2
0014 #define O_CREAT          0x40
0015 #define O_EXCL           0x80
0016 #define O_NOCTTY        0x100
0017 #define O_TRUNC         0x200
0018 #define O_APPEND        0x400
0019 #define O_NONBLOCK      0x800
0020 #define O_DIRECTORY    0x4000
0021 
0022 /* The struct returned by the newfstatat() syscall. Differs slightly from the
0023  * x86_64's stat one by field ordering, so be careful.
0024  */
0025 struct sys_stat_struct {
0026     unsigned long   st_dev;
0027     unsigned long   st_ino;
0028     unsigned int    st_mode;
0029     unsigned int    st_nlink;
0030     unsigned int    st_uid;
0031     unsigned int    st_gid;
0032 
0033     unsigned long   st_rdev;
0034     unsigned long   __pad1;
0035     long            st_size;
0036     int             st_blksize;
0037     int             __pad2;
0038 
0039     long            st_blocks;
0040     long            st_atime;
0041     unsigned long   st_atime_nsec;
0042     long            st_mtime;
0043 
0044     unsigned long   st_mtime_nsec;
0045     long            st_ctime;
0046     unsigned long   st_ctime_nsec;
0047     unsigned int    __unused[2];
0048 };
0049 
0050 /* Syscalls for AARCH64 :
0051  *   - registers are 64-bit
0052  *   - stack is 16-byte aligned
0053  *   - syscall number is passed in x8
0054  *   - arguments are in x0, x1, x2, x3, x4, x5
0055  *   - the system call is performed by calling svc 0
0056  *   - syscall return comes in x0.
0057  *   - the arguments are cast to long and assigned into the target registers
0058  *     which are then simply passed as registers to the asm code, so that we
0059  *     don't have to experience issues with register constraints.
0060  *
0061  * On aarch64, select() is not implemented so we have to use pselect6().
0062  */
0063 #define __ARCH_WANT_SYS_PSELECT6
0064 
0065 #define my_syscall0(num)                                                      \
0066 ({                                                                            \
0067     register long _num  __asm__ ("x8") = (num);                           \
0068     register long _arg1 __asm__ ("x0");                                   \
0069                                                                           \
0070     __asm__  volatile (                                                   \
0071         "svc #0\n"                                                    \
0072         : "=r"(_arg1)                                                 \
0073         : "r"(_num)                                                   \
0074         : "memory", "cc"                                              \
0075     );                                                                    \
0076     _arg1;                                                                \
0077 })
0078 
0079 #define my_syscall1(num, arg1)                                                \
0080 ({                                                                            \
0081     register long _num  __asm__ ("x8") = (num);                           \
0082     register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
0083                                                                           \
0084     __asm__  volatile (                                                   \
0085         "svc #0\n"                                                    \
0086         : "=r"(_arg1)                                                 \
0087         : "r"(_arg1),                                                 \
0088           "r"(_num)                                                   \
0089         : "memory", "cc"                                              \
0090     );                                                                    \
0091     _arg1;                                                                \
0092 })
0093 
0094 #define my_syscall2(num, arg1, arg2)                                          \
0095 ({                                                                            \
0096     register long _num  __asm__ ("x8") = (num);                           \
0097     register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
0098     register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
0099                                                                           \
0100     __asm__  volatile (                                                   \
0101         "svc #0\n"                                                    \
0102         : "=r"(_arg1)                                                 \
0103         : "r"(_arg1), "r"(_arg2),                                     \
0104           "r"(_num)                                                   \
0105         : "memory", "cc"                                              \
0106     );                                                                    \
0107     _arg1;                                                                \
0108 })
0109 
0110 #define my_syscall3(num, arg1, arg2, arg3)                                    \
0111 ({                                                                            \
0112     register long _num  __asm__ ("x8") = (num);                           \
0113     register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
0114     register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
0115     register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
0116                                                                           \
0117     __asm__  volatile (                                                   \
0118         "svc #0\n"                                                    \
0119         : "=r"(_arg1)                                                 \
0120         : "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
0121           "r"(_num)                                                   \
0122         : "memory", "cc"                                              \
0123     );                                                                    \
0124     _arg1;                                                                \
0125 })
0126 
0127 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
0128 ({                                                                            \
0129     register long _num  __asm__ ("x8") = (num);                           \
0130     register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
0131     register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
0132     register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
0133     register long _arg4 __asm__ ("x3") = (long)(arg4);                    \
0134                                                                           \
0135     __asm__  volatile (                                                   \
0136         "svc #0\n"                                                    \
0137         : "=r"(_arg1)                                                 \
0138         : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
0139           "r"(_num)                                                   \
0140         : "memory", "cc"                                              \
0141     );                                                                    \
0142     _arg1;                                                                \
0143 })
0144 
0145 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
0146 ({                                                                            \
0147     register long _num  __asm__ ("x8") = (num);                           \
0148     register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
0149     register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
0150     register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
0151     register long _arg4 __asm__ ("x3") = (long)(arg4);                    \
0152     register long _arg5 __asm__ ("x4") = (long)(arg5);                    \
0153                                                                           \
0154     __asm__  volatile (                                                   \
0155         "svc #0\n"                                                    \
0156         : "=r" (_arg1)                                                \
0157         : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
0158           "r"(_num)                                                   \
0159         : "memory", "cc"                                              \
0160     );                                                                    \
0161     _arg1;                                                                \
0162 })
0163 
0164 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
0165 ({                                                                            \
0166     register long _num  __asm__ ("x8") = (num);                           \
0167     register long _arg1 __asm__ ("x0") = (long)(arg1);                    \
0168     register long _arg2 __asm__ ("x1") = (long)(arg2);                    \
0169     register long _arg3 __asm__ ("x2") = (long)(arg3);                    \
0170     register long _arg4 __asm__ ("x3") = (long)(arg4);                    \
0171     register long _arg5 __asm__ ("x4") = (long)(arg5);                    \
0172     register long _arg6 __asm__ ("x5") = (long)(arg6);                    \
0173                                                                           \
0174     __asm__  volatile (                                                   \
0175         "svc #0\n"                                                    \
0176         : "=r" (_arg1)                                                \
0177         : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
0178           "r"(_arg6), "r"(_num)                                       \
0179         : "memory", "cc"                                              \
0180     );                                                                    \
0181     _arg1;                                                                \
0182 })
0183 
0184 /* startup code */
0185 __asm__ (".section .text\n"
0186     ".weak _start\n"
0187     "_start:\n"
0188     "ldr x0, [sp]\n"              // argc (x0) was in the stack
0189     "add x1, sp, 8\n"             // argv (x1) = sp
0190     "lsl x2, x0, 3\n"             // envp (x2) = 8*argc ...
0191     "add x2, x2, 8\n"             //           + 8 (skip null)
0192     "add x2, x2, x1\n"            //           + argv
0193     "and sp, x1, -16\n"           // sp must be 16-byte aligned in the callee
0194     "bl main\n"                   // main() returns the status code, we'll exit with it.
0195     "mov x8, 93\n"                // NR_exit == 93
0196     "svc #0\n"
0197     "");
0198 
0199 #endif // _NOLIBC_ARCH_AARCH64_H