arch: arm64: mpu: Use BR mode to flush the MPU regions
Using BR(background region) during the flushing regions instead of
enabling/disabling the MPU which is a heavy operation.
Signed-off-by: Jaxson Han <jaxson.han@arm.com>
diff --git a/arch/arm64/core/cortex_r/arm_mpu.c b/arch/arm64/core/cortex_r/arm_mpu.c
index f849021..4575959 100644
--- a/arch/arm64/core/cortex_r/arm_mpu.c
+++ b/arch/arm64/core/cortex_r/arm_mpu.c
@@ -222,6 +222,28 @@
static struct dynamic_region_info sys_dyn_regions[MPU_DYNAMIC_REGION_AREAS_NUM];
static int sys_dyn_regions_num;
+static void arm_core_mpu_background_region_enable(void)
+{
+ uint64_t val;
+
+ val = read_sctlr_el1();
+ val |= SCTLR_BR_BIT;
+ write_sctlr_el1(val);
+ barrier_dsync_fence_full();
+ barrier_isync_fence_full();
+}
+
+static void arm_core_mpu_background_region_disable(void)
+{
+ uint64_t val;
+
+ val = read_sctlr_el1();
+ val &= ~SCTLR_BR_BIT;
+ write_sctlr_el1(val);
+ barrier_dsync_fence_full();
+ barrier_isync_fence_full();
+}
+
static int dynamic_areas_init(uintptr_t start, size_t size)
{
const struct arm_mpu_region *region;
@@ -474,9 +496,9 @@
region_num = (uint8_t)ret2;
}
- arm_core_mpu_disable();
+ arm_core_mpu_background_region_enable();
ret = flush_dynamic_regions_to_mpu(dyn_regions, region_num);
- arm_core_mpu_enable();
+ arm_core_mpu_background_region_disable();
out:
return ret;
diff --git a/include/zephyr/arch/arm64/cpu.h b/include/zephyr/arch/arm64/cpu.h
index 3b30a80..bd29195 100644
--- a/include/zephyr/arch/arm64/cpu.h
+++ b/include/zephyr/arch/arm64/cpu.h
@@ -52,6 +52,7 @@
#define SCTLR_C_BIT BIT(2)
#define SCTLR_SA_BIT BIT(3)
#define SCTLR_I_BIT BIT(12)
+#define SCTLR_BR_BIT BIT(17)
#define CPACR_EL1_FPEN_NOTRAP (0x3 << 20)