diff --git a/src/arch/armv8/armv8-r/inc/arch/mpu.h b/src/arch/armv8/armv8-r/inc/arch/mpu.h index 53123ae5..32d20c9f 100644 --- a/src/arch/armv8/armv8-r/inc/arch/mpu.h +++ b/src/arch/armv8/armv8-r/inc/arch/mpu.h @@ -14,6 +14,7 @@ struct mpu_arch { BITMAP_ALLOC(allocated_entries, MPU_ARCH_MAX_NUM_ENTRIES); BITMAP_ALLOC(locked_entries, MPU_ARCH_MAX_NUM_ENTRIES); + asid_t entry_asid[MPU_ARCH_MAX_NUM_ENTRIES]; }; bool mpu_perms_compatible(unsigned long perms1, unsigned long perms2); diff --git a/src/arch/armv8/armv8-r/mpu.c b/src/arch/armv8/armv8-r/mpu.c index a43015a9..e7d38da9 100644 --- a/src/arch/armv8/armv8-r/mpu.c +++ b/src/arch/armv8/armv8-r/mpu.c @@ -9,19 +9,6 @@ #include #include -static priv_t mpu_as_priv(struct addr_space* as) -{ - priv_t priv; - - if (as->type == AS_VM) { - priv = PRIV_VM; - } else { - priv = PRIV_HYP; - } - - return priv; -} - static unsigned long mpu_get_region_base(mpid_t mpid) { unsigned long prbar = 0; @@ -33,24 +20,14 @@ static unsigned long mpu_get_region_base(mpid_t mpid) return PRBAR_BASE(prbar); } -static unsigned long mpu_get_region_limit(mpid_t mpid) -{ - unsigned long prlar = 0; - - sysreg_prselr_el2_write(mpid); - ISB(); - prlar = sysreg_prlar_el2_read(); - - return PRLAR_LIMIT(prlar); -} - -static mpid_t mpu_find_region_base(struct mp_region* mpr) +static mpid_t mpu_find_region(struct mp_region* mpr, asid_t asid) { mpid_t mpid = INVALID_MPID; for (mpid_t i = 0; i < MPU_ARCH_MAX_NUM_ENTRIES; i++) { if (bitmap_get(cpu()->arch.profile.mpu.allocated_entries, i)) { - if (mpu_get_region_base(i) == mpr->base) { + if (mpu_get_region_base(i) == mpr->base && + cpu()->arch.profile.mpu.entry_asid[i] == asid) { mpid = i; break; } @@ -59,26 +36,14 @@ static mpid_t mpu_find_region_base(struct mp_region* mpr) return mpid; } -static mpid_t mpu_find_region_exact(struct mp_region* mpr) -{ - mpid_t mpid = mpu_find_region_base(mpr); - - if (mpid != INVALID_MPID) { - if (mpu_get_region_limit(mpid) == PRLAR_LIMIT(mpr->base + mpr->size - 1)) { - return mpid; - } - } - - return INVALID_MPID; -} - -static mpid_t mpu_entry_allocate(void) +static mpid_t mpu_entry_allocate(asid_t asid) { mpid_t reg_num = INVALID_MPID; reg_num = (mpid_t)bitmap_find_nth(cpu()->arch.profile.mpu.allocated_entries, MPU_ARCH_MAX_NUM_ENTRIES, 1, 0, false); bitmap_set(cpu()->arch.profile.mpu.allocated_entries, reg_num); + cpu()->arch.profile.mpu.entry_asid[reg_num] = asid; return reg_num; } @@ -86,6 +51,7 @@ static mpid_t mpu_entry_allocate(void) static inline void mpu_entry_deallocate(mpid_t mpid) { bitmap_clear(cpu()->arch.profile.mpu.allocated_entries, mpid); + cpu()->arch.profile.mpu.entry_asid[mpid] = INVALID_ASID; } static inline void mpu_entry_lock(mpid_t mpid) @@ -132,7 +98,6 @@ static bool mpu_entry_clear(mpid_t mpid) bool mpu_map(struct addr_space* as, struct mp_region* mpr, bool locked) { mpid_t mpid = INVALID_MPID; - priv_t priv = mpu_as_priv(as); if (mpr->size == 0) { return false; @@ -145,14 +110,16 @@ bool mpu_map(struct addr_space* as, struct mp_region* mpr, bool locked) */ else { - mpid = mpu_entry_allocate(); + mpid = mpu_entry_allocate(as->id); if (mpid != INVALID_MPID) { if (locked) { mpu_entry_lock(mpid); } bitmap_set((bitmap_t*)&as->arch.mpu_entry_mask, mpid); - if (priv == PRIV_VM) { + if (as->type == AS_VM) { mpr->mem_flags.prlar &= (uint16_t)~PRLAR_EN; + } else if (as->type == AS_HYP || as->type == AS_HYP_CPY) { + mpr->mem_flags.prlar |= (uint16_t)PRLAR_EN; } mpu_entry_set(mpid, mpr); } @@ -164,7 +131,7 @@ bool mpu_map(struct addr_space* as, struct mp_region* mpr, bool locked) bool mpu_unmap(struct addr_space* as, struct mp_region* mpr) { UNUSED_ARG(as); - mpid_t mpid = mpu_find_region_exact(mpr); + mpid_t mpid = mpu_find_region(mpr, as->id); if (mpid != INVALID_MPID) { mpu_entry_deallocate(mpid); @@ -180,9 +147,7 @@ bool mpu_unmap(struct addr_space* as, struct mp_region* mpr) bool mpu_update(struct addr_space* as, struct mp_region* mpr) { - UNUSED_ARG(as); - - mpid_t mpid = mpu_find_region_base(mpr); + mpid_t mpid = mpu_find_region(mpr, as->id); if (mpid != INVALID_MPID) { mpu_entry_update_limit(mpid, mpr); @@ -213,5 +178,6 @@ void mpu_init() for (mpid_t mpid = 0; mpid < MPU_ARCH_MAX_NUM_ENTRIES; mpid++) { bitmap_clear(cpu()->arch.profile.mpu.allocated_entries, mpid); bitmap_clear(cpu()->arch.profile.mpu.locked_entries, mpid); + cpu()->arch.profile.mpu.entry_asid[mpid] = INVALID_ASID; } } diff --git a/src/core/inc/types.h b/src/core/inc/types.h index 234f884a..b07ce90d 100644 --- a/src/core/inc/types.h +++ b/src/core/inc/types.h @@ -23,6 +23,7 @@ typedef signed long ssize_t; typedef unsigned long asid_t; +#define INVALID_ASID ((asid_t)~0UL) typedef unsigned long vmid_t; #define INVALID_VMID ((vmid_t)~0UL)