mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
Kernel/aarch64: Flush the D-cache before reading back RPi mailbox data
Since we currently can't use MM to allocate a DMA buffer for the RPi mailbox (as it needs to be below 1G), we can't map it as Non-cacheable, and instead need to rely on manual cache maintenance operations. We previously forgot to flush the cache again before reading back data, which is required on ARM systems, as explained in the comment. (See also https://events.static.linuxfound.org/sites/events/files/slides/slides_17.pdf and the DMA examples at https://support.arm.com/documentation/ddi0487/mc/-Part-K-Appendixes/-Appendix-K11-Barrier-Litmus-Tests/-K11-5-Cache-and-TLB-maintenance-instructions-and-barriers/-K11-5-1-Data-cache-maintenance-instructions.) This appears to have fixed the "Failed to get the RPi CPU temperature" messages that occur every so often. In the future, we should instead make MM somehow be able to return DMA buffers below a given address threshold for legacy bus masters, such as the mailbox peripheral in Raspberry Pis. MM should also somehow try to make sure that some low memory stays available for legacy DMA peripherals and otherwise potentially fall back to bounce pages.
This commit is contained in:
1 parent
f414ac22bd
commit
6a04d4a37b
1 file changed
+11
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Arch/MemoryFences.h>
|
||||
#include <Kernel/Arch/aarch64/ASM_wrapper.h>
|
||||
#include <Kernel/Arch/aarch64/RPi/Mailbox.h>
|
||||
#include <Kernel/Memory/MemoryManager.h>
|
||||
@@ -137,6 +138,16 @@ bool Mailbox::send_queue(void* queue, u32 queue_size)
|
||||
u32 response = m_registers->read_data;
|
||||
// We keep at most one message in flight and do synchronous communication, so response will always be == request for us.
|
||||
if (response == request) {
|
||||
// Ensure that the data cache flush and memcpy() are done after the response == request check.
|
||||
full_memory_fence();
|
||||
|
||||
// Ensure that stale cache lines are discarded before reading from the buffer.
|
||||
// Cacheable memory regions can be allocated into cache lines at any time, e.g. because they were prefetched or speculatively read.
|
||||
// We could use an invalidate-only cache operation here (flush_data_cache() both cleans and invalidates),
|
||||
// but then we'd need to ensure that the buffer is aligned to the cache line size
|
||||
// (which can vary from processor to processor) to not accidentally delete unrelated data from the caches.
|
||||
Processor::flush_data_cache(VirtualAddress { &transfer_buffer }, queue_size);
|
||||
|
||||
memcpy(queue, transfer_buffer, queue_size);
|
||||
return message_header->success();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user