]> Git Repo - linux.git/blob - tools/include/nolibc/arch-riscv.h
driver core: Return proper error code when dev_set_name() fails
[linux.git] / tools / include / nolibc / arch-riscv.h
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 <[email protected]>
5  */
6
7 #ifndef _NOLIBC_ARCH_RISCV_H
8 #define _NOLIBC_ARCH_RISCV_H
9
10 #include "compiler.h"
11
12 struct sys_stat_struct {
13         unsigned long   st_dev;         /* Device.  */
14         unsigned long   st_ino;         /* File serial number.  */
15         unsigned int    st_mode;        /* File mode.  */
16         unsigned int    st_nlink;       /* Link count.  */
17         unsigned int    st_uid;         /* User ID of the file's owner.  */
18         unsigned int    st_gid;         /* Group ID of the file's group. */
19         unsigned long   st_rdev;        /* Device number, if device.  */
20         unsigned long   __pad1;
21         long            st_size;        /* Size of file, in bytes.  */
22         int             st_blksize;     /* Optimal block size for I/O.  */
23         int             __pad2;
24         long            st_blocks;      /* Number 512-byte blocks allocated. */
25         long            st_atime;       /* Time of last access.  */
26         unsigned long   st_atime_nsec;
27         long            st_mtime;       /* Time of last modification.  */
28         unsigned long   st_mtime_nsec;
29         long            st_ctime;       /* Time of last status change.  */
30         unsigned long   st_ctime_nsec;
31         unsigned int    __unused4;
32         unsigned int    __unused5;
33 };
34
35 #if   __riscv_xlen == 64
36 #define PTRLOG "3"
37 #define SZREG  "8"
38 #define REG_L  "ld"
39 #define REG_S  "sd"
40 #elif __riscv_xlen == 32
41 #define PTRLOG "2"
42 #define SZREG  "4"
43 #define REG_L  "lw"
44 #define REG_S  "sw"
45 #endif
46
47 /* Syscalls for RISCV :
48  *   - stack is 16-byte aligned
49  *   - syscall number is passed in a7
50  *   - arguments are in a0, a1, a2, a3, a4, a5
51  *   - the system call is performed by calling ecall
52  *   - syscall return comes in a0
53  *   - the arguments are cast to long and assigned into the target
54  *     registers which are then simply passed as registers to the asm code,
55  *     so that we don't have to experience issues with register constraints.
56  *
57  * On riscv, select() is not implemented so we have to use pselect6().
58  */
59 #define __ARCH_WANT_SYS_PSELECT6
60
61 #define my_syscall0(num)                                                      \
62 ({                                                                            \
63         register long _num  __asm__ ("a7") = (num);                           \
64         register long _arg1 __asm__ ("a0");                                   \
65                                                                               \
66         __asm__  volatile (                                                   \
67                 "ecall\n\t"                                                   \
68                 : "=r"(_arg1)                                                 \
69                 : "r"(_num)                                                   \
70                 : "memory", "cc"                                              \
71         );                                                                    \
72         _arg1;                                                                \
73 })
74
75 #define my_syscall1(num, arg1)                                                \
76 ({                                                                            \
77         register long _num  __asm__ ("a7") = (num);                           \
78         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
79                                                                               \
80         __asm__  volatile (                                                   \
81                 "ecall\n"                                                     \
82                 : "+r"(_arg1)                                                 \
83                 : "r"(_num)                                                   \
84                 : "memory", "cc"                                              \
85         );                                                                    \
86         _arg1;                                                                \
87 })
88
89 #define my_syscall2(num, arg1, arg2)                                          \
90 ({                                                                            \
91         register long _num  __asm__ ("a7") = (num);                           \
92         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
93         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
94                                                                               \
95         __asm__  volatile (                                                   \
96                 "ecall\n"                                                     \
97                 : "+r"(_arg1)                                                 \
98                 : "r"(_arg2),                                                 \
99                   "r"(_num)                                                   \
100                 : "memory", "cc"                                              \
101         );                                                                    \
102         _arg1;                                                                \
103 })
104
105 #define my_syscall3(num, arg1, arg2, arg3)                                    \
106 ({                                                                            \
107         register long _num  __asm__ ("a7") = (num);                           \
108         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
109         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
110         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
111                                                                               \
112         __asm__  volatile (                                                   \
113                 "ecall\n\t"                                                   \
114                 : "+r"(_arg1)                                                 \
115                 : "r"(_arg2), "r"(_arg3),                                     \
116                   "r"(_num)                                                   \
117                 : "memory", "cc"                                              \
118         );                                                                    \
119         _arg1;                                                                \
120 })
121
122 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
123 ({                                                                            \
124         register long _num  __asm__ ("a7") = (num);                           \
125         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
126         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
127         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
128         register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
129                                                                               \
130         __asm__  volatile (                                                   \
131                 "ecall\n"                                                     \
132                 : "+r"(_arg1)                                                 \
133                 : "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
134                   "r"(_num)                                                   \
135                 : "memory", "cc"                                              \
136         );                                                                    \
137         _arg1;                                                                \
138 })
139
140 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
141 ({                                                                            \
142         register long _num  __asm__ ("a7") = (num);                           \
143         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
144         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
145         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
146         register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
147         register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
148                                                                               \
149         __asm__  volatile (                                                   \
150                 "ecall\n"                                                     \
151                 : "+r"(_arg1)                                                 \
152                 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
153                   "r"(_num)                                                   \
154                 : "memory", "cc"                                              \
155         );                                                                    \
156         _arg1;                                                                \
157 })
158
159 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
160 ({                                                                            \
161         register long _num  __asm__ ("a7") = (num);                           \
162         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
163         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
164         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
165         register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
166         register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
167         register long _arg6 __asm__ ("a5") = (long)(arg6);                    \
168                                                                               \
169         __asm__  volatile (                                                   \
170                 "ecall\n"                                                     \
171                 : "+r"(_arg1)                                                 \
172                 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
173                   "r"(_num)                                                   \
174                 : "memory", "cc"                                              \
175         );                                                                    \
176         _arg1;                                                                \
177 })
178
179 char **environ __attribute__((weak));
180 const unsigned long *_auxv __attribute__((weak));
181
182 /* startup code */
183 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) __no_stack_protector _start(void)
184 {
185         __asm__ volatile (
186                 ".option push\n"
187                 ".option norelax\n"
188                 "lla   gp, __global_pointer$\n"
189                 ".option pop\n"
190 #ifdef _NOLIBC_STACKPROTECTOR
191                 "call __stack_chk_init\n"    /* initialize stack protector                          */
192 #endif
193                 REG_L" a0, 0(sp)\n"          /* argc (a0) was in the stack                          */
194                 "add   a1, sp, "SZREG"\n"    /* argv (a1) = sp                                      */
195                 "slli  a2, a0, "PTRLOG"\n"   /* envp (a2) = SZREG*argc ...                          */
196                 "add   a2, a2, "SZREG"\n"    /*             + SZREG (skip null)                     */
197                 "add   a2,a2,a1\n"           /*             + argv                                  */
198
199                 "add   a3, a2, zero\n"       /* iterate a3 over envp to find auxv (after NULL)      */
200                 "0:\n"                       /* do {                                                */
201                 REG_L" a4, 0(a3)\n"          /*   a4 = *a3;                                         */
202                 "add   a3, a3, "SZREG"\n"    /*   a3 += sizeof(void*);                              */
203                 "bne   a4, zero, 0b\n"       /* } while (a4);                                       */
204                 "lui   a4, %hi(_auxv)\n"     /* a4 = &_auxv (high bits)                             */
205                 REG_S" a3, %lo(_auxv)(a4)\n" /* store a3 into _auxv                                 */
206
207                 "lui   a3, %hi(environ)\n"   /* a3 = &environ (high bits)                           */
208                 REG_S" a2,%lo(environ)(a3)\n"/* store envp(a2) into environ                         */
209                 "andi  sp,a1,-16\n"          /* sp must be 16-byte aligned                          */
210                 "call  main\n"               /* main() returns the status code, we'll exit with it. */
211                 "li a7, 93\n"                /* NR_exit == 93                                       */
212                 "ecall\n"
213         );
214         __builtin_unreachable();
215 }
216
217 #endif /* _NOLIBC_ARCH_RISCV_H */
This page took 0.047333 seconds and 4 git commands to generate.