Skip to content

Commit ac3dccc

Browse files
hexagonal-sunarihant2math
authored andcommitted
arch: arm64: memory: fix cache flush for non-cache aligned addrs
If an object isn't aligned to a cache line boundary, the flush loop advances by a full cache line stride from the misaligned start address. This can cause the pointer to overshoot the object end before reaching the next cache line, leaving it unflushed. This was observed on secondary CPU bringup where the boot context struct was not cache-line aligned, causing the secondary core to read stale data from RAM for fields in the second cache line. Fix this by aligning the start address down to a cache line boundary before iterating.
1 parent d838add commit ac3dccc

File tree

1 file changed

+8
-12
lines changed

1 file changed

+8
-12
lines changed

src/arch/arm64/memory/mod.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,25 @@ pub fn translate_kernel_va(addr: VA) -> PA {
6363
PA::from_value(v + get_kimage_start().value())
6464
}
6565

66-
pub fn flush_to_ram<T>(mut x: *const T) {
67-
let mut stride: u64 = 0;
66+
pub fn flush_to_ram<T>(x: *const T) {
67+
let mut stride: usize = 0;
6868

6969
// Calc cache line stride.
7070
unsafe { asm!("mrs {0}, ctr_el0", out(reg) stride, options(nostack, nomem)) };
7171
stride = (1 << ((stride >> 16) & 0xf)) * 4;
7272

73-
let end = unsafe { x.byte_add(size_of::<T>()) };
73+
let end = unsafe { x.byte_add(size_of::<T>()) } as usize;
74+
let mut addr = (x as usize) & !(stride - 1); // align down
7475

75-
while x < end {
76+
while addr < end {
7677
// Clear the cache line for the given VA.
77-
//
78-
// NOTE: We allow the below lint since a flush to the cache is
79-
// transparrent; memory hasn't changed from the point of view of the
80-
// flushing core.
81-
#[allow(clippy::pointers_in_nomem_asm_block)]
8278
unsafe {
83-
asm!("dc cvac, {0}", in(reg) x, options(nostack, nomem));
79+
asm!("dc cvac, {0}", in(reg) addr, options(nostack));
8480

85-
x = x.byte_add(stride as _);
81+
addr += stride;
8682
}
8783
}
8884

8985
// Ensure the cache maintaince op has finished.
90-
unsafe { asm!("dsb ish", options(nostack, nomem)) };
86+
unsafe { asm!("dsb ish", options(nostack)) };
9187
}

0 commit comments

Comments
 (0)