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 19typedef 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 26enum vm_rights { 27 VMKernelOnly = 0, 28 VMReadWrite = 1, 29 VMKernelReadOnly = 2, 30 VMReadOnly = 3 31}; 32typedef 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 */ 60typedef pude_t vspace_root_t; 61#else 62/* Otherwise we use a 4-level translation */ 63typedef 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 105struct asid_pool { 106 vspace_root_t *array[BIT(asidLowBits)]; 107}; 108typedef 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 122static 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 161static 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 201static 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 240static 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 245static 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 250static 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 255static inline pude_t pude_invalid_new(void) 256{ 257 return (pude_t) { 258 { 259 0 260 } 261 }; 262} 263 264static 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 269static 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 274static inline pde_t pde_invalid_new(void) 275{ 276 return (pde_t) { 277 { 278 0 279 } 280 }; 281} 282 283static inline bool_t pte_ptr_get_present(pte_t *pt) 284{ 285 return (pte_ptr_get_reserved(pt) == 0x3); 286} 287 288static inline pte_t pte_invalid_new(void) 289{ 290 return (pte_t) { 291 { 292 0 293 } 294 }; 295} 296 297