diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2023-05-16 15:27:50 +0200 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2023-05-17 01:38:03 -0600 |
commit | 3d383974cdb0cc653aa133ae8834304b14113291 (patch) | |
tree | 2ef258ec52d136991510c465761f8c74bc78ca73 | |
parent | 0cbcdb227f5c3318170235c3cd20bfdc5ada4086 (diff) | |
download | serenity-3d383974cdb0cc653aa133ae8834304b14113291.zip |
Kernel: Flush data cache before passing a buffer to the VC Mailbox
Otherwise, the message's contents might be in the cache only, so
VideoCore will read stale/garbage data from main memory.
This fixes framebuffer setup on bare metal with the data cache enabled.
-rw-r--r-- | Kernel/Arch/aarch64/ASM_wrapper.h | 19 | ||||
-rw-r--r-- | Kernel/Arch/aarch64/RPi/Mailbox.cpp | 5 |
2 files changed, 24 insertions, 0 deletions
diff --git a/Kernel/Arch/aarch64/ASM_wrapper.h b/Kernel/Arch/aarch64/ASM_wrapper.h index f28d14fcc8..ebe7672bd2 100644 --- a/Kernel/Arch/aarch64/ASM_wrapper.h +++ b/Kernel/Arch/aarch64/ASM_wrapper.h @@ -125,6 +125,25 @@ inline u64 read_rndrrs() return value; } +inline FlatPtr get_cache_line_size() +{ + FlatPtr ctr_el0; + asm volatile("mrs %[value], ctr_el0" + : [value] "=r"(ctr_el0)); + auto log2_size = (ctr_el0 >> 16) & 0xF; + return 1 << log2_size; +} + +inline void flush_data_cache(FlatPtr start, size_t size) +{ + auto const cache_size = get_cache_line_size(); + for (FlatPtr addr = align_down_to(start, cache_size); addr < start + size; addr += cache_size) + asm volatile("dc civac, %[addr]" ::[addr] "r"(addr) + : "memory"); + asm volatile("dsb sy" :: + : "memory"); +} + } namespace Kernel { diff --git a/Kernel/Arch/aarch64/RPi/Mailbox.cpp b/Kernel/Arch/aarch64/RPi/Mailbox.cpp index 9ac0849591..e5278e9f1f 100644 --- a/Kernel/Arch/aarch64/RPi/Mailbox.cpp +++ b/Kernel/Arch/aarch64/RPi/Mailbox.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Arch/aarch64/ASM_wrapper.h> #include <Kernel/Arch/aarch64/RPi/MMIO.h> #include <Kernel/Arch/aarch64/RPi/Mailbox.h> @@ -90,6 +91,10 @@ bool Mailbox::send_queue(void* queue, u32 queue_size) const // The mailbox message is 32-bit based, so this assumes that message is in the first 4 GiB. u32 request = static_cast<u32>(reinterpret_cast<FlatPtr>(queue) & ~0xF) | (channel & 0xF); + + // The queue buffer might point to normal cached memory, so flush any writes that are in cache and not visible to VideoCore. + Aarch64::Asm::flush_data_cache((FlatPtr)queue, queue_size); + mmio.write(MBOX_WRITE_DATA, request); for (;;) { |