Unify DTCM and mem sections.

Move getting the return code and fault registers into Rust and out from
the C driver. This means extending the DTCM to cover memory previously
covered by `mem`.

Change-Id: I9d1ad8e9823445ad7dd476ef05f128a29567999b
GitOrigin-RevId: 21bc1ee544d39d6b4a2ff963aaae7c145fdd7fa9
This commit is contained in:
Adam Jesionowski 2021-11-08 12:38:22 -08:00 committed by Sam Leffler
parent 3185f9f503
commit 39f9eac9c3
7 changed files with 50 additions and 39 deletions

View File

@ -8,7 +8,7 @@ component MlCoordinator {
dataport Buf(0x300000) elf_file;
dataport Buf(0x40000) itcm;
dataport Buf(0xfff000) dtcm;
dataport Buf(0x1000000) dtcm;
uses LoggerInterface logger;
uses SecurityCoordinatorInterface security;

View File

@ -11,19 +11,19 @@ const DTCM_SIZE: usize = 0x1000000;
const DTCM_PADDR: usize = 0x34000000;
extern "C" {
static elf_file: *const u8;
static elf_file: *const u32;
}
extern "C" {
static itcm: *mut u8;
static itcm: *mut u32;
}
extern "C" {
static dtcm: *mut u8;
static dtcm: *mut u32;
}
pub fn loadelf() -> Result<(), &'static str> {
let elf_slice = unsafe { slice::from_raw_parts(elf_file, ELF_SIZE) };
let itcm_slice = unsafe { slice::from_raw_parts_mut(itcm, ITCM_SIZE) };
let dtcm_slice = unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE) };
let elf_slice = unsafe { slice::from_raw_parts(elf_file as *const u8, ELF_SIZE) };
let itcm_slice = unsafe { slice::from_raw_parts_mut(itcm as *mut u8, ITCM_SIZE) };
let dtcm_slice = unsafe { slice::from_raw_parts_mut(dtcm as *mut u8, DTCM_SIZE) };
let elf = ElfFile::new(&elf_slice)?;
@ -47,10 +47,8 @@ pub fn loadelf() -> Result<(), &'static str> {
itcm_slice[..fsize].copy_from_slice(&bytes);
}
} else if seg.virtual_addr() as usize == DTCM_PADDR {
// TODO(jesionowski): Change to msize. Will currently fail as a portion
// of the memory is mapped to the vctop driver for getting return information.
assert!(
fsize <= DTCM_SIZE,
msize <= DTCM_SIZE,
"Elf's DTCM section is larger than than DTCM_SIZE"
);
@ -67,3 +65,18 @@ pub fn loadelf() -> Result<(), &'static str> {
Ok(())
}
fn get_dtcm_slice() -> &'static mut [u32] {
unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / 4) }
}
// TODO(jesionowski): Read these from CSRs when available.
pub fn get_return_code() -> u32 {
const RC_OFFSET: usize = 0x3FFFEE;
get_dtcm_slice()[RC_OFFSET]
}
pub fn get_fault_register() -> u32 {
const FAULT_OFFSET: usize = 0x3FFFEF;
get_dtcm_slice()[FAULT_OFFSET]
}

View File

@ -16,6 +16,22 @@ pub struct MLCoordinator {
pub static mut ML_COORD: MLCoordinator = MLCoordinator { is_loaded: false };
impl MLCoordinator {
fn handle_return_interrupt(&self) {
// TODO(hcindyl): check the return code and fault registers, move the result
// from TCM to SRAM, update the input/model, and call mlcoord_execute again.
let return_code = mlcore::get_return_code();
let fault = mlcore::get_fault_register();
if return_code != 0 {
error!(
"vctop execution failed with code {}, fault pc: {:#010X}",
return_code, fault
);
}
}
}
impl MlCoordinatorInterface for MLCoordinator {
fn execute(&mut self) {
extern "C" {
@ -63,16 +79,14 @@ fn vctop_ctrl(freeze: u32, vc_reset: u32, pc_start: u32) -> u32 {
// TODO: Once multiple model support is in start by name.
#[no_mangle]
pub extern "C" fn mlcoord_execute() {
unsafe { ML_COORD.execute() };
unsafe {
ML_COORD.execute();
}
}
#[no_mangle]
pub extern "C" fn vctop_return_update_result(return_code: u32, fault: u32) {
// TODO(hcindyl): check the return code and fault registers, move the result
// from TCM to SRAM, update the input/model, and call mlcoord_execute again.
trace!(
"vctop execution done with code {}, fault pc: {:#010X}",
return_code,
fault
);
pub extern "C" fn vctop_return_update_result() {
unsafe {
ML_COORD.handle_return_interrupt();
}
}

View File

@ -1,6 +1,5 @@
component VectorCoreDriver {
dataport Buf csr;
dataport Buf mem;
consumes Interrupt host_req;
consumes Interrupt finish;
consumes Interrupt instruction_fault;

View File

@ -8,16 +8,6 @@
#define VCTOP_REG(name) \
*((volatile uint32_t *)(CSR_OFFSET + VC_TOP_##name##_REG_OFFSET))
static inline uint32_t get_return_code() {
const uint32_t kReturnCodeOffset = 0xfb8;
return *((volatile uint32_t *)((void *)mem + kReturnCodeOffset));
}
static inline uint32_t get_fault_register() {
const uint32_t kFaultRegOffset = 0xfbc;
return *((volatile uint32_t *)((void *)mem + kFaultRegOffset));
}
// CAmkES initialization hook.
//
// Enables Interrupts.
@ -42,7 +32,7 @@ void host_req_handle(void) {
void finish_handle(void) {
// Read main() return code and machine exception PC.
vctop_return_update_result(get_return_code(), get_fault_register());
vctop_return_update_result();
// Also need to clear the INTR_STATE (write-1-to-clear).
VCTOP_REG(INTR_STATE) = BIT(VC_TOP_INTR_STATE_FINISH_BIT);
seL4_Assert(finish_acknowledge() == 0);

View File

@ -1,3 +1,3 @@
procedure VectorCoreReturnInterface {
void update_result(in uint32_t return_code, in uint32_t fault);
void update_result();
};

View File

@ -35,9 +35,8 @@ component OpenTitanUART {
component VectorCoreHw {
hardware;
dataport Buf csr;
dataport Buf mem;
dataport Buf(0x40000) itcm;
dataport Buf(0xfff000) dtcm;
dataport Buf(0x1000000) dtcm;
emits Interrupt host_req;
emits Interrupt finish;
@ -77,7 +76,6 @@ assembly {
// VectorCoreDriver
connection seL4HardwareMMIO vc_csr(from vc_drv.csr, to vctop.csr);
connection seL4HardwareMMIO vc_mem(from vc_drv.mem, to vctop.mem);
connection seL4RPCCall ml_coord_to_driver(from ml_coordinator.vctop,
to vc_drv.vctop);
connection seL4RPCCall vc_driver_to_ml_coord(from vc_drv.vctop_return,
@ -148,13 +146,10 @@ assembly {
vctop.csr_paddr = 0x48000000;
vctop.csr_size = 0x1000;
// TODO(jesionowski): Merge mem and dtcm
vctop.mem_paddr = 0x34fff000;
vctop.mem_size = 0x1000;
vctop.itcm_paddr = 0x30000000;
vctop.itcm_size = 0x40000;
vctop.dtcm_paddr = 0x34000000;
vctop.dtcm_size = 0xfff000;
vctop.dtcm_size = 0x1000000;
vctop.host_req_irq_number = 179;
vctop.finish_irq_number = 180;
vctop.instruction_fault_irq_number = 181;