Skip to content

Commit 0e24841

Browse files
robhancocksedkartben
authored andcommitted
arch: arm: cortex_a_r: Fix memory corruption when disabling dcache
On the Xilinx MPSoC (Cortex-R5) platform, erratic operation was often seen when an operation which disabled the dcache, such as sys_reboot, was performed. Usually this manifested as an undefined instruction trap due to the CPU jumping to an invalid memory address. It appears the problem was due to dirty cache lines being present at the time the cache is disabled. Once the cache is disabled, the CPU will ignore the cache contents and read the possibly out-of-date data in main memory. Likewise, since the cache was being cleaned after it was already disabled, if the CPU had already written through changes to some memory locations, cleaning the cache at that point would potentially overwrite those changes with older data. The fact that the arch_dcache_flush_and_invd_all function was being called to do the cleaning and invalidation also contributed to this problem, because it is a non-inline function which means the compiler will generate memory writes to the stack when the function is called and returns. Corruption of the stack can result in the CPU ending up jumping to garbage addresses when trying to return from functions. To avoid this problem, the cache is now cleaned and invalidated prior to the dcache being disabled. This is done by directly calling the L1C_CleanInvalidateDCacheAll function, which, as it is declared as force inline, should help ensure there are no memory accesses, which would populate new cache lines, between the cache cleaning and disabling the cache. Ideally, for maximum safety, the cache cleaning and cache disabling should be done in assembler code, to guarantee that there are no memory accesses generated by the compiler during these operations. However, the present change does appear to solve this issue. Signed-off-by: Robert Hancock <[email protected]>
1 parent d0aa263 commit 0e24841

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

arch/arm/core/cortex_a_r/cache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ void arch_dcache_disable(void)
6363
{
6464
uint32_t val;
6565

66+
L1C_CleanInvalidateDCacheAll();
67+
6668
val = __get_SCTLR();
6769
val &= ~SCTLR_C_Msk;
6870
barrier_dsync_fence_full();
6971
__set_SCTLR(val);
7072
barrier_isync_fence_full();
71-
72-
arch_dcache_flush_and_invd_all();
7373
}
7474

7575
int arch_dcache_flush_all(void)

0 commit comments

Comments
 (0)