mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-09-25 14:49:13 +00:00
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
This commit is contained in:
committed by
Sam Leffler
parent
3bda869f20
commit
3185f9f503
@@ -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;
|
||||
|
@@ -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"
|
||||
|
@@ -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(())
|
||||
}
|
@@ -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
|
||||
);
|
||||
}
|
||||
|
@@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "kata-ml-interface"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
@@ -0,0 +1,5 @@
|
||||
#![no_std]
|
||||
|
||||
pub trait MlCoordinatorInterface {
|
||||
fn execute(&mut self);
|
||||
}
|
@@ -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";
|
||||
|
Reference in New Issue
Block a user