diff --git a/apps/system/components/MlCoordinator/MlCoordinator.camkes b/apps/system/components/MlCoordinator/MlCoordinator.camkes index 1d7e5ef..1102b17 100644 --- a/apps/system/components/MlCoordinator/MlCoordinator.camkes +++ b/apps/system/components/MlCoordinator/MlCoordinator.camkes @@ -6,6 +6,10 @@ component MlCoordinator { provides MlCoordinatorInterface mlcoord; provides VectorCoreReturnInterface vctop_return; + dataport Buf(0x300000) elf_file; + dataport Buf(0x40000) itcm; + dataport Buf(0xfff000) dtcm; + uses LoggerInterface logger; uses SecurityCoordinatorInterface security; uses VectorCoreInterface vctop; diff --git a/apps/system/components/MlCoordinator/kata-ml-coordinator/Cargo.toml b/apps/system/components/MlCoordinator/kata-ml-coordinator/Cargo.toml index 1ee8f90..bd4e33e 100644 --- a/apps/system/components/MlCoordinator/kata-ml-coordinator/Cargo.toml +++ b/apps/system/components/MlCoordinator/kata-ml-coordinator/Cargo.toml @@ -7,7 +7,9 @@ edition = "2018" [dependencies] kata-logger = { path = "../../DebugConsole/kata-logger" } kata-panic = { path = "../../DebugConsole/kata-panic" } +kata-ml-interface = { path = "../kata-ml-interface" } log = "0.4" +xmas-elf = "0.8.0" [lib] name = "kata_ml_coordinator" diff --git a/apps/system/components/MlCoordinator/kata-ml-coordinator/src/mlcore.rs b/apps/system/components/MlCoordinator/kata-ml-coordinator/src/mlcore.rs new file mode 100644 index 0000000..c62a3fc --- /dev/null +++ b/apps/system/components/MlCoordinator/kata-ml-coordinator/src/mlcore.rs @@ -0,0 +1,69 @@ +use core::assert; +use core::slice; +use xmas_elf::program::{SegmentData, Type}; +use xmas_elf::ElfFile; + +// TODO(jesionowski): Move these constants to an auto-generated file. +const ELF_SIZE: usize = 0x300000; +const ITCM_SIZE: usize = 0x40000; +const ITCM_PADDR: usize = 0x30000000; +const DTCM_SIZE: usize = 0x1000000; +const DTCM_PADDR: usize = 0x34000000; + +extern "C" { + static elf_file: *const u8; +} +extern "C" { + static itcm: *mut u8; +} +extern "C" { + static dtcm: *mut u8; +} + +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 = ElfFile::new(&elf_slice)?; + + for seg in elf.program_iter() { + if seg.get_type()? == Type::Load { + let fsize = seg.file_size() as usize; + let msize = seg.mem_size() as usize; + + // TODO(jesionowski): I'm assuming that there will be two segments, each beginning at + // the respective PADDRs. Is that assumption safe or does there need to be more + // complex handling? + if seg.virtual_addr() as usize == ITCM_PADDR { + assert!( + fsize <= ITCM_SIZE, + "Elf's ITCM section is larger than than ITCM_SIZE" + ); + + // Due to being Load types we are guarunteed SegmentData::Undefined as the + // data type. + if let SegmentData::Undefined(bytes) = seg.get_data(&elf)? { + 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, + "Elf's DTCM section is larger than than DTCM_SIZE" + ); + + if let SegmentData::Undefined(bytes) = seg.get_data(&elf)? { + dtcm_slice[..fsize].copy_from_slice(&bytes); + } + // Clear NOBITS sections. + dtcm_slice[fsize..msize].fill(0x00); + } else { + assert!(false, "Elf contains LOAD section outside TCM"); + } + } + } + + Ok(()) +} diff --git a/apps/system/components/MlCoordinator/kata-ml-coordinator/src/run.rs b/apps/system/components/MlCoordinator/kata-ml-coordinator/src/run.rs index d675354..1ee026f 100644 --- a/apps/system/components/MlCoordinator/kata-ml-coordinator/src/run.rs +++ b/apps/system/components/MlCoordinator/kata-ml-coordinator/src/run.rs @@ -5,7 +5,41 @@ extern crate kata_panic; use kata_logger::KataLogger; -use log::trace; +use kata_ml_interface::MlCoordinatorInterface; +use log::{error, info, trace}; + +mod mlcore; + +pub struct MLCoordinator { + pub is_loaded: bool, +} + +pub static mut ML_COORD: MLCoordinator = MLCoordinator { is_loaded: false }; + +impl MlCoordinatorInterface for MLCoordinator { + fn execute(&mut self) { + extern "C" { + fn vctop_set_ctrl(ctrl: u32); + } + + if !self.is_loaded { + let res = mlcore::loadelf(); + if let Err(e) = res { + error!("Load error: {:?}", e); + } else { + info!("Load successful."); + self.is_loaded = true; + } + } + + if self.is_loaded { + // Unhalt, start at default PC. + unsafe { + vctop_set_ctrl(vctop_ctrl(0, 0, 0)); + } + } + } +} #[no_mangle] pub extern "C" fn pre_init() { @@ -26,17 +60,10 @@ fn vctop_ctrl(freeze: u32, vc_reset: u32, pc_start: u32) -> u32 { (pc_start << 2) + ((vc_reset & 1) << 1) + (freeze & 1) } +// TODO: Once multiple model support is in start by name. #[no_mangle] pub extern "C" fn mlcoord_execute() { - // TODO: Call into MLCoordinator when available. - // TODO: Once multiple model support is in start by name. - extern "C" { - fn vctop_set_ctrl(ctrl: u32); - } - unsafe { - // Unhalt, start at default PC. - vctop_set_ctrl(vctop_ctrl(0, 0, 0)); - } + unsafe { ML_COORD.execute() }; } #[no_mangle] @@ -46,5 +73,6 @@ pub extern "C" fn vctop_return_update_result(return_code: u32, fault: u32) { trace!( "vctop execution done with code {}, fault pc: {:#010X}", return_code, - fault); + fault + ); } diff --git a/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml b/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml new file mode 100644 index 0000000..745a115 --- /dev/null +++ b/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "kata-ml-interface" +version = "0.1.0" +edition = "2018" diff --git a/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs b/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs new file mode 100644 index 0000000..268dc19 --- /dev/null +++ b/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +pub trait MlCoordinatorInterface { + fn execute(&mut self); +} diff --git a/apps/system/system.camkes b/apps/system/system.camkes index 95979e8..13640e9 100644 --- a/apps/system/system.camkes +++ b/apps/system/system.camkes @@ -36,6 +36,8 @@ component VectorCoreHw { hardware; dataport Buf csr; dataport Buf mem; + dataport Buf(0x40000) itcm; + dataport Buf(0xfff000) dtcm; emits Interrupt host_req; emits Interrupt finish; @@ -43,10 +45,16 @@ component VectorCoreHw { emits Interrupt data_fault; } +component VectorPayload { + hardware; + dataport Buf(0x300000) elf_file; +} + assembly { composition { component VectorCoreHw vctop; component VectorCoreDriver vc_drv; + component VectorPayload vc_payload; component OpenTitanUART uart; component OpenTitanUARTDriver uart_driver; @@ -82,6 +90,13 @@ assembly { to vc_drv.instruction_fault); connection seL4HardwareInterrupt vctop_data_fault(from vctop.data_fault, to vc_drv.data_fault); + connection seL4HardwareMMIO vc_itcm(from ml_coordinator.itcm, + to vctop.itcm); + connection seL4HardwareMMIO vc_dtcm(from ml_coordinator.dtcm, + to vctop.dtcm); + + connection seL4HardwareMMIO vc_elf(from ml_coordinator.elf_file, + to vc_payload.elf_file); // Hookup ProcessManager to DebugConsole for shell commands. connection seL4RPCCall shell_process(from debug_console.proc_ctrl, @@ -133,13 +148,21 @@ 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.host_req_irq_number = 179; vctop.finish_irq_number = 180; vctop.instruction_fault_irq_number = 181; vctop.data_fault_irq_number = 182; + vc_payload.elf_file_paddr = 0x45C00000; + vc_payload.elf_file_size = 0x300000; + random.ID = 1; uart.integrity_label = "opentitan_uart_driver";