Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/arch/armv8/armv8-r/inc/arch/mpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
60 changes: 13 additions & 47 deletions src/arch/armv8/armv8-r/mpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,6 @@
#include <arch/sysregs.h>
#include <arch/fences.h>

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;
Expand All @@ -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;
}
Expand All @@ -59,33 +36,22 @@ 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;
}

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)
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
}
1 change: 1 addition & 0 deletions src/core/inc/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down