1 /*
2 * Copyright (c) 2020 BayLibre, SAS
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief RISCV specific syscall header
10 *
11 * This header contains the RISCV specific syscall interface. It is
12 * included by the syscall interface architecture-abstraction header
13 * (include/arch/syscall.h)
14 */
15
16 #ifndef ZEPHYR_INCLUDE_ARCH_RISCV_SYSCALL_H_
17 #define ZEPHYR_INCLUDE_ARCH_RISCV_SYSCALL_H_
18
19 /*
20 * Privileged mode system calls
21 */
22 #define RV_ECALL_RUNTIME_EXCEPT 0
23 #define RV_ECALL_IRQ_OFFLOAD 1
24 #define RV_ECALL_SCHEDULE 2
25
26 #ifndef _ASMLANGUAGE
27
28 #include <zephyr/types.h>
29 #include <stdbool.h>
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /*
36 * Syscall invocation macros. riscv-specific machine constraints used to ensure
37 * args land in the proper registers.
38 */
arch_syscall_invoke6(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5,uintptr_t arg6,uintptr_t call_id)39 static inline uintptr_t arch_syscall_invoke6(uintptr_t arg1, uintptr_t arg2,
40 uintptr_t arg3, uintptr_t arg4,
41 uintptr_t arg5, uintptr_t arg6,
42 uintptr_t call_id)
43 {
44 register unsigned long a0 __asm__ ("a0") = arg1;
45 register unsigned long a1 __asm__ ("a1") = arg2;
46 register unsigned long a2 __asm__ ("a2") = arg3;
47 register unsigned long a3 __asm__ ("a3") = arg4;
48 register unsigned long a4 __asm__ ("a4") = arg5;
49 register unsigned long a5 __asm__ ("a5") = arg6;
50 register unsigned long t0 __asm__ ("t0") = call_id;
51
52 __asm__ volatile ("ecall"
53 : "+r" (a0)
54 : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5),
55 "r" (t0)
56 : "memory");
57 return a0;
58 }
59
arch_syscall_invoke5(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5,uintptr_t call_id)60 static inline uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
61 uintptr_t arg3, uintptr_t arg4,
62 uintptr_t arg5,
63 uintptr_t call_id)
64 {
65 register unsigned long a0 __asm__ ("a0") = arg1;
66 register unsigned long a1 __asm__ ("a1") = arg2;
67 register unsigned long a2 __asm__ ("a2") = arg3;
68 register unsigned long a3 __asm__ ("a3") = arg4;
69 register unsigned long a4 __asm__ ("a4") = arg5;
70 register unsigned long t0 __asm__ ("t0") = call_id;
71
72 __asm__ volatile ("ecall"
73 : "+r" (a0)
74 : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (t0)
75 : "memory");
76 return a0;
77 }
78
arch_syscall_invoke4(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t call_id)79 static inline uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
80 uintptr_t arg3, uintptr_t arg4,
81 uintptr_t call_id)
82 {
83 register unsigned long a0 __asm__ ("a0") = arg1;
84 register unsigned long a1 __asm__ ("a1") = arg2;
85 register unsigned long a2 __asm__ ("a2") = arg3;
86 register unsigned long a3 __asm__ ("a3") = arg4;
87 register unsigned long t0 __asm__ ("t0") = call_id;
88
89 __asm__ volatile ("ecall"
90 : "+r" (a0)
91 : "r" (a1), "r" (a2), "r" (a3), "r" (t0)
92 : "memory");
93 return a0;
94 }
95
arch_syscall_invoke3(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t call_id)96 static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
97 uintptr_t arg3,
98 uintptr_t call_id)
99 {
100 register unsigned long a0 __asm__ ("a0") = arg1;
101 register unsigned long a1 __asm__ ("a1") = arg2;
102 register unsigned long a2 __asm__ ("a2") = arg3;
103 register unsigned long t0 __asm__ ("t0") = call_id;
104
105 __asm__ volatile ("ecall"
106 : "+r" (a0)
107 : "r" (a1), "r" (a2), "r" (t0)
108 : "memory");
109 return a0;
110 }
111
arch_syscall_invoke2(uintptr_t arg1,uintptr_t arg2,uintptr_t call_id)112 static inline uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
113 uintptr_t call_id)
114 {
115 register unsigned long a0 __asm__ ("a0") = arg1;
116 register unsigned long a1 __asm__ ("a1") = arg2;
117 register unsigned long t0 __asm__ ("t0") = call_id;
118
119 __asm__ volatile ("ecall"
120 : "+r" (a0)
121 : "r" (a1), "r" (t0)
122 : "memory");
123 return a0;
124 }
125
arch_syscall_invoke1(uintptr_t arg1,uintptr_t call_id)126 static inline uintptr_t arch_syscall_invoke1(uintptr_t arg1, uintptr_t call_id)
127 {
128 register unsigned long a0 __asm__ ("a0") = arg1;
129 register unsigned long t0 __asm__ ("t0") = call_id;
130
131 __asm__ volatile ("ecall"
132 : "+r" (a0)
133 : "r" (t0)
134 : "memory");
135 return a0;
136 }
137
arch_syscall_invoke0(uintptr_t call_id)138 static inline uintptr_t arch_syscall_invoke0(uintptr_t call_id)
139 {
140 register unsigned long a0 __asm__ ("a0");
141 register unsigned long t0 __asm__ ("t0") = call_id;
142
143 __asm__ volatile ("ecall"
144 : "=r" (a0)
145 : "r" (t0)
146 : "memory");
147 return a0;
148 }
149
150 #ifdef CONFIG_USERSPACE
151 register unsigned long riscv_tp_reg __asm__ ("tp");
152
arch_is_user_context(void)153 static inline bool arch_is_user_context(void)
154 {
155 /* don't try accessing TLS variables if tp is not initialized */
156 if (riscv_tp_reg == 0) {
157 return false;
158 }
159
160 /* Defined in arch/riscv/core/thread.c */
161 extern __thread uint8_t is_user_mode;
162
163 return is_user_mode != 0;
164 }
165 #endif
166
167 #ifdef __cplusplus
168 }
169 #endif
170
171 #endif /* _ASMLANGUAGE */
172 #endif /* ZEPHYR_INCLUDE_ARCH_RISCV_SYSCALL_H_ */
173