Skip to content

Commit

Permalink
Add Axi bus behind the DMA engine (#1878)
Browse files Browse the repository at this point in the history
This change moves the dma widget to work with a separate axi_root_bus bus.
ArthurHeymans authored Jan 23, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 27849e1 commit 051960e
Showing 32 changed files with 856 additions and 830 deletions.
6 changes: 0 additions & 6 deletions builder/src/firmware.rs
Original file line number Diff line number Diff line change
@@ -159,11 +159,6 @@ pub mod driver_tests {
features: &["emu"],
};

pub const DMA: FwId = FwId {
bin_name: "axi_dma_tests",
..BASE_FWID
};

pub const DOE: FwId = FwId {
bin_name: "doe",
..BASE_FWID
@@ -414,7 +409,6 @@ pub const REGISTERED_FW: &[&FwId] = &[
&hw_model_tests::TEST_DCCM_DOUBLE_BIT_ECC,
&hw_model_tests::TEST_UNITIALIZED_READ,
&hw_model_tests::TEST_PCR_EXTEND,
&driver_tests::DMA,
&driver_tests::DOE,
&driver_tests::ECC384,
&driver_tests::ECC384_SIGN_VALIDATION_FAILURE,
77 changes: 58 additions & 19 deletions drivers/src/dma.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ use caliptra_registers::axi_dma::{
enums::{RdRouteE, WrRouteE},
AxiDmaReg,
};
use core::{ops::Add, ptr::read_volatile};
use zerocopy::AsBytes;

pub enum DmaReadTarget {
@@ -39,6 +40,22 @@ impl From<u64> for AxiAddr {
}
}
}
impl From<AxiAddr> for u64 {
fn from(addr: AxiAddr) -> Self {
(addr.hi as u64) << 32 | (addr.lo as u64)
}
}

impl Add for AxiAddr {
type Output = Self;

fn add(self, rhs: Self) -> Self {
let self_u64: u64 = self.into();
let rhs_u64: u64 = rhs.into();
let sum = self_u64 + rhs_u64;
sum.into()
}
}

pub struct DmaReadTransaction {
pub read_addr: AxiAddr,
@@ -161,16 +178,21 @@ impl Dma {
let status = dma.status0().read();

if read_data.len() > status.fifo_depth() as usize {
return Err(CaliptraError::DRIVER_DMA_FIFO_UNDERRUN);
Err(CaliptraError::DRIVER_DMA_FIFO_UNDERRUN)?;
}

read_data.chunks_mut(4).for_each(|word| {
let ptr = dma.read_data().ptr as *mut u8;
// Reg only exports u32 writes but we need finer grained access
unsafe {
ptr.copy_to_nonoverlapping(word.as_mut_ptr(), word.len());
}
});
// Only multiple of 4 bytes are allowed
if read_data.len() % core::mem::size_of::<u32>() != 0 {
Err(CaliptraError::DRIVER_DMA_FIFO_INVALID_SIZE)?;
}

let read_data_ptr = dma.read_data().ptr as *const u8;

// Process all 4-byte chunks
for chunk in read_data.chunks_exact_mut(4) {
let value = unsafe { read_volatile(read_data_ptr as *const u32) };
chunk.copy_from_slice(&value.to_le_bytes());
}

Ok(())
}
@@ -182,16 +204,19 @@ impl Dma {
let current_fifo_depth = dma.status0().read().fifo_depth();

if write_data.len() as u32 > max_fifo_depth - current_fifo_depth {
return Err(CaliptraError::DRIVER_DMA_FIFO_OVERRUN);
Err(CaliptraError::DRIVER_DMA_FIFO_OVERRUN)?;
}

write_data.chunks(4).for_each(|word| {
let ptr = dma.write_data().ptr as *mut u8;
// Reg only exports u32 writes but we need finer grained access
unsafe {
ptr.copy_from_nonoverlapping(word.as_ptr(), word.len());
}
});
// Only multiple of 4 bytes are allowed
if write_data.len() % core::mem::size_of::<u32>() != 0 {
Err(CaliptraError::DRIVER_DMA_FIFO_INVALID_SIZE)?;
}

// Process all 4-byte chunks
for chunk in write_data.chunks(4) {
let value = u32::from_le_bytes(chunk.try_into().unwrap());
unsafe { (dma.write_data().ptr as *mut u32).write_volatile(value) };
}

Ok(())
}
@@ -230,20 +255,34 @@ impl Dma {
/// * `CaliptraResult<u32>` - Read value or error code
pub fn read_dword(&mut self, read_addr: AxiAddr) -> CaliptraResult<u32> {
let mut read_val: u32 = 0;
self.read_buffer(read_addr, read_val.as_bytes_mut())?;
Ok(read_val)
}

/// Read an arbitrary length buffer to fifo and read back the fifo into the provided buffer
///
/// # Arguments
///
/// * `read_addr` - Address to read from
/// * `buffer` - Target location to read to
///
/// # Returns
///
/// * CaliptraResult<()> - Success or failure
pub fn read_buffer(&mut self, read_addr: AxiAddr, buffer: &mut [u8]) -> CaliptraResult<()> {
self.flush();

let read_transaction = DmaReadTransaction {
read_addr,
fixed_addr: false,
length: core::mem::size_of::<u32>() as u32,
length: buffer.len() as u32,
target: DmaReadTarget::AhbFifo,
};

self.setup_dma_read(read_transaction);
self.do_transaction()?;
self.dma_read_fifo(read_val.as_bytes_mut())?;
Ok(read_val)
self.dma_read_fifo(buffer)?;
Ok(())
}

/// Write a 32-bit word to the specified address
5 changes: 0 additions & 5 deletions drivers/test-fw/Cargo.toml
Original file line number Diff line number Diff line change
@@ -174,11 +174,6 @@ name = "trng_driver_responder"
path = "src/bin/trng_driver_responder.rs"
required-features = ["riscv"]

[[bin]]
name = "axi_dma_tests"
path = "src/bin/dma_tests.rs"
required-features = ["riscv"]

[[bin]]
name = "ml_dsa87"
path = "src/bin/mldsa87_tests.rs"
83 changes: 0 additions & 83 deletions drivers/test-fw/src/bin/dma_tests.rs

This file was deleted.

20 changes: 0 additions & 20 deletions drivers/tests/drivers_integration_tests/main.rs
Original file line number Diff line number Diff line change
@@ -1132,23 +1132,3 @@ fn test_uart() {
fn test_mailbox_txn_drop() {
run_driver_test(&firmware::driver_tests::MBOX_SEND_TXN_DROP);
}

#[test]
fn test_dma() {
let rom = caliptra_builder::build_firmware_rom(&firmware::driver_tests::DMA).unwrap();
let recovery_image = &[0xab; 512];

let init_params = InitParams {
rom: &rom,
..default_init_params()
};

let boot_params = BootParams {
..Default::default()
};

let mut model = caliptra_hw_model::new_unbooted(init_params).unwrap();
model.put_firmware_in_rri(recovery_image).unwrap();
model.boot(boot_params).unwrap();
model.step_until_exit_success().unwrap();
}
1 change: 1 addition & 0 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
@@ -376,6 +376,7 @@ impl CaliptraError {
pub const DRIVER_DMA_TRANSACTION_ERROR: CaliptraError = CaliptraError::new_const(0x0000f001);
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);

/// Runtime Errors
pub const RUNTIME_INTERNAL: CaliptraError = CaliptraError::new_const(0x000E0001);
4 changes: 2 additions & 2 deletions hw-model/c-binding/examples/api/caliptra_api.c
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ int caliptra_init_fuses(struct caliptra_model *model, struct caliptra_fuses *fus
caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_IDEVID_MANUF_HSM_ID_0, fuses->idevid_manuf_hsm_id, CALIPTRA_ARRAY_SIZE(fuses->idevid_manuf_hsm_id));

// Write to Caliptra Fuse Done
caliptra_model_axi_write_u32(model, EXTERNAL_PERIPH_BASE + CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_FUSE_WR_DONE, 1);
caliptra_model_apb_write_u32(model, EXTERNAL_PERIPH_BASE + CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_FUSE_WR_DONE, 1);

// It shouldn`t be longer ready for fuses
if (caliptra_model_ready_for_fuses(model))
@@ -48,7 +48,7 @@ int caliptra_bootfsm_go(struct caliptra_model *model)
}

// Write BOOTFSM_GO Register
caliptra_model_axi_write_u32(model, EXTERNAL_PERIPH_BASE + CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_BOOTFSM_GO, 1);
caliptra_model_apb_write_u32(model, EXTERNAL_PERIPH_BASE + CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_BOOTFSM_GO, 1);

return 0;
}
2 changes: 1 addition & 1 deletion hw-model/c-binding/examples/api/caliptra_fuses.h
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ extern "C" {

static inline void caliptra_fuse_write(caliptra_model *model, uint32_t offset, uint32_t data)
{
caliptra_model_axi_write_u32(model, EXTERNAL_PERIPH_BASE + (offset + CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_BASE_ADDR), data);
caliptra_model_apb_write_u32(model, EXTERNAL_PERIPH_BASE + (offset + CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_BASE_ADDR), data);
}

static inline void caliptra_fuse_array_write(caliptra_model *model, uint32_t offset, uint32_t *data, size_t size)
4 changes: 2 additions & 2 deletions hw-model/c-binding/examples/api/caliptra_mbox.h
Original file line number Diff line number Diff line change
@@ -13,13 +13,13 @@ extern "C" {

static inline void caliptra_mbox_write(caliptra_model *model, uint32_t offset, uint32_t data)
{
caliptra_model_axi_write_u32(model, EXTERNAL_PERIPH_BASE + (offset + CALIPTRA_TOP_REG_MBOX_CSR_BASE_ADDR), data);
caliptra_model_apb_write_u32(model, EXTERNAL_PERIPH_BASE + (offset + CALIPTRA_TOP_REG_MBOX_CSR_BASE_ADDR), data);
}

static inline uint32_t caliptra_mbox_read(caliptra_model *model, uint32_t offset)
{
uint32_t data;
caliptra_model_axi_read_u32(model, EXTERNAL_PERIPH_BASE + (offset + CALIPTRA_TOP_REG_MBOX_CSR_BASE_ADDR), &data);
caliptra_model_apb_read_u32(model, EXTERNAL_PERIPH_BASE + (offset + CALIPTRA_TOP_REG_MBOX_CSR_BASE_ADDR), &data);
return data;
}

8 changes: 4 additions & 4 deletions hw-model/c-binding/src/caliptra_model.rs
Original file line number Diff line number Diff line change
@@ -72,15 +72,15 @@ pub unsafe extern "C" fn caliptra_model_destroy(model: *mut caliptra_model) {

/// # Safety
#[no_mangle]
pub unsafe extern "C" fn caliptra_model_axi_read_u32(
pub unsafe extern "C" fn caliptra_model_apb_read_u32(
model: *mut caliptra_model,
addr: c_uint,
data: *mut c_uint,
) -> c_int {
// Parameter check
assert!(!model.is_null() || !data.is_null());
*data = (*{ model as *mut DefaultHwModel })
.axi_bus()
.apb_bus()
.read(RvSize::Word, addr)
.unwrap();

@@ -89,15 +89,15 @@ pub unsafe extern "C" fn caliptra_model_axi_read_u32(

/// # Safety
#[no_mangle]
pub unsafe extern "C" fn caliptra_model_axi_write_u32(
pub unsafe extern "C" fn caliptra_model_apb_write_u32(
model: *mut caliptra_model,
addr: c_uint,
data: c_uint,
) -> c_int {
// Parameter check
assert!(!model.is_null());
(*{ model as *mut DefaultHwModel })
.axi_bus()
.apb_bus()
.write(RvSize::Word, addr, data)
.unwrap();

3 changes: 0 additions & 3 deletions hw-model/src/bus_logger.rs
Original file line number Diff line number Diff line change
@@ -130,7 +130,4 @@ impl<TBus: Bus> Bus for BusLogger<TBus> {
fn update_reset(&mut self) {
self.bus.update_reset();
}
fn handle_dma(&mut self) {
self.bus.handle_dma();
}
}
Loading

0 comments on commit 051960e

Please sign in to comment.