1 /*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7 #pragma once
8
9 #include <config.h>
10
11 /* CurrentEL register */
12 #define PEXPL1 (1 << 2)
13 #define PEXPL2 (1 << 3)
14
15 /* PSTATE register */
16 #define PMODE_FIRQ (1 << 6)
17 #define PMODE_IRQ (1 << 7)
18 #define PMODE_SERROR (1 << 8)
19 #define PMODE_DEBUG (1 << 9)
20 #define PMODE_EL0t 0
21 #define PMODE_EL1t 4
22 #define PMODE_EL1h 5
23 #define PMODE_EL2h 9
24
25 /* DAIF register */
26 #define DAIF_FIRQ (1 << 6)
27 #define DAIF_IRQ (1 << 7)
28 #define DAIF_SERROR (1 << 8)
29 #define DAIF_DEBUG (1 << 9)
30 #define DAIFSET_MASK 0xf
31
32 /* ESR register */
33 #define ESR_EC_SHIFT 26
34 #define ESR_EC_LEL_DABT 0x24 // Data abort from a lower EL
35 #define ESR_EC_CEL_DABT 0x25 // Data abort from the current EL
36 #define ESR_EC_LEL_IABT 0x20 // Instruction abort from a lower EL
37 #define ESR_EC_CEL_IABT 0x21 // Instruction abort from the current EL
38 #define ESR_EC_LEL_SVC64 0x15 // SVC from a lower EL in AArch64 state
39 #define ESR_EC_LEL_HVC64 0x16 // HVC from EL1 in AArch64 state
40 #define ESR_EL1_EC_ENFP 0x7 // Access to Advanced SIMD or floating-point registers
41
42
43 /* ID_AA64PFR0_EL1 register */
44 #define ID_AA64PFR0_EL1_FP 16 // HWCap for Floating Point
45 #define ID_AA64PFR0_EL1_ASIMD 20 // HWCap for Advanced SIMD
46
47 /* CPACR_EL1 register */
48 #define CPACR_EL1_FPEN 20 // FP regiters access
49
50 /*
51 * We cannot allow async aborts in the verified kernel, but they are useful
52 * in identifying invalid memory access bugs so we enable them in debug mode.
53 */
54 #ifdef CONFIG_DEBUG_BUILD
55 #define PSTATE_EXTRA_FLAGS 0
56 #else
57 #define PSTATE_EXTRA_FLAGS PMODE_SERROR
58 #endif
59
60 #define PSTATE_USER (PMODE_FIRQ | PMODE_EL0t | PSTATE_EXTRA_FLAGS)
61
62 #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
63 #define PSTATE_IDLETHREAD (PMODE_FIRQ | PMODE_EL2h | PSTATE_EXTRA_FLAGS)
64 #else
65 #define PSTATE_IDLETHREAD (PMODE_FIRQ | PMODE_EL1h | PSTATE_EXTRA_FLAGS)
66 #endif
67
68 /* Offsets within the user context, these need to match the order in
69 * register_t below */
70 #define PT_LR (30 * 8)
71 #define PT_SP_EL0 (31 * 8)
72 #define PT_ELR_EL1 (32 * 8)
73 #define PT_SPSR_EL1 (33 * 8)
74 #define PT_FaultIP (34 * 8)
75 #define PT_TPIDR_EL0 (35 * 8)
76
77 #ifndef __ASSEMBLER__ /* C only definitions */
78
79 #include <config.h>
80 #include <stdint.h>
81 #include <assert.h>
82 #include <util.h>
83 #include <arch/types.h>
84 #include <sel4/plat/api/constants.h>
85
86 /* These are the indices of the registers in the saved thread context.
87 * The values are determined by the order in which they're saved in the trap handler. */
88 enum _register {
89 X0 = 0, /* 0x00 */
90 capRegister = 0,
91 badgeRegister = 0,
92
93 X1 = 1, /* 0x08 */
94 msgInfoRegister = 1,
95
96 X2 = 2, /* 0x10 */
97 X3 = 3, /* 0x18 */
98 X4 = 4, /* 0x20 */
99 X5 = 5, /* 0x28 */
100 X6 = 6, /* 0x30 */
101 #ifdef CONFIG_KERNEL_MCS
102 replyRegister = 6,
103 #endif
104 X7 = 7, /* 0x38 */
105 X8 = 8, /* 0x40 */
106 #ifdef CONFIG_KERNEL_MCS
107 nbsendRecvDest = 8,
108 #endif
109 X9 = 9, /* 0x48 */
110 X10 = 10, /* 0x50 */
111 X11 = 11, /* 0x58 */
112 X12 = 12, /* 0x60 */
113 X13 = 13, /* 0x68 */
114 X14 = 14, /* 0x70 */
115 X15 = 15, /* 0x78 */
116 X16 = 16, /* 0x80 */
117 X17 = 17, /* 0x88 */
118 X18 = 18, /* 0x90 */
119 X19 = 19, /* 0x98 */
120 X20 = 20, /* 0xa0 */
121 X21 = 21, /* 0xa8 */
122 X22 = 22, /* 0xb0 */
123 X23 = 23, /* 0xb8 */
124 X24 = 24, /* 0xc0 */
125 X25 = 25, /* 0xc8 */
126 X26 = 26, /* 0xd0 */
127 X27 = 27, /* 0xd8 */
128 X28 = 28, /* 0xe0 */
129 X29 = 29, /* 0xe8 */
130
131 X30 = 30, /* 0xf0 */
132 LR = 30,
133
134 /* End of GP registers, the following are additional kernel-saved state. */
135
136 SP_EL0 = 31, /* 0xf8 */
137 ELR_EL1 = 32, /* 0x100 */
138 NextIP = 32, /* LR_svc */
139 SPSR_EL1 = 33, /* 0x108 */
140
141 FaultIP = 34, /* 0x110 */
142 /* user readable/writable thread ID register.
143 * name comes from the ARM manual */
144 TPIDR_EL0 = 35,
145 TLS_BASE = TPIDR_EL0,
146 /* user readonly thread ID register. */
147 TPIDRRO_EL0 = 36,
148 n_contextRegisters = 37,
149 };
150
151 #define NEXT_PC_REG ELR_EL1
152
153 compile_assert(sp_offset_correct, SP_EL0 *sizeof(word_t) == PT_SP_EL0)
154 compile_assert(lr_svc_offset_correct, ELR_EL1 *sizeof(word_t) == PT_ELR_EL1)
155 compile_assert(faultinstruction_offset_correct, FaultIP *sizeof(word_t) == PT_FaultIP)
156
157 typedef word_t register_t;
158
159 enum messageSizes {
160 n_msgRegisters = seL4_FastMessageRegisters,
161 n_frameRegisters = 17,
162 n_gpRegisters = 19,
163 n_exceptionMessage = 3,
164 n_syscallMessage = 12,
165 #ifdef CONFIG_KERNEL_MCS
166 n_timeoutMessage = 34,
167 #endif
168 };
169
170 #define EXCEPTION_MESSAGE \
171 {\
172 [seL4_UserException_FaultIP] = FaultIP,\
173 [seL4_UserException_SP] = SP_EL0,\
174 [seL4_UserException_SPSR] = SPSR_EL1\
175 }
176
177 #define SYSCALL_MESSAGE \
178 {\
179 [seL4_UnknownSyscall_X0] = X0,\
180 [seL4_UnknownSyscall_X1] = X1,\
181 [seL4_UnknownSyscall_X2] = X2,\
182 [seL4_UnknownSyscall_X3] = X3,\
183 [seL4_UnknownSyscall_X4] = X4,\
184 [seL4_UnknownSyscall_X5] = X5,\
185 [seL4_UnknownSyscall_X6] = X6,\
186 [seL4_UnknownSyscall_X7] = X7,\
187 [seL4_UnknownSyscall_FaultIP] = FaultIP,\
188 [seL4_UnknownSyscall_SP] = SP_EL0,\
189 [seL4_UnknownSyscall_LR] = ELR_EL1,\
190 [seL4_UnknownSyscall_SPSR] = SPSR_EL1\
191 }
192
193 #define TIMEOUT_REPLY_MESSAGE \
194 {\
195 [seL4_TimeoutReply_FaultIP] = FaultIP,\
196 [seL4_TimeoutReply_SP] = SP_EL0,\
197 [seL4_TimeoutReply_SPSR_EL1] = SPSR_EL1,\
198 [seL4_TimeoutReply_X0] = X0,\
199 [seL4_TimeoutReply_X1] = X1,\
200 [seL4_TimeoutReply_X2] = X2,\
201 [seL4_TimeoutReply_X3] = X3,\
202 [seL4_TimeoutReply_X4] = X4,\
203 [seL4_TimeoutReply_X5] = X5,\
204 [seL4_TimeoutReply_X6] = X6,\
205 [seL4_TimeoutReply_X7] = X7,\
206 [seL4_TimeoutReply_X8] = X8,\
207 [seL4_TimeoutReply_X16] = X16,\
208 [seL4_TimeoutReply_X17] = X17,\
209 [seL4_TimeoutReply_X18] = X18,\
210 [seL4_TimeoutReply_X29] = X29,\
211 [seL4_TimeoutReply_X30] = X30,\
212 [seL4_TimeoutReply_X9] = X9,\
213 [seL4_TimeoutReply_X10] = X10,\
214 [seL4_TimeoutReply_X11] = X11,\
215 [seL4_TimeoutReply_X12] = X12,\
216 [seL4_TimeoutReply_X13] = X13,\
217 [seL4_TimeoutReply_X14] = X14,\
218 [seL4_TimeoutReply_X15] = X15,\
219 [seL4_TimeoutReply_X19] = X19,\
220 [seL4_TimeoutReply_X20] = X20,\
221 [seL4_TimeoutReply_X21] = X21,\
222 [seL4_TimeoutReply_X22] = X22,\
223 [seL4_TimeoutReply_X23] = X23,\
224 [seL4_TimeoutReply_X24] = X24,\
225 [seL4_TimeoutReply_X25] = X25,\
226 [seL4_TimeoutReply_X26] = X26,\
227 [seL4_TimeoutReply_X27] = X27,\
228 [seL4_TimeoutReply_X28] = X28,\
229 }
230
231 extern const register_t msgRegisters[];
232 extern const register_t frameRegisters[];
233 extern const register_t gpRegisters[];
234
235 #ifdef CONFIG_HAVE_FPU
236 typedef struct user_fpu_state {
237 uint64_t vregs[64];
238 uint32_t fpsr;
239 uint32_t fpcr;
240 } user_fpu_state_t;
241 #endif /* CONFIG_HAVE_FPU */
242
243 /* ARM user-code context: size = 72 bytes
244 * Or with hardware debug support built in:
245 * 72 + sizeof(word_t) * (NUM_BPS + NUM_WPS) * 2
246 *
247 * The "word_t registers" member of this struct must come first, because in
248 * head.S, we assume that an "ldr %0, =ksCurThread" will point to the beginning
249 * of the current thread's registers. The assert below should help.
250 */
251 struct user_context {
252 word_t registers[n_contextRegisters];
253 #ifdef CONFIG_HAVE_FPU
254 user_fpu_state_t fpuState;
255 #endif /* CONFIG_HAVE_FPU */
256 };
257 typedef struct user_context user_context_t;
258
259 unverified_compile_assert(registers_are_first_member_of_user_context,
260 OFFSETOF(user_context_t, registers) == 0)
261
262
Arch_initContext(user_context_t * context)263 static inline void Arch_initContext(user_context_t *context)
264 {
265 context->registers[SPSR_EL1] = PSTATE_USER;
266 }
267
268 #endif /* !__ASSEMBLER__ */
269
270