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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
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]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -385,8 +390,10 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"buddy-alloc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cortex-a",
|
"cortex-a",
|
||||||
|
"once_cell",
|
||||||
"qemu-exit",
|
"qemu-exit",
|
||||||
"r0",
|
"r0",
|
||||||
"snafu",
|
"snafu",
|
||||||
|
|
|
@ -38,3 +38,5 @@ bit_field = "0.10"
|
||||||
bitflags = "1.3"
|
bitflags = "1.3"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
snafu = { version = "0.7", default-features = false }
|
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(format_args_nl)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(nonnull_slice_from_raw_parts)]
|
#![feature(nonnull_slice_from_raw_parts)]
|
||||||
#![feature(custom_test_frameworks)]
|
#![feature(custom_test_frameworks)]
|
||||||
#![test_runner(crate::tests::test_runner)]
|
#![test_runner(crate::tests::test_runner)]
|
||||||
|
@ -18,6 +19,12 @@
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
use architecture_not_supported_sorry;
|
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.
|
/// Architecture-specific code.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod arch;
|
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
|
/// The global allocator for DMA-able memory. That is, memory which is tagged
|
||||||
/// non-cacheable in the page tables.
|
/// non-cacheable in the page tables.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
static DMA_ALLOCATOR: sync::NullLock<mm::BumpAllocator> =
|
static DMA_ALLOCATOR: sync::NullLock<Lazy<BuddyAlloc>> =
|
||||||
sync::NullLock::new(mm::BumpAllocator::new(
|
sync::NullLock::new(Lazy::new(|| unsafe {
|
||||||
// @todo Init this after we loaded boot memory map
|
BuddyAlloc::new(BuddyAllocParam::new(
|
||||||
platform::memory::map::virt::DMA_HEAP_START as usize,
|
// @todo Init this after we loaded boot memory map
|
||||||
platform::memory::map::virt::DMA_HEAP_END as usize,
|
DMA_HEAP_START as *const u8,
|
||||||
"Global DMA Allocator",
|
DMA_HEAP_END - DMA_HEAP_START,
|
||||||
// Try the following arguments instead to see all mailbox operations
|
64,
|
||||||
// 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
|
// Try the following arguments instead to see all mailbox operations
|
||||||
// that resembles an error case instead.
|
// 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,
|
// 0x00600000 as usize,
|
||||||
// 0x007FFFFF as usize,
|
// 0x007FFFFF as usize,
|
||||||
// "Global Non-DMA Allocator",
|
|
||||||
));
|
|
||||||
|
|
|
@ -13,8 +13,11 @@
|
||||||
|
|
||||||
use {
|
use {
|
||||||
super::BcmHost,
|
super::BcmHost,
|
||||||
crate::{platform::MMIODerefWrapper, println},
|
crate::{platform::MMIODerefWrapper, println, DMA_ALLOCATOR},
|
||||||
core::{
|
core::{
|
||||||
|
alloc::{AllocError, Allocator, Layout},
|
||||||
|
mem,
|
||||||
|
ptr::NonNull,
|
||||||
result::Result as CoreResult,
|
result::Result as CoreResult,
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
},
|
},
|
||||||
|
@ -31,14 +34,14 @@ use {
|
||||||
/// The address for the buffer needs to be 16-byte aligned
|
/// The address for the buffer needs to be 16-byte aligned
|
||||||
/// so that the VideoCore can handle it properly.
|
/// so that the VideoCore can handle it properly.
|
||||||
/// The reason is that lowest 4 bits of the address will contain the channel number.
|
/// 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,
|
registers: Registers,
|
||||||
pub buffer: Storage,
|
pub buffer: Storage,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mailbox that is ready to be called.
|
/// Mailbox that is ready to be called.
|
||||||
/// This prevents invalid use of the mailbox until it is fully prepared.
|
/// 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>,
|
Mailbox<N_SLOTS, Storage>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -96,6 +99,8 @@ pub enum MailboxError {
|
||||||
Unknown,
|
Unknown,
|
||||||
#[snafu(display("Timeout"))]
|
#[snafu(display("Timeout"))]
|
||||||
Timeout,
|
Timeout,
|
||||||
|
#[snafu(display("AllocError"))]
|
||||||
|
Alloc,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = CoreResult<T, MailboxError>;
|
pub type Result<T> = CoreResult<T, MailboxError>;
|
||||||
|
@ -111,7 +116,9 @@ pub trait MailboxOps {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MailboxStorage {
|
pub trait MailboxStorage {
|
||||||
fn new() -> Self;
|
fn new() -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MailboxStorageRef {
|
pub trait MailboxStorageRef {
|
||||||
|
@ -127,11 +134,45 @@ pub struct LocalMailboxStorage<const N_SLOTS: usize> {
|
||||||
pub storage: [u32; N_SLOTS],
|
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> {
|
impl<const N_SLOTS: usize> MailboxStorage for LocalMailboxStorage<N_SLOTS> {
|
||||||
fn new() -> Self {
|
fn new() -> Result<Self> {
|
||||||
Self {
|
Ok(Self {
|
||||||
storage: [0u32; N_SLOTS],
|
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 https://elinux.org/RPi_Framebuffer
|
||||||
* Source for channels 8 and 9: https://github.com/raspberrypi/firmware/wiki/Mailboxes
|
* 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>> {
|
pub unsafe fn new(base_addr: usize) -> Result<Mailbox<N_SLOTS, Storage>> {
|
||||||
Ok(Mailbox {
|
Ok(Mailbox {
|
||||||
registers: Registers::new(base_addr),
|
registers: Registers::new(base_addr),
|
||||||
buffer: Storage::new(),
|
buffer: Storage::new()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue