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