Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dma: Remove use of Cell<Option<>> in DMA driver #1946

Merged
merged 3 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 40 additions & 57 deletions drivers/src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,36 +113,25 @@ pub struct DmaWriteTransaction {
}

/// Dma Widget
pub struct Dma {
dma: Cell<Option<AxiDmaReg>>,
}
/// Safety: only one instance of the DMA widget should be created.
#[derive(Default)]
pub struct Dma {}

impl Dma {
/// Create a new DMA instance
///
/// # Arguments
///
/// * `dma` - DMA register block
pub fn new(dma: AxiDmaReg) -> Self {
Self {
dma: Cell::new(Some(dma)),
}
}

pub fn with_dma<T>(
&self,
f: impl FnOnce(RegisterBlock<RealMmioMut>) -> T,
) -> CaliptraResult<T> {
if let Some(mut dma) = self.dma.take() {
let result = f(dma.regs_mut());
self.dma.set(Some(dma));
Ok(result)
} else {
Err(CaliptraError::DRIVER_DMA_INTERNAL) // should never happen
}
}

pub fn flush(&self) -> CaliptraResult<()> {
/// Safety: This should never be called in a nested manner to avoid
/// programming conflicts with the underlying DMA registers.
pub fn with_dma<T>(&self, f: impl FnOnce(RegisterBlock<RealMmioMut>) -> T) -> T {
// Safety: Caliptra is single-threaded and only one caller to with_dma
// is allowed at a time, so it is safe to create and consume the
// zero-sized AxiDmaReg here and create a new one each time.
// Since the Mmio interface is immutable, we can't generate a
// around mutable reference to a shared AxiDmaReg without using
// Cell, which bloats the code.
let mut dma = unsafe { AxiDmaReg::new() };
f(dma.regs_mut())
}

pub fn flush(&self) {
self.with_dma(|dma| {
dma.ctrl().write(|c| c.flush(true));
// Wait till we're not busy and have no errors
Expand All @@ -156,11 +145,11 @@ impl Dma {
})
}

pub fn set_block_size(&self, block_size: u32) -> CaliptraResult<()> {
pub fn set_block_size(&self, block_size: u32) {
self.with_dma(|dma| dma.block_size().write(|f| f.size(block_size)))
}

pub fn setup_dma_read(&self, read_transaction: DmaReadTransaction) -> CaliptraResult<()> {
pub fn setup_dma_read(&self, read_transaction: DmaReadTransaction) {
self.with_dma(|dma| {
let read_addr = read_transaction.read_addr;
dma.src_addr_l().write(|_| read_addr.lo);
Expand Down Expand Up @@ -188,7 +177,7 @@ impl Dma {
})
}

fn setup_dma_write(&self, write_transaction: DmaWriteTransaction) -> CaliptraResult<()> {
fn setup_dma_write(&self, write_transaction: DmaWriteTransaction) {
self.with_dma(|dma| {
let write_addr = write_transaction.write_addr;
dma.dst_addr_l().write(|_| write_addr.lo);
Expand Down Expand Up @@ -247,7 +236,7 @@ impl Dma {
}
});
Ok(())
})?
})
}

fn dma_write_fifo(&self, write_data: &[u8]) -> CaliptraResult<()> {
Expand All @@ -272,7 +261,7 @@ impl Dma {
}
});
Ok(())
})?
})
}

pub fn do_transaction(&self) -> CaliptraResult<()> {
Expand All @@ -295,7 +284,7 @@ impl Dma {
}

Ok(())
})?
})
}

/// Read a 32-bit word from the specified address
Expand Down Expand Up @@ -324,7 +313,7 @@ impl Dma {
///
/// * CaliptraResult<()> - Success or failure
pub fn read_buffer(&self, read_addr: AxiAddr, buffer: &mut [u8]) -> CaliptraResult<()> {
self.flush()?;
self.flush();

let read_transaction = DmaReadTransaction {
read_addr,
Expand All @@ -333,7 +322,7 @@ impl Dma {
target: DmaReadTarget::AhbFifo,
};

self.setup_dma_read(read_transaction)?;
self.setup_dma_read(read_transaction);
self.do_transaction()?;
self.dma_read_fifo(buffer)?;
Ok(())
Expand All @@ -350,7 +339,7 @@ impl Dma {
///
/// * `CaliptraResult<()>` - Success or error code
pub fn write_dword(&self, write_addr: AxiAddr, write_val: u32) -> CaliptraResult<()> {
self.flush()?;
self.flush();

let write_transaction = DmaWriteTransaction {
write_addr,
Expand All @@ -359,7 +348,7 @@ impl Dma {
origin: DmaWriteOrigin::AhbFifo,
};
self.dma_write_fifo(write_val.as_bytes())?;
self.setup_dma_write(write_transaction)?;
self.setup_dma_write(write_transaction);
self.do_transaction()?;
Ok(())
}
Expand All @@ -385,16 +374,16 @@ impl Dma {
fixed_addr: bool,
block_size: u32,
) -> CaliptraResult<()> {
self.flush()?;
self.flush();

let read_transaction = DmaReadTransaction {
read_addr,
fixed_addr,
length: payload_len_bytes,
target: DmaReadTarget::Mbox,
};
self.setup_dma_read(read_transaction)?;
self.set_block_size(block_size)?;
self.setup_dma_read(read_transaction);
self.set_block_size(block_size);
self.do_transaction()?;
Ok(())
}
Expand All @@ -404,7 +393,7 @@ impl Dma {
/// # Returns
/// true if payload is available, false otherwise
///
pub fn payload_available(&self) -> CaliptraResult<bool> {
pub fn payload_available(&self) -> bool {
self.with_dma(|dma| dma.status0().read().payload_available())
}
}
Expand Down Expand Up @@ -501,10 +490,7 @@ impl<'a> DmaRecovery<'a> {
)
};
let t = f(regs);
match mmio.last_error.take() {
Some(err) => Err(err),
None => Ok(t),
}
mmio.check_error(t)
}

/// Return a register block that can be used to read and
Expand All @@ -525,10 +511,7 @@ impl<'a> DmaRecovery<'a> {
)
};
let t = f(regs);
match mmio.last_error.take() {
Some(err) => Err(err),
None => Ok(t),
}
mmio.check_error(t)
}

fn transfer_payload_to_mbox(
Expand All @@ -538,16 +521,16 @@ impl<'a> DmaRecovery<'a> {
fixed_addr: bool,
block_size: u32,
) -> CaliptraResult<()> {
self.dma.flush()?;
self.dma.flush();

let read_transaction = DmaReadTransaction {
read_addr,
fixed_addr,
length: payload_len_bytes,
target: DmaReadTarget::Mbox,
};
self.dma.setup_dma_read(read_transaction)?;
self.dma.set_block_size(block_size)?;
self.dma.setup_dma_read(read_transaction);
self.dma.set_block_size(block_size);
self.dma.do_transaction()?;
Ok(())
}
Expand All @@ -559,16 +542,16 @@ impl<'a> DmaRecovery<'a> {
write_addr: AxiAddr,
fixed_addr: bool,
) -> CaliptraResult<()> {
self.dma.flush()?;
self.dma.flush();

let write_transaction = DmaWriteTransaction {
write_addr,
fixed_addr,
length: payload_len_bytes,
origin: DmaWriteOrigin::Mbox,
};
self.dma.setup_dma_write(write_transaction)?;
self.dma.set_block_size(block_size)?;
self.dma.setup_dma_write(write_transaction);
self.dma.set_block_size(block_size);
self.dma.do_transaction()?;
Ok(())
}
Expand Down Expand Up @@ -602,7 +585,7 @@ impl<'a> DmaRecovery<'a> {

// Loop on the 'payload_available' signal for the recovery image details to be available.
cprintln!("[fwproc] Waiting for payload available signal...");
while !self.dma.payload_available()? {}
while !self.dma.payload_available() {}
let image_size_bytes = self.with_regs_mut(|regs_mut| {
let recovery = regs_mut.sec_fw_recovery_if();

Expand Down
1 change: 0 additions & 1 deletion error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,6 @@ impl CaliptraError {
pub const DRIVER_DMA_FIFO_UNDERRUN: CaliptraError = CaliptraError::new_const(0x0000f002);
pub const DRIVER_DMA_FIFO_OVERRUN: CaliptraError = CaliptraError::new_const(0x0000f003);
pub const DRIVER_DMA_FIFO_INVALID_SIZE: CaliptraError = CaliptraError::new_const(0x0000f004);
pub const DRIVER_DMA_INTERNAL: CaliptraError = CaliptraError::new_const(0x0000f004);

/// Runtime Errors
pub const RUNTIME_INTERNAL: CaliptraError = CaliptraError::new_const(0x000E0001);
Expand Down
8 changes: 4 additions & 4 deletions rom/dev/src/rom_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use caliptra_drivers::{
};
use caliptra_error::CaliptraResult;
use caliptra_registers::{
axi_dma::AxiDmaReg, csrng::CsrngReg, doe::DoeReg, ecc::EccReg, entropy_src::EntropySrcReg,
hmac::HmacReg, kv::KvReg, mbox::MboxCsr, mldsa::MldsaReg, pv::PvReg, sha256::Sha256Reg,
sha512::Sha512Reg, sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg,
csrng::CsrngReg, doe::DoeReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg,
kv::KvReg, mbox::MboxCsr, mldsa::MldsaReg, pv::PvReg, sha256::Sha256Reg, sha512::Sha512Reg,
sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg,
};

/// Rom Context
Expand Down Expand Up @@ -107,7 +107,7 @@ impl RomEnv {
trng,
persistent_data: PersistentDataAccessor::new(),
mldsa87: Mldsa87::new(MldsaReg::new()),
dma: Dma::new(AxiDmaReg::new()),
dma: Dma::default(),
})
}
}
3 changes: 1 addition & 2 deletions runtime/src/drivers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use caliptra_drivers::{
Sha2_512_384Acc, SocIfc, Trng,
};
use caliptra_image_types::ImageManifest;
use caliptra_registers::axi_dma::AxiDmaReg;
use caliptra_registers::{
csrng::CsrngReg,
dv::DvReg,
Expand Down Expand Up @@ -159,7 +158,7 @@ impl Drivers {
cert_chain: ArrayVec::new(),
is_shutdown: false,
dmtf_device_info: None,
dma: Dma::new(AxiDmaReg::new()),
dma: Dma::default(),
})
}

Expand Down