diff options
author | Joe Komlodi <komlodi@google.com> | 2025-03-10 20:36:22 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2025-03-14 12:54:33 +0000 |
commit | e6c38d2ab55d66c74ceade5699e22cabe9058d22 (patch) | |
tree | 88a7539c2d62b5aef6cb776c53c48fa8c11e0dfa | |
parent | 5b14454d37854f5c4227d642133a477a07e49759 (diff) | |
download | qemu-e6c38d2ab55d66c74ceade5699e22cabe9058d22.zip qemu-e6c38d2ab55d66c74ceade5699e22cabe9058d22.tar.gz qemu-e6c38d2ab55d66c74ceade5699e22cabe9058d22.tar.bz2 |
util/cacheflush: Make first DSB unconditional on aarch64
On ARM hosts with CTR_EL0.DIC and CTR_EL0.IDC set, this would only cause
an ISB to be executed during cache maintenance, which could lead to QEMU
executing TBs containing garbage instructions.
This seems to be because the ISB finishes executing instructions and
flushes the pipeline, but the ISB doesn't guarantee that writes from the
executed instructions are committed. If a small enough TB is created, it's
possible that the writes setting up the TB aren't committed by the time the
TB is executed.
This function is intended to be a port of the gcc implementation
(https://github.com/gcc-mirror/gcc/blob/85b46d0795ac76bc192cb8f88b646a647acf98c1/libgcc/config/aarch64/sync-cache.c#L67)
which makes the first DSB unconditional, so we can fix the synchronization
issue by doing that as well.
Cc: qemu-stable@nongnu.org
Fixes: 664a79735e4deb1 ("util: Specialize flush_idcache_range for aarch64")
Signed-off-by: Joe Komlodi <komlodi@google.com>
Message-id: 20250310203622.1827940-2-komlodi@google.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | util/cacheflush.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/util/cacheflush.c b/util/cacheflush.c index a089061..1d12899 100644 --- a/util/cacheflush.c +++ b/util/cacheflush.c @@ -279,9 +279,11 @@ void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len) for (p = rw & -dcache_lsize; p < rw + len; p += dcache_lsize) { asm volatile("dc\tcvau, %0" : : "r" (p) : "memory"); } - asm volatile("dsb\tish" : : : "memory"); } + /* DSB unconditionally to ensure any outstanding writes are committed. */ + asm volatile("dsb\tish" : : : "memory"); + /* * If CTR_EL0.DIC is enabled, Instruction cache cleaning to the Point * of Unification is not required for instruction to data coherence. |