diff options
Diffstat (limited to 'src/kern/mpu/mpu_manager.c')
-rw-r--r-- | src/kern/mpu/mpu_manager.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/kern/mpu/mpu_manager.c b/src/kern/mpu/mpu_manager.c new file mode 100644 index 0000000..614766a --- /dev/null +++ b/src/kern/mpu/mpu_manager.c @@ -0,0 +1,63 @@ +#include "arch.h" +#include "kern/mpu/mpu_manager.h" + +#include "arch/arm/cortex-m4/mpu.h" +#include "kern/common.h" +#include "kern/log.h" +#include "kern/panic.h" + +memory_region_opts_t memory_regions[8]; + +void mpu_set_enabled(bool enabled) +{ + if (enabled) { + regset(MPU.ctrl_r, mpu_en, 1); + __isb(); + __dsb(); + } else { + regset(MPU.ctrl_r, mpu_en, 0); + } +} + +void mpu_configure_region(int region_number, memory_region_opts_t* opts) +{ + if (region_number >= 8) { + panic("MPU can only handle 8 regions."); + } + + memory_regions[region_number] = *opts; + + uint32_t region = ptr2reg(opts->region); + + if (opts->size == REGION_SIZE_4Gb && region != 0) { + panic("Region pointer must be 0 for region size of 4Gb"); + } else if ((region & region_size_mask(opts->size))) { + panic("Memory region MUST be aligned with given size."); + } + + MPU.rn_r = region_number; + + uint32_t rbar = region; + regset(rbar, mpu_region, region_number); + regset(rbar, mpu_valid, 1); + + klogf("Writing RBAR: %p\n", rbar); + + uint32_t rasr = 0; + regset(rasr, mpu_en, opts->enable); + regset(rasr, mpu_size, opts->size); + regset(rasr, mpu_srd, opts->subregion_disable); + + regset(rasr, mpu_b, opts->bufferable); + regset(rasr, mpu_c, opts->cacheable); + regset(rasr, mpu_s, opts->sharable); + + regset(rasr, mpu_tex, opts->tex); + regset(rasr, mpu_ap, opts->perms); + regset(rasr, mpu_xn, !opts->executable); + + klogf("Writing RASR: %p\n", rasr); + + MPU.rba_r = rbar; + MPU.ras_r = rasr; +} |