github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/dmz/nolibc/arch-riscv.h (about)

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