diff --git a/arch/arm64/core/cortex_r/arm_mpu.c b/arch/arm64/core/cortex_r/arm_mpu.c index 264d1ec59e..2ecdb52571 100644 --- a/arch/arm64/core/cortex_r/arm_mpu.c +++ b/arch/arm64/core/cortex_r/arm_mpu.c @@ -14,6 +14,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(mpu, CONFIG_MPU_LOG_LEVEL); @@ -62,8 +63,12 @@ static inline uint8_t get_num_regions(void) /** * @brief enable the MPU + * + * On the SMP system, The function that enables MPU can not insert stack protector + * code because the canary values read by the secondary CPUs before enabling MPU + * and after enabling it are not equal due to cache coherence issues. */ -void arm_core_mpu_enable(void) +FUNC_NO_STACK_PROTECTOR void arm_core_mpu_enable(void) { uint64_t val; @@ -110,7 +115,12 @@ static void mpu_init(void) barrier_isync_fence_full(); } -static inline void mpu_set_region(uint32_t rnr, uint64_t rbar, +/* + * Changing the MPU region may change the cache related attribute and cause + * cache coherence issues, so it's necessary to avoid invoking functions in such + * critical scope to avoid memory access before the MPU regions are all configured. + */ +static ALWAYS_INLINE void mpu_set_region(uint32_t rnr, uint64_t rbar, uint64_t rlar) { write_prselr_el1(rnr); @@ -135,8 +145,14 @@ static inline void mpu_clr_region(uint32_t rnr) barrier_isync_fence_full(); } -/* This internal functions performs MPU region initialization. */ -static void region_init(const uint32_t index, +/* + * This internal functions performs MPU region initialization. + * + * Changing the MPU region may change the cache related attribute and cause + * cache coherence issues, so it's necessary to avoid invoking functions in such + * critical scope to avoid memory access before the MPU regions are all configured. + */ +static ALWAYS_INLINE void region_init(const uint32_t index, const struct arm_mpu_region *region_conf) { uint64_t rbar = region_conf->base & MPU_RBAR_BASE_Msk; @@ -156,8 +172,12 @@ static void region_init(const uint32_t index, * * This function here provides the default configuration mechanism * for the Memory Protection Unit (MPU). + * + * On the SMP system, The function that enables MPU can not insert stack protector + * code because the canary values read by the secondary CPUs before enabling MPU + * and after enabling it are not equal due to cache coherence issues. */ -void z_arm64_mm_init(bool is_primary_core) +FUNC_NO_STACK_PROTECTOR void z_arm64_mm_init(bool is_primary_core) { uint64_t val; uint32_t r_index; @@ -396,9 +416,13 @@ static int flush_dynamic_regions_to_mpu(struct dynamic_region_info *dyn_regions, int ret = 0; arm_core_mpu_background_region_enable(); + /* * Clean the dynamic regions + * Before cleaning them, we need to flush dyn_regions to memory, because we need to read it + * in updating mpu region. */ + sys_cache_data_flush_range(dyn_regions, sizeof(struct dynamic_region_info) * region_num); for (size_t i = reg_avail_idx; i < get_num_regions(); i++) { mpu_clr_region(i); } diff --git a/arch/arm64/core/reset.c b/arch/arm64/core/reset.c index 929bb38091..bd78555de5 100644 --- a/arch/arm64/core/reset.c +++ b/arch/arm64/core/reset.c @@ -173,6 +173,7 @@ void z_arm64_el1_init(void) reg = read_sctlr_el1(); reg |= (SCTLR_EL1_RES1 | /* RES1 */ SCTLR_I_BIT | /* Enable i-cache */ + SCTLR_C_BIT | /* Enable d-cache */ SCTLR_SA_BIT); /* Enable SP alignment check */ write_sctlr_el1(reg);