Use ASID map bitfield for aarch64

This uses the asid_map bitfield from x86 for aarch64 to map from ASID to
a given address space.

This will allow for alternate mappings from ASIDs in the future as well
as moving small amounts of metadata into the the ASID table itself.

Co-authored-by: Kent McLeod <kent@kry10.com>
Signed-off-by: Kent McLeod <kent@kry10.com>
This commit is contained in:
Curtis Millar 2019-09-26 14:24:12 +10:00 committed by Kent McLeod
parent 83a02a96fc
commit 14a0b4ac5e
4 changed files with 81 additions and 38 deletions

View file

@ -49,6 +49,8 @@ void deleteASID(asid_t asid, vspace_root_t *vspace);
hw_asid_t getHWASID(asid_t asid);
#endif
asid_map_t findMapForASID(asid_t asid);
#ifdef __clang__
static const region_t BOOT_RODATA mode_reserved_region[] = {};
#else
@ -88,10 +90,10 @@ static inline exception_t performASIDPoolInvocation(asid_t asid, asid_pool_t *po
{
cap_page_upper_directory_cap_ptr_set_capPUDMappedASID(&cte->cap, asid);
cap_page_upper_directory_cap_ptr_set_capPUDIsMapped(&cte->cap, 1);
poolPtr->array[asid & MASK(asidLowBits)] =
PUDE_PTR(cap_page_upper_directory_cap_get_capPUDBasePtr(cte->cap));
asid_map_t asid_map = asid_map_asid_map_vspace_new(cap_page_upper_directory_cap_get_capPUDBasePtr(cte->cap));
poolPtr->array[asid & MASK(asidLowBits)] = asid_map;
#ifdef CONFIG_ARM_SMMU
vspace_root_t *vtable = poolPtr->array[asid & MASK(asidLowBits)];
vspace_root_t *vtable = (vspace_root_t *)cap_page_upper_directory_cap_get_capPUDBasePtr(cte->cap);
vtable[VTABLE_SMMU_SLOT] = vtable_invalid_smmu_new(0);
#endif
return EXCEPTION_NONE;
@ -132,11 +134,11 @@ static inline exception_t performASIDPoolInvocation(asid_t asid, asid_pool_t *po
{
cap_page_global_directory_cap_ptr_set_capPGDMappedASID(&cte->cap, asid);
cap_page_global_directory_cap_ptr_set_capPGDIsMapped(&cte->cap, 1);
poolPtr->array[asid & MASK(asidLowBits)] =
PGDE_PTR(cap_page_global_directory_cap_get_capPGDBasePtr(cte->cap));
asid_map_t asid_map = asid_map_asid_map_vspace_new(cap_page_global_directory_cap_get_capPGDBasePtr(cte->cap));
poolPtr->array[asid & MASK(asidLowBits)] = asid_map;
#ifdef CONFIG_ARM_SMMU
vspace_root_t *vtable = poolPtr->array[asid & MASK(asidLowBits)];
vspace_root_t *vtable = (vspace_root_t *)cap_page_global_directory_cap_get_capPGDBasePtr(cte->cap);
vtable[VTABLE_SMMU_SLOT] = vtable_invalid_smmu_new(0);
#endif
return EXCEPTION_NONE;

View file

@ -239,6 +239,23 @@ block vm_attributes {
---- ARM-specific object types
block asid_map_none {
padding 63
field type 1
}
block asid_map_vspace {
padding 16
field_high vspace_root 36
padding 11
field type 1
}
tagged_union asid_map type {
tag asid_map_none 0
tag asid_map_vspace 1
}
-- PGDE, PUDE, PDEs and PTEs, assuming 48-bit physical address
base 64(48,0)

View file

@ -103,7 +103,7 @@ typedef pgde_t vspace_root_t;
#define VCPU_REF(p) ((word_t)(p))
struct asid_pool {
vspace_root_t *array[BIT(asidLowBits)];
asid_map_t array[BIT(asidLowBits)];
};
typedef struct asid_pool asid_pool_t;

View file

@ -551,24 +551,36 @@ BOOT_CODE void activate_kernel_vspace(void)
BOOT_CODE void write_it_asid_pool(cap_t it_ap_cap, cap_t it_vspace_cap)
{
asid_pool_t *ap = ASID_POOL_PTR(pptr_of_cap(it_ap_cap));
ap->array[IT_ASID] = (void *)(pptr_of_cap(it_vspace_cap));
asid_map_t asid_map = asid_map_asid_map_vspace_new(pptr_of_cap(it_vspace_cap));
ap->array[IT_ASID] = asid_map;
armKSASIDTable[IT_ASID >> asidLowBits] = ap;
#ifdef CONFIG_ARM_SMMU
vspace_root_t *vtable = ap->array[IT_ASID];
vspace_root_t *vtable = cap_vtable_root_get_basePtr(it_vspace_cap);
vtable[VTABLE_SMMU_SLOT] = vtable_invalid_smmu_new(0);
#endif
}
/* ==================== BOOT CODE FINISHES HERE ==================== */
static findVSpaceForASID_ret_t findVSpaceForASID(asid_t asid)
asid_map_t findMapForASID(asid_t asid)
{
findVSpaceForASID_ret_t ret;
asid_pool_t *poolPtr;
vspace_root_t *vspace_root;
poolPtr = armKSASIDTable[asid >> asidLowBits];
if (!poolPtr) {
return asid_map_asid_map_none_new();
}
return poolPtr->array[asid & MASK(asidLowBits)];
}
static findVSpaceForASID_ret_t findVSpaceForASID(asid_t asid)
{
findVSpaceForASID_ret_t ret;
asid_map_t asid_map;
asid_map = findMapForASID(asid);
if (asid_map_get_type(asid_map) != asid_map_asid_map_vspace) {
current_lookup_fault = lookup_fault_invalid_root_new();
ret.vspace_root = NULL;
@ -576,16 +588,7 @@ static findVSpaceForASID_ret_t findVSpaceForASID(asid_t asid)
return ret;
}
vspace_root = poolPtr->array[asid & MASK(asidLowBits)];
if (!vspace_root) {
current_lookup_fault = lookup_fault_invalid_root_new();
ret.vspace_root = NULL;
ret.status = EXCEPTION_LOOKUP_FAULT;
return ret;
}
ret.vspace_root = vspace_root;
ret.vspace_root = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);
ret.status = EXCEPTION_NONE;
return ret;
}
@ -1078,8 +1081,10 @@ static void invalidateASID(asid_t asid)
asidPool = armKSASIDTable[asid >> asidLowBits];
assert(asidPool);
vspace_root_t *vtable = asidPool->array[asid & MASK(asidLowBits)];
assert(vtable);
asid_map_t asid_map = asidPool->array[asid & MASK(asidLowBits)];
assert(asid_map_get_type(asid_map) == asid_map_asid_map_vspace);
vspace_root_t *vtable = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);
vtable[VTABLE_VMID_SLOT] = vtable_invalid_new(0, false);
}
@ -1091,8 +1096,10 @@ static vspace_root_t PURE loadHWASID(asid_t asid)
asidPool = armKSASIDTable[asid >> asidLowBits];
assert(asidPool);
vspace_root_t *vtable = asidPool->array[asid & MASK(asidLowBits)];
assert(vtable);
asid_map_t asid_map = asidPool->array[asid & MASK(asidLowBits)];
assert(asid_map_get_type(asid_map) == asid_map_asid_map_vspace);
vspace_root_t *vtable = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);
return vtable[VTABLE_VMID_SLOT];
}
@ -1104,8 +1111,10 @@ static void storeHWASID(asid_t asid, hw_asid_t hw_asid)
asidPool = armKSASIDTable[asid >> asidLowBits];
assert(asidPool);
vspace_root_t *vtable = asidPool->array[asid & MASK(asidLowBits)];
assert(vtable);
asid_map_t asid_map = asidPool->array[asid & MASK(asidLowBits)];
assert(asid_map_get_type(asid_map) == asid_map_asid_map_vspace);
vspace_root_t *vtable = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);
/* Store HW VMID in the last entry
Masquerade as an invalid PDGE */
@ -1182,7 +1191,10 @@ static vspace_root_t getASIDBindCB(asid_t asid)
asidPool = armKSASIDTable[asid >> asidLowBits];
assert(asidPool);
vspace_root_t *vtable = asidPool->array[asid & MASK(asidLowBits)];
asid_map_t asid_map = asidPool->array[asid & MASK(asidLowBits)];
assert(asid_map_get_type(asid_map) == asid_map_asid_map_vspace);
vspace_root_t *vtable = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);;
assert(vtable);
return vtable[VTABLE_SMMU_SLOT];
@ -1196,7 +1208,10 @@ void increaseASIDBindCB(asid_t asid)
asidPool = armKSASIDTable[asid >> asidLowBits];
assert(asidPool);
vspace_root_t *vtable = asidPool->array[asid & MASK(asidLowBits)];
asid_map_t asid_map = asidPool->array[asid & MASK(asidLowBits)];
assert(asid_map_get_type(asid_map) == asid_map_asid_map_vspace);
vspace_root_t *vtable = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);;
assert(vtable);
stored_info = vtable[VTABLE_SMMU_SLOT];
@ -1211,7 +1226,10 @@ void decreaseASIDBindCB(asid_t asid)
asidPool = armKSASIDTable[asid >> asidLowBits];
assert(asidPool);
vspace_root_t *vtable = asidPool->array[asid & MASK(asidLowBits)];
asid_map_t asid_map = asidPool->array[asid & MASK(asidLowBits)];
assert(asid_map_get_type(asid_map) == asid_map_asid_map_vspace);
vspace_root_t *vtable = (vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map);;
assert(vtable);
stored_info = vtable[VTABLE_SMMU_SLOT];
@ -1404,13 +1422,17 @@ void deleteASID(asid_t asid, vspace_root_t *vspace)
poolPtr = armKSASIDTable[asid >> asidLowBits];
if (poolPtr != NULL && poolPtr->array[asid & MASK(asidLowBits)] == vspace) {
invalidateTLBByASID(asid);
if (poolPtr != NULL) {
asid_map_t asid_map = poolPtr->array[asid & MASK(asidLowBits)];
if (asid_map_get_type(asid_map) == asid_map_asid_map_vspace &&
(vspace_root_t *)asid_map_asid_map_vspace_get_vspace_root(asid_map) == vspace) {
invalidateTLBByASID(asid);
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
invalidateASIDEntry(asid);
invalidateASIDEntry(asid);
#endif
poolPtr->array[asid & MASK(asidLowBits)] = NULL;
setVMRoot(NODE_STATE(ksCurThread));
poolPtr->array[asid & MASK(asidLowBits)] = asid_map_asid_map_none_new();
setVMRoot(NODE_STATE(ksCurThread));
}
}
}
@ -1422,7 +1444,8 @@ void deleteASIDPool(asid_t asid_base, asid_pool_t *pool)
if (armKSASIDTable[asid_base >> asidLowBits] == pool) {
for (offset = 0; offset < BIT(asidLowBits); offset++) {
if (pool->array[offset]) {
asid_map_t asid_map = pool->array[offset];
if (asid_map_get_type(asid_map) == asid_map_asid_map_vspace) {
invalidateTLBByASID(asid_base + offset);
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
invalidateASIDEntry(asid_base + offset);
@ -2406,7 +2429,8 @@ exception_t decodeARMMMUInvocation(word_t invLabel, word_t length, cptr_t cptr,
/* Find first free ASID */
asid = cap_asid_pool_cap_get_capASIDBase(cap);
for (i = 0; i < (1 << asidLowBits) && (asid + i == 0 || pool->array[i]); i++);
for (i = 0; i < (1 << asidLowBits) && (asid + i == 0
|| (asid_map_get_type(pool->array[i]) != asid_map_asid_map_none)); i++);
if (unlikely(i == 1 << asidLowBits)) {
current_syscall_error.type = seL4_DeleteFirst;