Zephyr Project API 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
syscall.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
15
16#ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_SYSCALL_H_
17#define ZEPHYR_INCLUDE_ARCH_XTENSA_SYSCALL_H_
18
19#ifdef CONFIG_USERSPACE
20#ifndef _ASMLANGUAGE
21
22#include <zephyr/types.h>
23#include <stdbool.h>
26
27#include <xtensa/config/core-isa.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/* When syscall assembly is executed, the EPC points to the syscall
34 * instruction, and we have to manually advance it so we will
35 * return to the instruction after syscall to continue execution.
36 * However, with zero-overhead loops and the syscall instruction is
37 * the last instruction, this simple addition does not work as it
38 * would point past the loop and would have skipped the loop.
39 * Because of this, syscall entrance would need to look at the loop
40 * registers and set the PC back to the beginning of loop if we are
41 * still looping. Assuming most of the syscalls are not inside
42 * loops, the extra handling code consumes quite a few cycles.
43 * To workaround this, simply adds a nop after syscall so we no
44 * longer have to deal with loops at syscall entrance, and that
45 * a nop is faster than all the code to manipulate loop registers.
46 */
47#ifdef XCHAL_HAVE_LOOPS
48#define XTENSA_SYSCALL_ASM "syscall; nop;"
49#else
50#define XTENSA_SYSCALL_ASM "syscall"
51#endif
52
53#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
54uintptr_t xtensa_syscall_helper_args_6(uintptr_t arg1, uintptr_t arg2,
55 uintptr_t arg3, uintptr_t arg4,
56 uintptr_t arg5, uintptr_t arg6,
57 uintptr_t call_id);
58
59uintptr_t xtensa_syscall_helper_args_5(uintptr_t arg1, uintptr_t arg2,
60 uintptr_t arg3, uintptr_t arg4,
61 uintptr_t arg5, uintptr_t call_id);
62
63uintptr_t xtensa_syscall_helper_args_4(uintptr_t arg1, uintptr_t arg2,
64 uintptr_t arg3, uintptr_t arg4,
65 uintptr_t call_id);
66
67#define SYSINL ALWAYS_INLINE
68#else
69#define SYSINL inline
70#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
71
72#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL
73uintptr_t xtensa_syscall_helper_args_3(uintptr_t arg1, uintptr_t arg2,
74 uintptr_t arg3, uintptr_t call_id);
75
76uintptr_t xtensa_syscall_helper_args_2(uintptr_t arg1, uintptr_t arg2,
77 uintptr_t call_id);
78
79uintptr_t xtensa_syscall_helper_args_1(uintptr_t arg1, uintptr_t call_id);
80
81uintptr_t xtensa_syscall_helper_args_0(uintptr_t call_id);
82#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL */
83
92
93
95 uintptr_t arg3, uintptr_t arg4,
96 uintptr_t arg5, uintptr_t arg6,
97 uintptr_t call_id)
98{
99#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
100 return xtensa_syscall_helper_args_6(arg1, arg2, arg3, arg4, arg5, arg6, call_id);
101#else
102 register uintptr_t a2 __asm__("%a2") = call_id;
103 register uintptr_t a6 __asm__("%a6") = arg1;
104 register uintptr_t a3 __asm__("%a3") = arg2;
105 register uintptr_t a4 __asm__("%a4") = arg3;
106 register uintptr_t a5 __asm__("%a5") = arg4;
107 register uintptr_t a8 __asm__("%a8") = arg5;
108 register uintptr_t a9 __asm__("%a9") = arg6;
109
110 __asm__ volatile(XTENSA_SYSCALL_ASM
111 : "=r" (a2)
112 : "r" (a2), "r" (a6), "r" (a3), "r" (a4),
113 "r" (a5), "r" (a8), "r" (a9)
114 : "memory");
115
116 return a2;
117#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
118}
119
121 uintptr_t arg3, uintptr_t arg4,
122 uintptr_t arg5, uintptr_t call_id)
123{
124#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
125 return xtensa_syscall_helper_args_5(arg1, arg2, arg3, arg4, arg5, call_id);
126#else
127 register uintptr_t a2 __asm__("%a2") = call_id;
128 register uintptr_t a6 __asm__("%a6") = arg1;
129 register uintptr_t a3 __asm__("%a3") = arg2;
130 register uintptr_t a4 __asm__("%a4") = arg3;
131 register uintptr_t a5 __asm__("%a5") = arg4;
132 register uintptr_t a8 __asm__("%a8") = arg5;
133
134 __asm__ volatile(XTENSA_SYSCALL_ASM
135 : "=r" (a2)
136 : "r" (a2), "r" (a6), "r" (a3), "r" (a4),
137 "r" (a5), "r" (a8)
138 : "memory");
139
140 return a2;
141#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
142}
143
145 uintptr_t arg3, uintptr_t arg4,
146 uintptr_t call_id)
147{
148#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
149 return xtensa_syscall_helper_args_4(arg1, arg2, arg3, arg4, call_id);
150#else
151 register uintptr_t a2 __asm__("%a2") = call_id;
152 register uintptr_t a6 __asm__("%a6") = arg1;
153 register uintptr_t a3 __asm__("%a3") = arg2;
154 register uintptr_t a4 __asm__("%a4") = arg3;
155 register uintptr_t a5 __asm__("%a5") = arg4;
156
157 __asm__ volatile(XTENSA_SYSCALL_ASM
158 : "=r" (a2)
159 : "r" (a2), "r" (a6), "r" (a3), "r" (a4),
160 "r" (a5)
161 : "memory");
162
163 return a2;
164#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
165}
166
168 uintptr_t arg3, uintptr_t call_id)
169{
170#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL
171 return xtensa_syscall_helper_args_3(arg1, arg2, arg3, call_id);
172#else
173 register uintptr_t a2 __asm__("%a2") = call_id;
174 register uintptr_t a6 __asm__("%a6") = arg1;
175 register uintptr_t a3 __asm__("%a3") = arg2;
176 register uintptr_t a4 __asm__("%a4") = arg3;
177
178 __asm__ volatile(XTENSA_SYSCALL_ASM
179 : "=r" (a2)
180 : "r" (a2), "r" (a6), "r" (a3), "r" (a4)
181 : "memory");
182
183 return a2;
184#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL */
185}
186
188 uintptr_t call_id)
189{
190#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL
191 return xtensa_syscall_helper_args_2(arg1, arg2, call_id);
192#else
193 register uintptr_t a2 __asm__("%a2") = call_id;
194 register uintptr_t a6 __asm__("%a6") = arg1;
195 register uintptr_t a3 __asm__("%a3") = arg2;
196
197 __asm__ volatile(XTENSA_SYSCALL_ASM
198 : "=r" (a2)
199 : "r" (a2), "r" (a6), "r" (a3)
200 : "memory");
201
202 return a2;
203#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL */
204}
205
207{
208#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL
209 return xtensa_syscall_helper_args_1(arg1, call_id);
210#else
211 register uintptr_t a2 __asm__("%a2") = call_id;
212 register uintptr_t a6 __asm__("%a6") = arg1;
213
214 __asm__ volatile(XTENSA_SYSCALL_ASM
215 : "=r" (a2)
216 : "r" (a2), "r" (a6)
217 : "memory");
218
219 return a2;
220#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL */
221}
222
224{
225#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL
226 return xtensa_syscall_helper_args_0(call_id);
227#else
228 register uintptr_t a2 __asm__("%a2") = call_id;
229
230 __asm__ volatile(XTENSA_SYSCALL_ASM
231 : "=r" (a2)
232 : "r" (a2)
233 : "memory");
234
235 return a2;
236#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER_ALL */
237}
238
239/*
240 * There is no easy (or generic) way to figure out if a thread is running
241 * in un-privileged mode. Reading the current ring (PS.CRING) is a privileged
242 * instruction and not thread local storage is not available in xcc.
243 */
244static inline bool arch_is_user_context(void)
245{
246#if XCHAL_HAVE_THREADPTR
247 uint32_t thread;
248
249 __asm__ volatile(
250 "rur.THREADPTR %0\n\t"
251 : "=a" (thread)
252 );
253#ifdef CONFIG_THREAD_LOCAL_STORAGE
254 extern Z_THREAD_LOCAL uint32_t is_user_mode;
255
256 if (!thread) {
257 return false;
258 }
259
260 return is_user_mode != 0;
261#else
262 return !!thread;
263#endif
264
265#else /* XCHAL_HAVE_THREADPTR */
266 extern bool xtensa_is_user_context(void);
267
268 return xtensa_is_user_context();
269#endif /* XCHAL_HAVE_THREADPTR */
270}
271
272#undef SYSINL
273
274#ifdef __cplusplus
275}
276#endif
277
278#endif /* _ASMLANGUAGE */
279#endif /* CONFIG_USERSPACE */
280#endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_SYSCALL_H_ */
static uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t call_id)
Definition syscall.h:89
static uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2, uintptr_t call_id)
Definition syscall.h:131
static uintptr_t arch_syscall_invoke1(uintptr_t arg1, uintptr_t call_id)
Definition syscall.h:149
static uintptr_t arch_syscall_invoke0(uintptr_t call_id)
Definition syscall.h:165
static bool arch_is_user_context(void)
Definition syscall.h:181
static uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t call_id)
Definition syscall.h:65
static uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t call_id)
Definition syscall.h:111
static uintptr_t 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)
Definition syscall.h:40
#define SYSINL
Definition syscall.h:69
#define XTENSA_SYSCALL_ASM
Definition syscall.h:50
Definitions of various linker Sections.
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:105
Macro utilities.