From 3185f9f5031175b3040e584b8cabc389757de873 Mon Sep 17 00:00:00 2001 From: Adam Jesionowski Date: Mon, 8 Nov 2021 09:13:07 -0800 Subject: [PATCH] Load ELF in MLCoordinator. Rather than using the Renode ELF loader, this CL moves that capability into the ML Coordinator. The ELF is memory mapped in eflash instead. We create MMIO buffers for the MLCoordinator to access. The ELF information is gathered from the header. The ITCM and DTCM data is copied over to the vector core. Next steps are to integrate the load with the execute and to re-map the return codes and fault registers into Rust code. Change-Id: I3fc266feb262966318bb451888df146703a03579 GitOrigin-RevId: 8db55b58f86918b8c37d436f1d9f359afdd2a3ea --- .../MlCoordinator/MlCoordinator.camkes | 4 ++ .../kata-ml-coordinator/Cargo.toml | 2 + .../kata-ml-coordinator/src/mlcore.rs | 69 +++++++++++++++++++ .../kata-ml-coordinator/src/run.rs | 50 +++++++++++--- .../kata-ml-interface/Cargo.toml | 4 ++ .../kata-ml-interface/src/lib.rs | 5 ++ apps/system/system.camkes | 23 +++++++ 7 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 apps/system/components/MlCoordinator/kata-ml-coordinator/src/mlcore.rs create mode 100644 apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml create mode 100644 apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs 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";