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 #include <assert.h>
11 #include <util.h>
12 #include <api/types.h>
13 #include <sel4/macros.h>
14 #include <arch/types.h>
15 #include <arch/object/structures_gen.h>
16 #include <arch/machine/hardware.h>
17 #include <arch/machine/registerset.h>
18
19 typedef struct arch_tcb {
20 user_context_t tcbContext;
21 #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
22 struct vcpu *tcbVCPU;
23 #endif
24 } arch_tcb_t;
25
26 enum vm_rights {
27 VMKernelOnly = 0,
28 VMReadWrite = 1,
29 VMKernelReadOnly = 2,
30 VMReadOnly = 3
31 };
32 typedef word_t vm_rights_t;
33
34 /* If hypervisor support for aarch64 is enabled and we run on processors with
35 * 40-bit PA, the stage-2 translation for EL1/EL0 uses a 3-level translation, skipping the PGD level.
36 * Yet the kernel will still use a stage-1 translation with 48 bit input addresses and a 4-level
37 * translation. Therefore, PUD and PGD size for the kernel can be different from EL1/EL0
38 * so we do not use the libsel4 definitions */
39 #define PGD_SIZE_BITS 12
40 #define PGD_INDEX_BITS 9
41 #define PUD_SIZE_BITS 12
42 #define PUD_INDEX_BITS 9
43 #define UPUD_SIZE_BITS seL4_PUDBits
44 #define UPUD_INDEX_BITS seL4_PUDIndexBits
45
46 #define PDE_SIZE_BITS seL4_PageDirEntryBits
47 #define PD_INDEX_BITS seL4_PageDirIndexBits
48 #define PTE_SIZE_BITS seL4_PageTableEntryBits
49 #define PT_INDEX_BITS seL4_PageTableIndexBits
50
51 #define PT_INDEX_OFFSET (seL4_PageBits)
52 #define PD_INDEX_OFFSET (PT_INDEX_OFFSET + PT_INDEX_BITS)
53 #define PUD_INDEX_OFFSET (PD_INDEX_OFFSET + PD_INDEX_BITS)
54 #define PGD_INDEX_OFFSET (PUD_INDEX_OFFSET + PUD_INDEX_BITS)
55
56 #define VCPU_SIZE_BITS seL4_VCPUBits
57
58 #ifdef AARCH64_VSPACE_S2_START_L1
59 /* For hyp with 40 bit PA, EL1 and EL0 use a 3 level translation and skips the PGD */
60 typedef pude_t vspace_root_t;
61 #else
62 /* Otherwise we use a 4-level translation */
63 typedef pgde_t vspace_root_t;
64 #endif
65
66 #define VSPACE_PTR(r) ((vspace_root_t *)(r))
67
68 #define GET_PGD_INDEX(x) (((x) >> (PGD_INDEX_OFFSET)) & MASK(PGD_INDEX_BITS))
69 #define GET_PUD_INDEX(x) (((x) >> (PUD_INDEX_OFFSET)) & MASK(PUD_INDEX_BITS))
70 #define GET_UPUD_INDEX(x) (((x) >> (PUD_INDEX_OFFSET)) & MASK(UPUD_INDEX_BITS))
71 #define GET_PD_INDEX(x) (((x) >> (PD_INDEX_OFFSET)) & MASK(PD_INDEX_BITS))
72 #define GET_PT_INDEX(x) (((x) >> (PT_INDEX_OFFSET)) & MASK(PT_INDEX_BITS))
73
74 #define PGDE_PTR(r) ((pgde_t *)(r))
75 #define PGDE_PTR_PTR(r) ((pgde_t **)(r))
76 #define PGDE_REF(p) ((word_t)(p))
77
78 #define PGD_PTR(r) ((pgde_t *)(r))
79 #define PGD_REF(p) ((word_t)(r))
80
81 #define PUDE_PTR(r) ((pude_t *)(r))
82 #define PUDE_PTR_PTR(r) ((pude_t **)(r))
83 #define PUDE_REF(p) ((word_t)(p))
84
85 #define PUD_PTR(r) ((pude_t *)(r))
86 #define PUD_PREF(p) ((word_t)(p))
87
88 #define PDE_PTR(r) ((pde_t *)(r))
89 #define PDE_PTR_PTR(r) ((pde_t **)(r))
90 #define PDE_REF(p) ((word_t)(p))
91
92 #define PD_PTR(r) ((pde_t *)(r))
93 #define PD_REF(p) ((word_t)(p))
94
95 #define PTE_PTR(r) ((pte_t *)(r))
96 #define PTE_REF(p) ((word_t)(p))
97
98 #define PT_PTR(r) ((pte_t *)(r))
99 #define PT_REF(p) ((word_t)(p))
100
101 /* Generate a vcpu_t pointer from a vcpu block reference */
102 #define VCPU_PTR(r) ((struct vcpu *)(r))
103 #define VCPU_REF(p) ((word_t)(p))
104
105 struct asid_pool {
106 vspace_root_t *array[BIT(asidLowBits)];
107 };
108 typedef struct asid_pool asid_pool_t;
109
110 #define ASID_POOL_PTR(r) ((asid_pool_t*)r)
111 #define ASID_POOL_REF(p) ((word_t)p)
112
113
114 #define ASID_POOL_INDEX_BITS seL4_ASIDPoolIndexBits
115 #define ASID_BITS (asidHighBits+asidLowBits)
116 #define nASIDs BIT(ASID_BITS)
117 #define nASIDPools BIT(asidHighBits)
118
119 #define ASID_LOW(a) (a & MASK(asidLowBits))
120 #define ASID_HIGH(a) ((a >> asidLowBits) & MASK(asidHighBits))
121
cap_get_archCapSizeBits(cap_t cap)122 static inline word_t CONST cap_get_archCapSizeBits(cap_t cap)
123 {
124 cap_tag_t ctag;
125
126 ctag = cap_get_capType(cap);
127
128 switch (ctag) {
129 case cap_frame_cap:
130 return pageBitsForSize(cap_frame_cap_get_capFSize(cap));
131
132 case cap_page_table_cap:
133 return seL4_PageTableBits;
134
135 case cap_page_directory_cap:
136 return seL4_PageDirBits;
137
138 case cap_page_upper_directory_cap:
139 return seL4_PUDBits;
140
141 case cap_page_global_directory_cap:
142 return seL4_PGDBits;
143
144 case cap_asid_pool_cap:
145 return seL4_ASIDPoolBits;
146
147 case cap_asid_control_cap:
148 return 0;
149
150 #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
151 case cap_vcpu_cap:
152 return seL4_VCPUBits;
153 #endif
154
155 default:
156 /* Unreachable, but GCC can't figure that out */
157 return 0;
158 }
159 }
160
cap_get_archCapIsPhysical(cap_t cap)161 static inline bool_t CONST cap_get_archCapIsPhysical(cap_t cap)
162 {
163 cap_tag_t ctag;
164
165 ctag = cap_get_capType(cap);
166
167 switch (ctag) {
168
169 case cap_frame_cap:
170 return true;
171
172 case cap_page_table_cap:
173 return true;
174
175 case cap_page_directory_cap:
176 return true;
177
178 case cap_page_upper_directory_cap:
179 return true;
180
181 case cap_page_global_directory_cap:
182 return true;
183
184 case cap_asid_pool_cap:
185 return true;
186
187 case cap_asid_control_cap:
188 return false;
189
190 #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
191 case cap_vcpu_cap:
192 return true;
193 #endif
194
195 default:
196 /* Unreachable, but GCC can't figure that out */
197 return false;
198 }
199 }
200
cap_get_archCapPtr(cap_t cap)201 static inline void *CONST cap_get_archCapPtr(cap_t cap)
202 {
203 cap_tag_t ctag;
204
205 ctag = cap_get_capType(cap);
206
207 switch (ctag) {
208 case cap_frame_cap:
209 return (void *)(cap_frame_cap_get_capFBasePtr(cap));
210
211 case cap_page_table_cap:
212 return PD_PTR(cap_page_table_cap_get_capPTBasePtr(cap));
213
214 case cap_page_directory_cap:
215 return PT_PTR(cap_page_directory_cap_get_capPDBasePtr(cap));
216
217 case cap_page_upper_directory_cap:
218 return PUD_PTR(cap_page_upper_directory_cap_get_capPUDBasePtr(cap));
219
220 case cap_page_global_directory_cap:
221 return PGD_PTR(cap_page_global_directory_cap_get_capPGDBasePtr(cap));
222
223 case cap_asid_control_cap:
224 return NULL;
225
226 case cap_asid_pool_cap:
227 return ASID_POOL_PTR(cap_asid_pool_cap_get_capASIDPool(cap));
228
229 #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
230 case cap_vcpu_cap:
231 return VCPU_PTR(cap_vcpu_cap_get_capVCPUPtr(cap));
232 #endif
233
234 default:
235 /* Unreachable, but GCC can't figure that out */
236 return NULL;
237 }
238 }
239
pgde_pgde_pud_ptr_get_present(pgde_t * pgd)240 static inline bool_t pgde_pgde_pud_ptr_get_present(pgde_t *pgd)
241 {
242 return (pgde_ptr_get_pgde_type(pgd) == pgde_pgde_pud);
243 }
244
pude_pude_pd_ptr_get_present(pude_t * pud)245 static inline bool_t pude_pude_pd_ptr_get_present(pude_t *pud)
246 {
247 return (pude_ptr_get_pude_type(pud) == pude_pude_pd);
248 }
249
pude_pude_1g_ptr_get_present(pude_t * pud)250 static inline bool_t pude_pude_1g_ptr_get_present(pude_t *pud)
251 {
252 return (pude_ptr_get_pude_type(pud) == pude_pude_1g);
253 }
254
pude_invalid_new(void)255 static inline pude_t pude_invalid_new(void)
256 {
257 return (pude_t) {
258 {
259 0
260 }
261 };
262 }
263
pde_pde_small_ptr_get_present(pde_t * pd)264 static inline bool_t pde_pde_small_ptr_get_present(pde_t *pd)
265 {
266 return (pde_ptr_get_pde_type(pd) == pde_pde_small);
267 }
268
pde_pde_large_ptr_get_present(pde_t * pd)269 static inline bool_t pde_pde_large_ptr_get_present(pde_t *pd)
270 {
271 return (pde_ptr_get_pde_type(pd) == pde_pde_large);
272 }
273
pde_invalid_new(void)274 static inline pde_t pde_invalid_new(void)
275 {
276 return (pde_t) {
277 {
278 0
279 }
280 };
281 }
282
pte_ptr_get_present(pte_t * pt)283 static inline bool_t pte_ptr_get_present(pte_t *pt)
284 {
285 return (pte_ptr_get_reserved(pt) == 0x3);
286 }
287
pte_invalid_new(void)288 static inline pte_t pte_invalid_new(void)
289 {
290 return (pte_t) {
291 {
292 0
293 }
294 };
295 }
296
297