feat: ✨ Switch mailboxes to correct DMA-backed storage by default
Allocate DmaBackedMailboxStorage out of DMA_ALLOCATOR. Replace DMA bump_allocator with buddy_alloc.
This commit is contained in:
parent
07df330b62
commit
ddf6d09136
|
@ -67,6 +67,11 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "buddy-alloc"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/metta-systems/buddy-alloc?branch=feature/allocator-api#70c17c858100282252754981f13e9442b86e07e0"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
|
@ -385,8 +390,10 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"buddy-alloc",
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"once_cell",
|
||||
"qemu-exit",
|
||||
"r0",
|
||||
"snafu",
|
||||
|
|
|
@ -38,3 +38,5 @@ bit_field = "0.10"
|
|||
bitflags = "1.3"
|
||||
cfg-if = "1.0"
|
||||
snafu = { version = "0.7", default-features = false }
|
||||
buddy-alloc = { git = "https://github.com/metta-systems/buddy-alloc", version = "0.5.0", branch = "feature/allocator-api" }
|
||||
once_cell = { version = "1.10.0", default-features = false, features = ["unstable"] }
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(format_args_nl)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(crate::tests::test_runner)]
|
||||
|
@ -18,6 +19,12 @@
|
|||
#[cfg(not(target_arch = "aarch64"))]
|
||||
use architecture_not_supported_sorry;
|
||||
|
||||
use {
|
||||
buddy_alloc::{BuddyAlloc, BuddyAllocParam},
|
||||
once_cell::unsync::Lazy,
|
||||
platform::memory::map::virt::{DMA_HEAP_END, DMA_HEAP_START},
|
||||
};
|
||||
|
||||
/// Architecture-specific code.
|
||||
#[macro_use]
|
||||
pub mod arch;
|
||||
|
@ -41,19 +48,20 @@ pub static CONSOLE: sync::NullLock<devices::Console> = sync::NullLock::new(devic
|
|||
/// The global allocator for DMA-able memory. That is, memory which is tagged
|
||||
/// non-cacheable in the page tables.
|
||||
#[allow(dead_code)]
|
||||
static DMA_ALLOCATOR: sync::NullLock<mm::BumpAllocator> =
|
||||
sync::NullLock::new(mm::BumpAllocator::new(
|
||||
// @todo Init this after we loaded boot memory map
|
||||
platform::memory::map::virt::DMA_HEAP_START as usize,
|
||||
platform::memory::map::virt::DMA_HEAP_END as usize,
|
||||
"Global DMA Allocator",
|
||||
// Try the following arguments instead to see all mailbox operations
|
||||
// fail. It will cause the allocator to use memory that are marked
|
||||
// cacheable and therefore not DMA-safe. The answer from the VideoCore
|
||||
// won't be received by the CPU because it reads an old cached value
|
||||
// that resembles an error case instead.
|
||||
static DMA_ALLOCATOR: sync::NullLock<Lazy<BuddyAlloc>> =
|
||||
sync::NullLock::new(Lazy::new(|| unsafe {
|
||||
BuddyAlloc::new(BuddyAllocParam::new(
|
||||
// @todo Init this after we loaded boot memory map
|
||||
DMA_HEAP_START as *const u8,
|
||||
DMA_HEAP_END - DMA_HEAP_START,
|
||||
64,
|
||||
))
|
||||
}));
|
||||
// Try the following arguments instead to see all mailbox operations
|
||||
// fail. It will cause the allocator to use memory that are marked
|
||||
// cacheable and therefore not DMA-safe. The answer from the VideoCore
|
||||
// won't be received by the CPU because it reads an old cached value
|
||||
// that resembles an error case instead.
|
||||
|
||||
// 0x00600000 as usize,
|
||||
// 0x007FFFFF as usize,
|
||||
// "Global Non-DMA Allocator",
|
||||
));
|
||||
// 0x00600000 as usize,
|
||||
// 0x007FFFFF as usize,
|
||||
|
|
|
@ -13,8 +13,11 @@
|
|||
|
||||
use {
|
||||
super::BcmHost,
|
||||
crate::{platform::MMIODerefWrapper, println},
|
||||
crate::{platform::MMIODerefWrapper, println, DMA_ALLOCATOR},
|
||||
core::{
|
||||
alloc::{AllocError, Allocator, Layout},
|
||||
mem,
|
||||
ptr::NonNull,
|
||||
result::Result as CoreResult,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
},
|
||||
|
@ -31,14 +34,14 @@ use {
|
|||
/// The address for the buffer needs to be 16-byte aligned
|
||||
/// so that the VideoCore can handle it properly.
|
||||
/// The reason is that lowest 4 bits of the address will contain the channel number.
|
||||
pub struct Mailbox<const N_SLOTS: usize, Storage = LocalMailboxStorage<N_SLOTS>> {
|
||||
pub struct Mailbox<const N_SLOTS: usize, Storage = DmaBackedMailboxStorage<N_SLOTS>> {
|
||||
registers: Registers,
|
||||
pub buffer: Storage,
|
||||
}
|
||||
|
||||
/// Mailbox that is ready to be called.
|
||||
/// This prevents invalid use of the mailbox until it is fully prepared.
|
||||
pub struct PreparedMailbox<const N_SLOTS: usize, Storage = LocalMailboxStorage<N_SLOTS>>(
|
||||
pub struct PreparedMailbox<const N_SLOTS: usize, Storage = DmaBackedMailboxStorage<N_SLOTS>>(
|
||||
Mailbox<N_SLOTS, Storage>,
|
||||
);
|
||||
|
||||
|
@ -96,6 +99,8 @@ pub enum MailboxError {
|
|||
Unknown,
|
||||
#[snafu(display("Timeout"))]
|
||||
Timeout,
|
||||
#[snafu(display("AllocError"))]
|
||||
Alloc,
|
||||
}
|
||||
|
||||
pub type Result<T> = CoreResult<T, MailboxError>;
|
||||
|
@ -111,7 +116,9 @@ pub trait MailboxOps {
|
|||
}
|
||||
|
||||
pub trait MailboxStorage {
|
||||
fn new() -> Self;
|
||||
fn new() -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait MailboxStorageRef {
|
||||
|
@ -127,11 +134,45 @@ pub struct LocalMailboxStorage<const N_SLOTS: usize> {
|
|||
pub storage: [u32; N_SLOTS],
|
||||
}
|
||||
|
||||
pub struct DmaBackedMailboxStorage<const N_SLOTS: usize> {
|
||||
pub storage: *mut u32,
|
||||
}
|
||||
|
||||
impl<const N_SLOTS: usize> MailboxStorage for LocalMailboxStorage<N_SLOTS> {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
fn new() -> Result<Self> {
|
||||
Ok(Self {
|
||||
storage: [0u32; N_SLOTS],
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N_SLOTS: usize> MailboxStorage for DmaBackedMailboxStorage<N_SLOTS> {
|
||||
fn new() -> Result<Self> {
|
||||
Ok(Self {
|
||||
storage: DMA_ALLOCATOR
|
||||
.lock(|a| {
|
||||
a.allocate(
|
||||
Layout::from_size_align(N_SLOTS * mem::size_of::<u32>(), 16)
|
||||
.map_err(|_| AllocError)?,
|
||||
)
|
||||
})
|
||||
.map_err(|_| MailboxError::Alloc)?
|
||||
.as_mut_ptr() as *mut u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N_SLOTS: usize> Drop for DmaBackedMailboxStorage<N_SLOTS> {
|
||||
fn drop(&mut self) {
|
||||
DMA_ALLOCATOR
|
||||
.lock::<_, Result<()>>(|a| unsafe {
|
||||
Ok(a.deallocate(
|
||||
NonNull::new_unchecked(self.storage as *mut u8),
|
||||
Layout::from_size_align(N_SLOTS * mem::size_of::<u32>(), 16)
|
||||
.map_err(|_| MailboxError::Alloc)?,
|
||||
))
|
||||
})
|
||||
.unwrap_or(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +195,25 @@ impl<const N_SLOTS: usize> MailboxStorageRef for LocalMailboxStorage<N_SLOTS> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N_SLOTS: usize> MailboxStorageRef for DmaBackedMailboxStorage<N_SLOTS> {
|
||||
fn as_ref(&self) -> &[u32] {
|
||||
unsafe { core::slice::from_raw_parts(self.storage.cast(), N_SLOTS) }
|
||||
}
|
||||
|
||||
fn as_mut(&mut self) -> &mut [u32] {
|
||||
unsafe { core::slice::from_raw_parts_mut(self.storage.cast(), N_SLOTS) }
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const u32 {
|
||||
self.storage.cast()
|
||||
}
|
||||
|
||||
// @todo Probably need a ResultMailbox for accessing data after call()?
|
||||
fn value_at(&self, index: usize) -> u32 {
|
||||
self.as_ref()[index]
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Source https://elinux.org/RPi_Framebuffer
|
||||
* Source for channels 8 and 9: https://github.com/raspberrypi/firmware/wiki/Mailboxes
|
||||
|
@ -315,7 +375,7 @@ impl<const N_SLOTS: usize, Storage: MailboxStorage + MailboxStorageRef> Mailbox<
|
|||
pub unsafe fn new(base_addr: usize) -> Result<Mailbox<N_SLOTS, Storage>> {
|
||||
Ok(Mailbox {
|
||||
registers: Registers::new(base_addr),
|
||||
buffer: Storage::new(),
|
||||
buffer: Storage::new()?,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue