Skip to content

Commit

Permalink
Move recovery register interface on the AXI bus
Browse files Browse the repository at this point in the history
This also adds the offset in the soc_ifc registers.

Signed-off-by: Arthur Heymans <arthur.heymans@9elements.com>
  • Loading branch information
ArthurHeymans committed Jan 4, 2025
1 parent 3abbc07 commit 06a2e29
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 74 deletions.
3 changes: 2 additions & 1 deletion hw-model/src/model_emulated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,9 @@ impl HwModel for ModelEmulated {
self.step();
}

// [TODO][CAP2] Should it be statically provisioned?
fn put_firmware_in_rri(&mut self, firmware: &[u8]) -> Result<(), ModelError> {
self.cpu.bus.bus.recovery.cms_data = Some(Rc::new(firmware.to_vec()));
self.cpu.bus.bus.dma.axi.recovery.cms_data = Some(Rc::new(firmware.to_vec()));
Ok(())
}
}
5 changes: 3 additions & 2 deletions sw-emulator/lib/periph/src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ use std::collections::VecDeque;
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use tock_registers::register_bitfields;

mod axi_root_bus;
pub mod axi_root_bus;
use axi_root_bus::AxiRootBus;
mod recovery;

register_bitfields! [
u32,
Expand Down Expand Up @@ -140,7 +141,7 @@ pub struct Dma {
fifo: VecDeque<u8>,

/// Axi Bus
axi: AxiRootBus,
pub axi: AxiRootBus,

/// Mailbox
mailbox: MailboxRam,
Expand Down
20 changes: 18 additions & 2 deletions sw-emulator/lib/periph/src/dma/axi_root_bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,30 @@ Abstract:

use caliptra_emu_derive::AxiBus;

use crate::dma::recovery::RecoveryRegisterInterface;

#[derive(AxiBus)]
pub struct AxiRootBus {
#[register(offset = 0xaa00)]
pub reg: u32,
pub test_reg: u32,

#[peripheral(offset = 0xf_00000000, mask = 0xfff)]
pub recovery: RecoveryRegisterInterface,
}

impl Default for AxiRootBus {
fn default() -> Self {
Self::new()
}
}

impl AxiRootBus {
pub const RECOVERY_REGISTER_INTERFACE_OFFSET: u64 = 0xf_00000000;

pub fn new() -> Self {
Self { reg: 0xaabbccdd }
Self {
test_reg: 0xaabbccdd,
recovery: RecoveryRegisterInterface::new(),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Abstract:
--*/

use caliptra_emu_bus::{BusError, ReadOnlyRegister, ReadWriteRegister};
use caliptra_emu_derive::Bus;
use caliptra_emu_types::{RvData, RvSize};
use caliptra_emu_bus::{AxiBusError, AxiReadOnlyRegister, AxiReadWriteRegister};
use caliptra_emu_derive::AxiBus;
use caliptra_emu_types::{AxiData, AxiSize};
use std::rc::Rc;
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use tock_registers::register_bitfields;
Expand Down Expand Up @@ -197,70 +197,70 @@ register_bitfields! [
];

/// Recovery register interface
#[derive(Bus)]
#[derive(AxiBus)]
pub struct RecoveryRegisterInterface {
// #[register_array(offset = 0x00)]
// prot_cap_magic: [u8; 8],
#[register(offset = 0x08)]
prot_cap_version: ReadWriteRegister<u32, VersionCapabilities::Register>,
prot_cap_version: AxiReadWriteRegister<u32, VersionCapabilities::Register>,

#[register(offset = 0x0c)]
prot_cap_cms_timing: ReadOnlyRegister<u32, CmsTimings::Register>,
prot_cap_cms_timing: AxiReadOnlyRegister<u32, CmsTimings::Register>,

// TODO will this work with 32bit memory access?
// #[register(offset = 0x10)]
// device_id_descriptor_type: ReadOnlyRegister<u8, DidType::Register>,
// device_id_descriptor_type: AxiReadOnlyRegister<u8, DidType::Register>,

// #[register(offset = 0x11)]
// device_id_vendor_id_string_length: ReadOnlyRegister<u8>,
// device_id_vendor_id_string_length: AxiReadOnlyRegister<u8>,

// #[register_array(offset = 0x12)]
// device_id: [u8; 22],
#[register(offset = 0x28)]
device_info: ReadWriteRegister<u32, DeviceInfo::Register>,
device_info: AxiReadWriteRegister<u32, DeviceInfo::Register>,

// #[register(offset = 0x2c)]
// hearthbeat: ReadOnlyRegister<u16>, // TODO do we need hearthbeat?
// hearthbeat: AxiReadOnlyRegister<u16>, // TODO do we need hearthbeat?

// #[register(offset = 0x2e)]
// vendor_status_length: ReadOnlyRegister<u8>, // TODO Not supported?
// vendor_status_length: AxiReadOnlyRegister<u8>, // TODO Not supported?
#[register(offset = 0x30)]
device_reset: ReadWriteRegister<u32, ResetControl::Register>,
device_reset: AxiReadWriteRegister<u32, ResetControl::Register>,

#[register(offset = 0x34)]
recovery_control: ReadWriteRegister<u32, RecoveryControl::Register>,
recovery_control: AxiReadWriteRegister<u32, RecoveryControl::Register>,

#[register(offset = 0x38)]
recovery_status: ReadWriteRegister<u32, RecoveryStatus::Register>,
recovery_status: AxiReadWriteRegister<u32, RecoveryStatus::Register>,

#[register(offset = 0x3c)]
hw_status: ReadOnlyRegister<u32, HwStatus::Register>,
hw_status: AxiReadOnlyRegister<u32, HwStatus::Register>,

#[register(offset = 0x40, write_fn = indirect_fifo_ctrl_write)]
indirect_fifo_ctrl: ReadWriteRegister<u32, IndirectCtrl::Register>,
indirect_fifo_ctrl: AxiReadWriteRegister<u32, IndirectCtrl::Register>,

#[register(offset = 0x44)] // TODO Aligned here but spec says otherwise?
indirect_fifo_image_size: ReadOnlyRegister<u32>,
indirect_fifo_image_size: AxiReadOnlyRegister<u32>,

#[register(offset = 0x48)]
indirect_fifo_status: ReadOnlyRegister<u32, IndirectStatus::Register>,
indirect_fifo_status: AxiReadOnlyRegister<u32, IndirectStatus::Register>,

#[register(offset = 0x4c)]
write_index: ReadOnlyRegister<u32>,
write_index: AxiReadOnlyRegister<u32>,

#[register(offset = 0x50)]
read_index: ReadOnlyRegister<u32>,
read_index: AxiReadOnlyRegister<u32>,

#[register(offset = 0x54)]
indirect_size: ReadOnlyRegister<u32>,
indirect_size: AxiReadOnlyRegister<u32>,

#[register(offset = 0x58)]
max_transfer_window: ReadOnlyRegister<u32>,
max_transfer_window: AxiReadOnlyRegister<u32>,

// TODO email said it's 24 sized
#[register(offset = 0x6c, read_fn = indirect_fifo_data_read)]
indirect_fifo_data: ReadOnlyRegister<u32>,
// indirect_fifo_data: ReadWriteRegisterArray<u32, FIFO_SIZE_DWORD>, // TODO should be larger size but for FW with only read use just one dword
indirect_fifo_data: AxiReadOnlyRegister<u32>,
// indirect_fifo_data: AxiReadWriteRegisterArray<u32, FIFO_SIZE_DWORD>, // TODO should be larger size but for FW with only read use just one dword
pub cms_data: Option<Rc<Vec<u8>>>, // TODO Multiple images?
}

Expand All @@ -272,44 +272,44 @@ impl RecoveryRegisterInterface {
pub fn new() -> Self {
Self {
// prot_cap_magic: Self::MAGIC,
prot_cap_version: ReadWriteRegister::new(
prot_cap_version: AxiReadWriteRegister::new(
VersionCapabilities::MAJOR.val(Self::MAJOR_VERSION).value
| VersionCapabilities::MINOR.val(Self::MINOR_VERSION).value,
),
prot_cap_cms_timing: ReadOnlyRegister::new(
prot_cap_cms_timing: AxiReadOnlyRegister::new(
CmsTimings::CMS.val(1).value // TODO
| CmsTimings::MAX_RESPONSE_TIME.val(0xff).value // TODO
| CmsTimings::HEARTBEAT_PERIOD.val(0).value, // TODO 0 means unsupported
),
// device_id_descriptor_type: ReadOnlyRegister::new(DidType::TYPE::UUID.value), // TODO
// device_id_vendor_id_string_length: ReadOnlyRegister::new(0), // not supported
// device_id_descriptor_type: AxiReadOnlyRegister::new(DidType::TYPE::UUID.value), // TODO
// device_id_vendor_id_string_length: AxiReadOnlyRegister::new(0), // not supported
// device_id: [0; 22],
device_info: ReadWriteRegister::new(
device_info: AxiReadWriteRegister::new(
DeviceInfo::STATUS::DeviceHealthy.value
| DeviceInfo::ERROR::NoProtocolError.value
| DeviceInfo::RECOVERY_REASON::NoBootFailureDetected.value,
),
// hearthbeat: ReadOnlyRegister::new(0),
// vendor_status_length: ReadOnlyRegister::new(0),
device_reset: ReadWriteRegister::new(0),
recovery_control: ReadWriteRegister::new(0),
recovery_status: ReadWriteRegister::new(0),
hw_status: ReadOnlyRegister::new(0), // TODO
indirect_fifo_ctrl: ReadWriteRegister::new(0),
indirect_fifo_image_size: ReadOnlyRegister::new(0),
indirect_fifo_status: ReadOnlyRegister::new(0),
write_index: ReadOnlyRegister::new(0),
read_index: ReadOnlyRegister::new(0),
indirect_size: ReadOnlyRegister::new(FIFO_SIZE_DWORD.try_into().unwrap()),
max_transfer_window: ReadOnlyRegister::new(0),
indirect_fifo_data: ReadOnlyRegister::new(0),
// hearthbeat: AxiReadOnlyRegister::new(0),
// vendor_status_length: AxiReadOnlyRegister::new(0),
device_reset: AxiReadWriteRegister::new(0),
recovery_control: AxiReadWriteRegister::new(0),
recovery_status: AxiReadWriteRegister::new(0),
hw_status: AxiReadOnlyRegister::new(0), // TODO
indirect_fifo_ctrl: AxiReadWriteRegister::new(0),
indirect_fifo_image_size: AxiReadOnlyRegister::new(0),
indirect_fifo_status: AxiReadOnlyRegister::new(0),
write_index: AxiReadOnlyRegister::new(0),
read_index: AxiReadOnlyRegister::new(0),
indirect_size: AxiReadOnlyRegister::new(FIFO_SIZE_DWORD.try_into().unwrap()),
max_transfer_window: AxiReadOnlyRegister::new(0),
indirect_fifo_data: AxiReadOnlyRegister::new(0),
cms_data: None,
}
}

pub fn indirect_fifo_data_read(&mut self, size: RvSize) -> Result<RvData, BusError> {
if size != RvSize::Word {
return Err(BusError::LoadAccessFault);
pub fn indirect_fifo_data_read(&mut self, size: AxiSize) -> Result<AxiData, AxiBusError> {
if size != AxiSize::Word {
return Err(AxiBusError::LoadAccessFault);
}
let image = match &self.cms_data {
None => {
Expand Down Expand Up @@ -341,15 +341,20 @@ impl RecoveryRegisterInterface {
let range = address..(address + 4);
let data = &image[range];
self.read_index.reg.set(read_index + 1);
Ok(u32::from_le_bytes(data.try_into().unwrap()))
Ok(u32::from_le_bytes(data.try_into().unwrap()) as u64)
}

pub fn indirect_fifo_ctrl_write(&mut self, size: RvSize, val: RvData) -> Result<(), BusError> {
pub fn indirect_fifo_ctrl_write(
&mut self,
size: AxiSize,
val: AxiData,
) -> Result<(), AxiBusError> {
// Writes have to be Word aligned
if size != RvSize::Word {
Err(BusError::StoreAccessFault)?
if size != AxiSize::Word {
Err(AxiBusError::StoreAccessFault)?
}
let load: ReadWriteRegister<u32, IndirectCtrl::Register> = ReadWriteRegister::new(val);
let load: AxiReadWriteRegister<u32, IndirectCtrl::Register> =
AxiReadWriteRegister::new(val as u32);
if load.reg.is_set(IndirectCtrl::RESET) {
if let Some(image) = &self.cms_data {
let cms = load.reg.read(IndirectCtrl::CMS);
Expand Down Expand Up @@ -389,16 +394,16 @@ impl Default for RecoveryRegisterInterface {

#[cfg(test)]
mod tests {
use caliptra_emu_bus::Bus;
use caliptra_emu_types::RvAddr;
use caliptra_emu_bus::AxiBus;
use caliptra_emu_types::AxiAddr;

use super::*;

const INDIRECT_FIFO_CTRL: RvAddr = 0x40;
const INDIRECT_FIFO_RESET: RvData = 0x100;
const INDIRECT_FIFO_IMAGE_SIZE: RvAddr = 0x44;
const INDIRECT_FIFO_STATUS: RvAddr = 0x48;
const INDIRECT_FIFO_DATA: RvAddr = 0x6c;
const INDIRECT_FIFO_CTRL: AxiAddr = 0x40;
const INDIRECT_FIFO_RESET: AxiData = 0x100;
const INDIRECT_FIFO_IMAGE_SIZE: AxiAddr = 0x44;
const INDIRECT_FIFO_STATUS: AxiAddr = 0x48;
const INDIRECT_FIFO_DATA: AxiAddr = 0x6c;

#[test]
fn test_get_image() {
Expand All @@ -408,15 +413,15 @@ mod tests {
rri.cms_data = Some(image.clone());

// Reset
rri.write(RvSize::Word, INDIRECT_FIFO_CTRL, INDIRECT_FIFO_RESET)
rri.write(AxiSize::Word, INDIRECT_FIFO_CTRL, INDIRECT_FIFO_RESET)
.unwrap();

let image_size = rri.read(RvSize::Word, INDIRECT_FIFO_IMAGE_SIZE).unwrap();
let image_size = rri.read(AxiSize::Word, INDIRECT_FIFO_IMAGE_SIZE).unwrap();
assert_eq!(image_len, image_size as usize * 4);

let mut read_image = Vec::new();
while rri.read(RvSize::Word, INDIRECT_FIFO_STATUS).unwrap() & 1 == 0 {
let dword_read = rri.read(RvSize::Word, INDIRECT_FIFO_DATA).unwrap();
while rri.read(AxiSize::Word, INDIRECT_FIFO_STATUS).unwrap() & 1 == 0 {
let dword_read = rri.read(AxiSize::Word, INDIRECT_FIFO_DATA).unwrap() as u32;
let bytes = dword_read.to_le_bytes();
read_image.extend_from_slice(&bytes);
}
Expand Down
1 change: 0 additions & 1 deletion sw-emulator/lib/periph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ mod iccm;
mod key_vault;
mod mailbox;
mod ml_dsa87;
mod recovery;
mod root_bus;
mod sha512_acc;
pub mod soc_reg;
Expand Down
6 changes: 0 additions & 6 deletions sw-emulator/lib/periph/src/root_bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::{
helpers::words_from_bytes_be,
iccm::Iccm,
ml_dsa87::Mldsa87,
recovery::RecoveryRegisterInterface,
soc_reg::{DebugManufService, SocRegistersExternal},
AsymEcc384, Csrng, Doe, EmuCtrl, HashSha256, HashSha512, HmacSha, KeyVault, MailboxExternal,
MailboxInternal, MailboxRam, Sha512Accelerator, SocRegistersInternal, Uart,
Expand Down Expand Up @@ -272,10 +271,6 @@ pub struct CaliptraRootBus {
#[peripheral(offset = 0x1003_0000, mask = 0x0000_ffff)]
pub ml_dsa87: Mldsa87,

// We set I3C at 0x1004_0000 and EC is at 0x100 offset
#[peripheral(offset = 0x1004_0100, mask = 0x0000_7fff)] // TODO
pub recovery: RecoveryRegisterInterface,

#[peripheral(offset = 0x4000_0000, mask = 0x0fff_ffff)]
pub iccm: Iccm,

Expand Down Expand Up @@ -342,7 +337,6 @@ impl CaliptraRootBus {
sha512,
sha256: HashSha256::new(clock),
ml_dsa87: Mldsa87::new(clock, key_vault.clone()),
recovery: RecoveryRegisterInterface::new(),
iccm,
dccm: Ram::new(vec![0; Self::DCCM_SIZE]),
uart: Uart::new(),
Expand Down
10 changes: 10 additions & 0 deletions sw-emulator/lib/periph/src/soc_reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,12 @@ struct SocRegistersImpl {
#[register_array(offset = 0x34c)]
fuse_manuf_dbg_unlock_token: [u32; FUSE_MANUF_DBG_UNLOCK_TOKEN_SIZE / 4],

#[register(offset = 0x510)]
ss_recovery_ifc_base_addr_l: ReadOnlyRegister<u32>,

#[register(offset = 0x514)]
ss_recovery_ifc_base_addr_h: ReadOnlyRegister<u32>,

#[register(offset = 0x520)]
ss_uds_seed_base_addr_l: ReadOnlyRegister<u32>,

Expand Down Expand Up @@ -846,6 +852,8 @@ impl SocRegistersImpl {
let flow_status = InMemoryRegister::<u32, FlowStatus::Register>::new(0);
flow_status.write(FlowStatus::READY_FOR_FUSES.val(1));

let rri_offset = crate::dma::axi_root_bus::AxiRootBus::RECOVERY_REGISTER_INTERFACE_OFFSET;

let regs = Self {
cptra_hw_error_fatal: ReadWriteRegister::new(0),
cptra_hw_error_non_fatal: ReadWriteRegister::new(0),
Expand Down Expand Up @@ -906,6 +914,8 @@ impl SocRegistersImpl {
fuse_mldsa_revocation: Default::default(),
fuse_soc_stepping_id: ReadWriteRegister::new(0),
fuse_manuf_dbg_unlock_token: [0; 4],
ss_recovery_ifc_base_addr_l: ReadOnlyRegister::new(rri_offset as u32),
ss_recovery_ifc_base_addr_h: ReadOnlyRegister::new((rri_offset >> 32) as u32),
internal_obf_key: args.cptra_obf_key,
internal_iccm_lock: ReadWriteRegister::new(0),
internal_fw_update_reset: ReadWriteRegister::new(0),
Expand Down

0 comments on commit 06a2e29

Please sign in to comment.