1 /*
2 * Copyright (c) 2018 Linaro Limited.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief ARC specific syscall header
10 *
11 * This header contains the ARC 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_ARC_SYSCALL_H_
17 #define ZEPHYR_INCLUDE_ARCH_ARC_SYSCALL_H_
18
19 #define _TRAP_S_CALL_RUNTIME_EXCEPT 2
20 #define _TRAP_S_CALL_SYSTEM_CALL 3
21
22 #ifdef CONFIG_USERSPACE
23 #ifndef _ASMLANGUAGE
24
25 #include <zephyr/types.h>
26 #include <stdbool.h>
27
28 #ifdef CONFIG_ISA_ARCV2
29 #include <zephyr/arch/arc/v2/aux_regs.h>
30 #endif
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 /* Syscall invocation macros. arc-specific machine constraints used to ensure
36 * args land in the proper registers. Currently, they are all stub functions
37 * just for enabling CONFIG_USERSPACE on arc w/o errors.
38 */
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 ret __asm__("r0") = arg1;
46 register uint32_t r1 __asm__("r1") = arg2;
47 register uint32_t r2 __asm__("r2") = arg3;
48 register uint32_t r3 __asm__("r3") = arg4;
49 register uint32_t r4 __asm__("r4") = arg5;
50 register uint32_t r5 __asm__("r5") = arg6;
51 register uint32_t r6 __asm__("r6") = call_id;
52
53 compiler_barrier();
54
55 __asm__ volatile(
56 "trap_s %[trap_s_id]\n"
57 : "=r"(ret)
58 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
59 "r" (ret), "r" (r1), "r" (r2), "r" (r3),
60 "r" (r4), "r" (r5), "r" (r6));
61
62 return ret;
63 }
64
arch_syscall_invoke5(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5,uintptr_t call_id)65 static inline uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
66 uintptr_t arg3, uintptr_t arg4,
67 uintptr_t arg5,
68 uintptr_t call_id)
69 {
70 register uint32_t ret __asm__("r0") = arg1;
71 register uint32_t r1 __asm__("r1") = arg2;
72 register uint32_t r2 __asm__("r2") = arg3;
73 register uint32_t r3 __asm__("r3") = arg4;
74 register uint32_t r4 __asm__("r4") = arg5;
75 register uint32_t r6 __asm__("r6") = call_id;
76
77 compiler_barrier();
78
79 __asm__ volatile(
80 "trap_s %[trap_s_id]\n"
81 : "=r"(ret)
82 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
83 "r" (ret), "r" (r1), "r" (r2), "r" (r3),
84 "r" (r4), "r" (r6));
85
86 return ret;
87 }
88
arch_syscall_invoke4(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t call_id)89 static inline uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
90 uintptr_t arg3, uintptr_t arg4,
91 uintptr_t call_id)
92 {
93 register uint32_t ret __asm__("r0") = arg1;
94 register uint32_t r1 __asm__("r1") = arg2;
95 register uint32_t r2 __asm__("r2") = arg3;
96 register uint32_t r3 __asm__("r3") = arg4;
97 register uint32_t r6 __asm__("r6") = call_id;
98
99 compiler_barrier();
100
101 __asm__ volatile(
102 "trap_s %[trap_s_id]\n"
103 : "=r"(ret)
104 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
105 "r" (ret), "r" (r1), "r" (r2), "r" (r3),
106 "r" (r6));
107
108 return ret;
109 }
110
arch_syscall_invoke3(uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t call_id)111 static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
112 uintptr_t arg3,
113 uintptr_t call_id)
114 {
115 register uint32_t ret __asm__("r0") = arg1;
116 register uint32_t r1 __asm__("r1") = arg2;
117 register uint32_t r2 __asm__("r2") = arg3;
118 register uint32_t r6 __asm__("r6") = call_id;
119
120 compiler_barrier();
121
122 __asm__ volatile(
123 "trap_s %[trap_s_id]\n"
124 : "=r"(ret)
125 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
126 "r" (ret), "r" (r1), "r" (r2), "r" (r6));
127
128 return ret;
129 }
130
arch_syscall_invoke2(uintptr_t arg1,uintptr_t arg2,uintptr_t call_id)131 static inline uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
132 uintptr_t call_id)
133 {
134 register uint32_t ret __asm__("r0") = arg1;
135 register uint32_t r1 __asm__("r1") = arg2;
136 register uint32_t r6 __asm__("r6") = call_id;
137
138 compiler_barrier();
139
140 __asm__ volatile(
141 "trap_s %[trap_s_id]\n"
142 : "=r"(ret)
143 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
144 "r" (ret), "r" (r1), "r" (r6));
145
146 return ret;
147 }
148
arch_syscall_invoke1(uintptr_t arg1,uintptr_t call_id)149 static inline uintptr_t arch_syscall_invoke1(uintptr_t arg1, uintptr_t call_id)
150 {
151 register uint32_t ret __asm__("r0") = arg1;
152 register uint32_t r6 __asm__("r6") = call_id;
153
154 compiler_barrier();
155
156 __asm__ volatile(
157 "trap_s %[trap_s_id]\n"
158 : "=r"(ret)
159 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
160 "r" (ret), "r" (r6));
161
162 return ret;
163 }
164
arch_syscall_invoke0(uintptr_t call_id)165 static inline uintptr_t arch_syscall_invoke0(uintptr_t call_id)
166 {
167 register uint32_t ret __asm__("r0");
168 register uint32_t r6 __asm__("r6") = call_id;
169
170 compiler_barrier();
171
172 __asm__ volatile(
173 "trap_s %[trap_s_id]\n"
174 : "=r"(ret)
175 : [trap_s_id] "i" (_TRAP_S_CALL_SYSTEM_CALL),
176 "r" (ret), "r" (r6));
177
178 return ret;
179 }
180
arch_is_user_context(void)181 static inline bool arch_is_user_context(void)
182 {
183 uint32_t status;
184
185 compiler_barrier();
186
187 __asm__ volatile("lr %0, [%[status32]]\n"
188 : "=r"(status)
189 : [status32] "i" (_ARC_V2_STATUS32));
190
191 return !(status & _ARC_V2_STATUS32_US) ? true : false;
192 }
193
194 #ifdef __cplusplus
195 }
196 #endif
197
198 #endif /* _ASMLANGUAGE */
199 #endif /* CONFIG_USERSPACE */
200 #endif /* ZEPHYR_INCLUDE_ARCH_ARC_SYSCALL_H_ */
201