Line data Source code
1 1 : /*
2 : * Copyright (c) 2018 Linaro Limited.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief x86 (IA32) specific syscall header
10 : *
11 : * This header contains the x86 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_X86_IA32_SYSCALL_H_
17 : #define ZEPHYR_INCLUDE_ARCH_X86_IA32_SYSCALL_H_
18 :
19 0 : #define USER_CODE_SEG 0x2b /* at dpl=3 */
20 0 : #define USER_DATA_SEG 0x33 /* at dpl=3 */
21 :
22 : #ifdef CONFIG_USERSPACE
23 : #ifndef _ASMLANGUAGE
24 :
25 : #include <zephyr/types.h>
26 : #include <stdbool.h>
27 : #include <zephyr/linker/sections.h>
28 :
29 : #ifdef __cplusplus
30 : extern "C" {
31 : #endif
32 :
33 : /* Syscall invocation macros. x86-specific machine constraints used to ensure
34 : * args land in the proper registers, see implementation of
35 : * z_x86_syscall_entry_stub in userspace.S
36 : */
37 :
38 : __pinned_func
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 : uint32_t ret;
45 :
46 : __asm__ volatile("push %%ebp\n\t"
47 : "mov %[arg6], %%ebp\n\t"
48 : "int $0x80\n\t"
49 : "pop %%ebp\n\t"
50 : : "=a" (ret)
51 : : "S" (call_id), "a" (arg1), "d" (arg2),
52 : "c" (arg3), "b" (arg4), "D" (arg5),
53 : [arg6] "m" (arg6)
54 : : "memory");
55 : return ret;
56 : }
57 :
58 : __pinned_func
59 0 : static inline uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
60 : uintptr_t arg3, uintptr_t arg4,
61 : uintptr_t arg5,
62 : uintptr_t call_id)
63 : {
64 : uint32_t ret;
65 :
66 : __asm__ volatile("int $0x80"
67 : : "=a" (ret)
68 : : "S" (call_id), "a" (arg1), "d" (arg2),
69 : "c" (arg3), "b" (arg4), "D" (arg5)
70 : : "memory");
71 : return ret;
72 : }
73 :
74 : __pinned_func
75 0 : static inline uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
76 : uintptr_t arg3, uintptr_t arg4,
77 : uintptr_t call_id)
78 : {
79 : uint32_t ret;
80 :
81 : __asm__ volatile("int $0x80"
82 : : "=a" (ret)
83 : : "S" (call_id), "a" (arg1), "d" (arg2), "c" (arg3),
84 : "b" (arg4)
85 : : "memory");
86 : return ret;
87 : }
88 :
89 : __pinned_func
90 0 : static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
91 : uintptr_t arg3,
92 : uintptr_t call_id)
93 : {
94 : uint32_t ret;
95 :
96 : __asm__ volatile("int $0x80"
97 : : "=a" (ret)
98 : : "S" (call_id), "a" (arg1), "d" (arg2), "c" (arg3)
99 : : "memory");
100 : return ret;
101 : }
102 :
103 : __pinned_func
104 0 : static inline uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
105 : uintptr_t call_id)
106 : {
107 : uint32_t ret;
108 :
109 : __asm__ volatile("int $0x80"
110 : : "=a" (ret)
111 : : "S" (call_id), "a" (arg1), "d" (arg2)
112 : : "memory"
113 : );
114 : return ret;
115 : }
116 :
117 : __pinned_func
118 0 : static inline uintptr_t arch_syscall_invoke1(uintptr_t arg1,
119 : uintptr_t call_id)
120 : {
121 : uint32_t ret;
122 :
123 : __asm__ volatile("int $0x80"
124 : : "=a" (ret)
125 : : "S" (call_id), "a" (arg1)
126 : : "memory"
127 : );
128 : return ret;
129 : }
130 :
131 : __pinned_func
132 0 : static inline uintptr_t arch_syscall_invoke0(uintptr_t call_id)
133 : {
134 : uint32_t ret;
135 :
136 : __asm__ volatile("int $0x80"
137 : : "=a" (ret)
138 : : "S" (call_id)
139 : : "memory"
140 : );
141 : return ret;
142 : }
143 :
144 : __pinned_func
145 0 : static inline bool arch_is_user_context(void)
146 : {
147 : int cs;
148 :
149 : /* On x86, read the CS register (which cannot be manually set) */
150 : __asm__ volatile ("mov %%cs, %[cs_val]" : [cs_val] "=r" (cs));
151 :
152 : return cs == USER_CODE_SEG;
153 : }
154 :
155 :
156 : #ifdef __cplusplus
157 : }
158 : #endif
159 :
160 : #endif /* _ASMLANGUAGE */
161 : #endif /* CONFIG_USERSPACE */
162 : #endif /* ZEPHYR_INCLUDE_ARCH_X86_IA32_SYSCALL_H_ */
|