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