aboutsummaryrefslogtreecommitdiff
path: root/src/kern/mpu/mpu_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kern/mpu/mpu_manager.c')
-rw-r--r--src/kern/mpu/mpu_manager.c63
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;
+}