Line data Source code
1 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 0 : #define RV_ECALL_RUNTIME_EXCEPT 0
23 0 : #define RV_ECALL_IRQ_OFFLOAD 1
24 0 : #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 : */
39 0 : 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 :
60 0 : 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 :
79 0 : 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 :
96 0 : 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 :
112 0 : 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 :
126 0 : 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 :
138 0 : 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 :
153 0 : 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 Z_THREAD_LOCAL 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_ */
|