aboutsummaryrefslogtreecommitdiff
path: root/src/kern/mpu/mpu_manager.c
blob: 614766abff3571c04dcb7ac41fb89a85f2611366 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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;
}