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 #define _SVC_CALL_CONTEXT_SWITCH	0
20 #define _SVC_CALL_IRQ_OFFLOAD		1
21 #define _SVC_CALL_RUNTIME_EXCEPT	2
22 #define _SVC_CALL_SYSTEM_CALL		3
23 
24 #define FORCE_SYSCALL_ID		-1
25 
26 #ifdef CONFIG_USERSPACE
27 #ifndef _ASMLANGUAGE
28 
29 #include <zephyr/types.h>
30 #include <stdbool.h>
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 /*
37  * Syscall invocation macros. riscv-specific machine constraints used to ensure
38  * args land in the proper registers.
39  */
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)40 static inline uintptr_t arch_syscall_invoke6(uintptr_t arg1, uintptr_t arg2,
41 					     uintptr_t arg3, uintptr_t arg4,
42 					     uintptr_t arg5, uintptr_t arg6,
43 					     uintptr_t call_id)
44 {
45 	register uint32_t a0 __asm__ ("a0") = arg1;
46 	register uint32_t a1 __asm__ ("a1") = arg2;
47 	register uint32_t a2 __asm__ ("a2") = arg3;
48 	register uint32_t a3 __asm__ ("a3") = arg4;
49 	register uint32_t a4 __asm__ ("a4") = arg5;
50 	register uint32_t a5 __asm__ ("a5") = arg6;
51 	register uint32_t a7 __asm__ ("a7") = call_id;
52 
53 	__asm__ volatile ("ecall"
54 			  : "+r" (a0)
55 			  : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5),
56 			  "r" (a7)
57 			  : "memory");
58 	return a0;
59 }
60 
arch_syscall_invoke5(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5,uintptr_t call_id)61 static inline uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
62 					     uintptr_t arg3, uintptr_t arg4,
63 					     uintptr_t arg5,
64 					     uintptr_t call_id)
65 {
66 	register uint32_t a0 __asm__ ("a0") = arg1;
67 	register uint32_t a1 __asm__ ("a1") = arg2;
68 	register uint32_t a2 __asm__ ("a2") = arg3;
69 	register uint32_t a3 __asm__ ("a3") = arg4;
70 	register uint32_t a4 __asm__ ("a4") = arg5;
71 	register uint32_t a7 __asm__ ("a7") = call_id;
72 
73 	__asm__ volatile ("ecall"
74 			  : "+r" (a0)
75 			  : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a7)
76 			  : "memory");
77 	return a0;
78 }
79 
arch_syscall_invoke4(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t call_id)80 static inline uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
81 					     uintptr_t arg3, uintptr_t arg4,
82 					     uintptr_t call_id)
83 {
84 	register uint32_t a0 __asm__ ("a0") = arg1;
85 	register uint32_t a1 __asm__ ("a1") = arg2;
86 	register uint32_t a2 __asm__ ("a2") = arg3;
87 	register uint32_t a3 __asm__ ("a3") = arg4;
88 	register uint32_t a7 __asm__ ("a7") = call_id;
89 
90 	__asm__ volatile ("ecall"
91 			  : "+r" (a0)
92 			  : "r" (a1), "r" (a2), "r" (a3), "r" (a7)
93 			  : "memory");
94 	return a0;
95 }
96 
arch_syscall_invoke3(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t call_id)97 static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
98 					     uintptr_t arg3,
99 					     uintptr_t call_id)
100 {
101 	register uint32_t a0 __asm__ ("a0") = arg1;
102 	register uint32_t a1 __asm__ ("a1") = arg2;
103 	register uint32_t a2 __asm__ ("a2") = arg3;
104 	register uint32_t a7 __asm__ ("a7") = call_id;
105 
106 	__asm__ volatile ("ecall"
107 			  : "+r" (a0)
108 			  : "r" (a1), "r" (a2), "r" (a7)
109 			  : "memory");
110 	return a0;
111 }
112 
arch_syscall_invoke2(uintptr_t arg1,uintptr_t arg2,uintptr_t call_id)113 static inline uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
114 					     uintptr_t call_id)
115 {
116 	register uint32_t a0 __asm__ ("a0") = arg1;
117 	register uint32_t a1 __asm__ ("a1") = arg2;
118 	register uint32_t a7 __asm__ ("a7") = call_id;
119 
120 	__asm__ volatile ("ecall"
121 			  : "+r" (a0)
122 			  : "r" (a1), "r" (a7)
123 			  : "memory");
124 	return a0;
125 }
126 
arch_syscall_invoke1(uintptr_t arg1,uintptr_t call_id)127 static inline uintptr_t arch_syscall_invoke1(uintptr_t arg1, uintptr_t call_id)
128 {
129 	register uint32_t a0 __asm__ ("a0") = arg1;
130 	register uint32_t a7 __asm__ ("a7") = call_id;
131 
132 	__asm__ volatile ("ecall"
133 			  : "+r" (a0)
134 			  : "r" (a7)
135 			  : "memory");
136 	return a0;
137 }
138 
arch_syscall_invoke0(uintptr_t call_id)139 static inline uintptr_t arch_syscall_invoke0(uintptr_t call_id)
140 {
141 	register uint32_t a0 __asm__ ("a0");
142 	register uint32_t a7 __asm__ ("a7") = call_id;
143 
144 	__asm__ volatile ("ecall"
145 			  : "+r" (a0)
146 			  : "r" (a7)
147 			  : "memory");
148 	return a0;
149 }
150 
arch_is_user_context(void)151 static inline bool arch_is_user_context(void)
152 {
153 	/* Defined in arch/riscv/core/thread.c */
154 	extern ulong_t is_user_mode;
155 	return is_user_mode;
156 }
157 
158 #ifdef __cplusplus
159 }
160 #endif
161 
162 #endif /* _ASMLANGUAGE */
163 #endif /* CONFIG_USERSPACE */
164 #endif /* ZEPHYR_INCLUDE_ARCH_RISCV_SYSCALL_H_ */
165