From 8800dc4a960efe5a8328a34ac4f8ced55d4f5350 Mon Sep 17 00:00:00 2001 From: Adam Jesionowski Date: Tue, 14 Jun 2022 18:53:27 +0000 Subject: [PATCH] Merge "Refactor kata-vec-core and add fake-vec-core" GitOrigin-RevId: 96f07ab9323932ee3b06da58367a5b95a4d7718b --- .../components/MlCoordinator/Cargo.toml | 1 + .../MlCoordinator/fake-vec-core/Cargo.toml | 11 + .../MlCoordinator/fake-vec-core/src/lib.rs | 38 +++ .../kata-ml-coordinator/src/lib.rs | 13 +- .../kata-ml-interface/Cargo.toml | 1 - .../kata-ml-interface/src/lib.rs | 15 - .../MlCoordinator/kata-vec-core/src/lib.rs | 259 +++++++++--------- .../MlCoordinator/kata-vec-core/src/vc_top.rs | 13 +- 8 files changed, 190 insertions(+), 161 deletions(-) create mode 100644 apps/system/components/MlCoordinator/fake-vec-core/Cargo.toml create mode 100644 apps/system/components/MlCoordinator/fake-vec-core/src/lib.rs diff --git a/apps/system/components/MlCoordinator/Cargo.toml b/apps/system/components/MlCoordinator/Cargo.toml index d150bfe..96258e3 100644 --- a/apps/system/components/MlCoordinator/Cargo.toml +++ b/apps/system/components/MlCoordinator/Cargo.toml @@ -3,6 +3,7 @@ cargo-features = ["edition2021"] [workspace] members = [ + "fake-vec-core", "kata-ml-component", "kata-ml-coordinator", "kata-ml-interface", diff --git a/apps/system/components/MlCoordinator/fake-vec-core/Cargo.toml b/apps/system/components/MlCoordinator/fake-vec-core/Cargo.toml new file mode 100644 index 0000000..036dbae --- /dev/null +++ b/apps/system/components/MlCoordinator/fake-vec-core/Cargo.toml @@ -0,0 +1,11 @@ +cargo-features = ["edition2021"] + +[package] +name = "fake-vec-core" +version = "0.1.0" +edition = "2021" + +[dependencies] +kata-memory-interface = { path = "../../MemoryManager/kata-memory-interface" } +kata-ml-interface = { path = "../kata-ml-interface" } + diff --git a/apps/system/components/MlCoordinator/fake-vec-core/src/lib.rs b/apps/system/components/MlCoordinator/fake-vec-core/src/lib.rs new file mode 100644 index 0000000..200812e --- /dev/null +++ b/apps/system/components/MlCoordinator/fake-vec-core/src/lib.rs @@ -0,0 +1,38 @@ +#![no_std] + +// fake-vec-core is a stubbed out version of kata-vec-core. + +use kata_memory_interface::ObjDescBundle; +use kata_ml_interface::{ModelSections, Window}; + +pub fn enable_interrupts(_enable: bool) {} + +pub fn set_wmmu(_sections: &ModelSections) {} + +// NB: this function will be moved out of *-vec-core shortly. +pub fn load_image(_frames: &ObjDescBundle) -> Result { + Ok(ModelSections { + instructions: Window { addr: 0, size: 0 }, + data: Window { addr: 0, size: 0 }, + }) +} + +pub fn run() {} + +pub fn clear_host_req() {} + +pub fn clear_finish() {} + +pub fn clear_instruction_fault() {} + +pub fn clear_data_fault() {} + +pub fn clear_tcm() {} + +pub fn get_return_code() -> u32 { + 0 +} + +pub fn get_fault_register() -> u32 { + 0 +} diff --git a/apps/system/components/MlCoordinator/kata-ml-coordinator/src/lib.rs b/apps/system/components/MlCoordinator/kata-ml-coordinator/src/lib.rs index 084caa2..e106d63 100644 --- a/apps/system/components/MlCoordinator/kata-ml-coordinator/src/lib.rs +++ b/apps/system/components/MlCoordinator/kata-ml-coordinator/src/lib.rs @@ -7,11 +7,10 @@ extern crate alloc; use alloc::string::String; use alloc::vec::Vec; use kata_ml_interface::MlCoordError; -use kata_ml_interface::MlCoreInterface; use kata_os_common::cspace_slot::CSpaceSlot; use kata_security_interface::*; use kata_timer_interface::*; -use kata_vec_core::MlCore; +use kata_vec_core as MlCore; use log::{error, info, trace, warn}; /// The maximum number of models that the MLCoordinator can handle, bounded by @@ -46,7 +45,6 @@ pub struct MLCoordinator { /// core, once the currently running model has finished. execution_queue: Vec, statistics: Statistics, - ml_core: MlCore, } // The index of a model in MLCoordinator.models @@ -63,13 +61,12 @@ impl MLCoordinator { models: [INIT_NONE; MAX_MODELS], execution_queue: Vec::new(), statistics: Statistics{load_failures: 0, already_queued: 0}, - ml_core: MlCore {}, } } /// Initialize the vector core. pub fn init(&mut self) { - self.ml_core.enable_interrupts(true); + MlCore::enable_interrupts(true); self.execution_queue.reserve(MAX_MODELS); } @@ -95,7 +92,7 @@ impl MLCoordinator { let container_slot = CSpaceSlot::new(); match kata_security_load_model(&model.bundle_id, &model.model_id, &container_slot) { Ok(model_frames) => { - match self.ml_core.load_image(&model_frames) { + match MlCore::load_image(&model_frames) { Err(e) => { error!( "Load of {}:{} failed: {:?}", @@ -108,7 +105,7 @@ impl MLCoordinator { } Ok(sections) => { info!("Load successful."); - self.ml_core.set_wmmu(§ions); + MlCore::set_wmmu(§ions); self.loaded_model = Some(model_idx); Ok(()) } @@ -134,7 +131,7 @@ impl MLCoordinator { // It's very unlikely for load errors to be transient, it should // only happen in the case of a mal-formed model. self.load_model(next_idx)?; - self.ml_core.run(); // Unhalt, start at default PC. + MlCore::run(); // Unhalt, start at default PC. self.running_model = Some(next_idx); } diff --git a/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml b/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml index 4fff725..011aaf4 100644 --- a/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml +++ b/apps/system/components/MlCoordinator/kata-ml-interface/Cargo.toml @@ -7,4 +7,3 @@ edition = "2021" [dependencies] cstr_core = { version = "0.2.3", default-features = false } -kata-memory-interface = { path = "../../MemoryManager/kata-memory-interface" } diff --git a/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs b/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs index 3910cdb..2eea527 100644 --- a/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs +++ b/apps/system/components/MlCoordinator/kata-ml-interface/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![allow(dead_code)] use cstr_core::CString; -use kata_memory_interface::ObjDescBundle; /// The Vector Core uses a Windowed MMU (go/sparrow-wmmu) in order to prevent /// models from interferring with each other. Before executing a model, @@ -41,20 +40,6 @@ impl From for Result<(), MlCoordError> { } } -/// Abstraction layer over the hardware vector core. -pub trait MlCoreInterface { - fn set_wmmu(&mut self, sections: &ModelSections); - fn enable_interrupts(&mut self, enabled: bool); - fn run(&mut self); - fn load_image(&mut self, frames: &ObjDescBundle) -> Result; - fn get_return_code() -> u32; - fn get_fault_register() -> u32; - fn clear_host_req(); - fn clear_finish(); - fn clear_instruction_fault(); - fn clear_data_fault(); -} - #[inline] pub fn kata_mlcoord_oneshot(bundle_id: &str, model_id: &str) -> Result<(), MlCoordError> { extern "C" { diff --git a/apps/system/components/MlCoordinator/kata-vec-core/src/lib.rs b/apps/system/components/MlCoordinator/kata-vec-core/src/lib.rs index 128c657..97afdda 100644 --- a/apps/system/components/MlCoordinator/kata-vec-core/src/lib.rs +++ b/apps/system/components/MlCoordinator/kata-vec-core/src/lib.rs @@ -8,7 +8,7 @@ mod vc_top; use core::mem::size_of; use core::slice; use kata_memory_interface::ObjDescBundle; -use kata_ml_interface::{MlCoreInterface, ModelSections, Window}; +use kata_ml_interface::{ModelSections, Window}; use kata_proc_interface::BundleImage; use io::Read; @@ -24,7 +24,6 @@ const ITCM_PADDR: usize = 0x32000000; const DTCM_SIZE: usize = 0x1000000; const DTCM_PADDR: usize = 0x34000000; -// TODO(jesionowski): ITCM / DTCM will eventually be merged into a single memory. extern "C" { static itcm: *mut u32; static dtcm: *mut u32; @@ -38,11 +37,119 @@ fn round_up(a: usize, b: usize) -> usize { } } -fn get_dtcm_slice() -> &'static mut [u32] { - unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / size_of::()) } +pub fn enable_interrupts(enable: bool) { + let intr_enable = vc_top::IntrEnable::new() + .with_host_req(enable) + .with_finish(enable) + .with_instruction_fault(enable) + .with_data_fault(enable); + vc_top::set_intr_enable(intr_enable); } -pub struct MlCore {} +pub fn set_wmmu(sections: &ModelSections) { + // The length of the window is not the size of the window, but rather + // the last address of the window. This saves us a bit in hardware: + // 0x400000 is 23 bits vs. 0x3FFFFF 22 bits. + vc_top::set_immu_window_offset(0, sections.instructions.addr); + vc_top::set_immu_window_length(0, sections.instructions.size - 1); + vc_top::set_immu_window_permission(0, vc_top::Permission::Read); + + vc_top::set_dmmu_window_offset(0, sections.data.addr); + vc_top::set_dmmu_window_length(0, sections.data.size - 1); + vc_top::set_dmmu_window_permission(0, vc_top::Permission::ReadAndWrite); +} + +pub fn run() { + let ctrl = vc_top::Ctrl::new() + .with_freeze(false) + .with_vc_reset(false) + .with_pc_start(0); + vc_top::set_ctrl(ctrl); +} + +// Loads the model into the TCM. +pub fn load_image(frames: &ObjDescBundle) -> Result { + let mut image = BundleImage::new(frames); + let mut itcm_found = false; + let mut dtcm_found = false; + // Size of windows is filled in below. + let mut iwindow = Window { + addr: ITCM_PADDR, + size: 0, + }; + let mut dwindow = Window { + addr: DTCM_PADDR, + size: 0, + }; + + clear_tcm(); + // NB: we require both ITCM & DTCM sections and that only one + // instance of each is present + while let Some(section) = image.next_section() { + let slice = if section.vaddr == ITCM_PADDR { + if itcm_found { + return Err("dup ITCM"); + } + itcm_found = true; + + if section.fsize > ITCM_SIZE { + return Err("ITCM too big"); + } + iwindow.size = round_up(section.msize, WMMU_PAGE_SIZE); + unsafe { slice::from_raw_parts_mut(itcm as *mut u8, ITCM_SIZE) } + } else if section.vaddr == DTCM_PADDR { + if dtcm_found { + return Err("dup DTCM"); + } + dtcm_found = true; + + if section.fsize > DTCM_SIZE { + return Err("DTCM section too big"); + } + dwindow.size = round_up(section.msize, WMMU_PAGE_SIZE); + unsafe { slice::from_raw_parts_mut(dtcm as *mut u8, DTCM_SIZE) } + } else { + return Err("Unexpected section"); + }; + image + .read_exact(&mut slice[section.data_range()]) + .map_err(|_| "section read error")?; + // TODO(jesionowski): Remove when clear_tcm is fully implemented. + slice[section.zero_range()].fill(0x00); + } + if !itcm_found || !dtcm_found { + return Err("Incomplete"); + } + Ok(ModelSections { + instructions: iwindow, + data: dwindow, + }) +} + +// Interrupts are write 1 to clear. +pub fn clear_host_req() { + let mut intr_state = vc_top::get_intr_state(); + intr_state.set_host_req(true); + vc_top::set_intr_state(intr_state); +} + +pub fn clear_finish() { + let mut intr_state = vc_top::get_intr_state(); + intr_state.set_finish(true); + vc_top::set_intr_state(intr_state); +} + +pub fn clear_instruction_fault() { + let mut intr_state = vc_top::get_intr_state(); + intr_state.set_instruction_fault(true); + vc_top::set_intr_state(intr_state); +} + +pub fn clear_data_fault() { + let mut intr_state = vc_top::get_intr_state(); + intr_state.set_data_fault(true); + vc_top::set_intr_state(intr_state); +} fn clear_section(start: u32, end: u32, is_itcm: bool) { let init_start = vc_top::InitStart::new() @@ -56,135 +163,25 @@ fn clear_section(start: u32, end: u32, is_itcm: bool) { while !vc_top::get_init_status().init_done() {} } -fn clear_tcm() { +pub fn clear_tcm() { clear_section(0, ITCM_SIZE as u32, true); // TODO(jesionowski): Enable when DTCM_SIZE fits into INIT_END. // clear_section(0, DTCM_SIZE as u32, false); } -impl MlCoreInterface for MlCore { - fn set_wmmu(&mut self, sections: &ModelSections) { - // The length of the window is not the size of the window, but rather - // the last address of the window. This saves us a bit in hardware: - // 0x400000 is 23 bits vs. 0x3FFFFF 22 bits. - vc_top::set_immu_window_offset(0, sections.instructions.addr); - vc_top::set_immu_window_length(0, sections.instructions.size - 1); - vc_top::set_immu_window_permission(0, vc_top::Permission::Read); - - vc_top::set_dmmu_window_offset(0, sections.data.addr); - vc_top::set_dmmu_window_length(0, sections.data.size - 1); - vc_top::set_dmmu_window_permission(0, vc_top::Permission::ReadAndWrite); - } - - fn enable_interrupts(&mut self, enable: bool) { - let intr_enable = vc_top::IntrEnable::new() - .with_host_req(enable) - .with_finish(enable) - .with_instruction_fault(enable) - .with_data_fault(enable); - vc_top::set_intr_enable(intr_enable); - } - - fn run(&mut self) { - let ctrl = vc_top::Ctrl::new() - .with_freeze(false) - .with_vc_reset(false) - .with_pc_start(0); - vc_top::set_ctrl(ctrl); - } - - // Loads the model into the TCM. - fn load_image(&mut self, frames: &ObjDescBundle) -> Result { - let mut image = BundleImage::new(frames); - let mut itcm_found = false; - let mut dtcm_found = false; - // Size of windows is filled in below. - let mut iwindow = Window { - addr: ITCM_PADDR, - size: 0, - }; - let mut dwindow = Window { - addr: DTCM_PADDR, - size: 0, - }; - - clear_tcm(); - // NB: we require both ITCM & DTCM sections and that only one - // instance of each is present - while let Some(section) = image.next_section() { - let slice = if section.vaddr == ITCM_PADDR { - if itcm_found { - return Err("dup ITCM"); - } - itcm_found = true; - - if section.fsize > ITCM_SIZE { - return Err("ITCM too big"); - } - iwindow.size = round_up(section.msize, WMMU_PAGE_SIZE); - unsafe { slice::from_raw_parts_mut(itcm as *mut u8, ITCM_SIZE) } - } else if section.vaddr == DTCM_PADDR { - if dtcm_found { - return Err("dup DTCM"); - } - dtcm_found = true; - - if section.fsize > DTCM_SIZE { - return Err("DTCM section too big"); - } - dwindow.size = round_up(section.msize, WMMU_PAGE_SIZE); - unsafe { slice::from_raw_parts_mut(dtcm as *mut u8, DTCM_SIZE) } - } else { - return Err("Unexpected section"); - }; - image - .read_exact(&mut slice[section.data_range()]) - .map_err(|_| "section read error")?; - // TODO(jesionowski): Remove when clear_tcm is fully implemented. - slice[section.zero_range()].fill(0x00); - } - if !itcm_found || !dtcm_found { - return Err("Incomplete"); - } - Ok(ModelSections { - instructions: iwindow, - data: dwindow, - }) - } - - // TODO(jesionowski): Read these from CSRs when available. - fn get_return_code() -> u32 { - const RC_OFFSET: usize = 0x3FFFEE; - get_dtcm_slice()[RC_OFFSET] - } - - fn get_fault_register() -> u32 { - const FAULT_OFFSET: usize = 0x3FFFEF; - get_dtcm_slice()[FAULT_OFFSET] - } - - // Interrupts are write 1 to clear. - fn clear_host_req() { - let mut intr_state = vc_top::get_intr_state(); - intr_state.set_host_req(true); - vc_top::set_intr_state(intr_state); - } - - fn clear_finish() { - let mut intr_state = vc_top::get_intr_state(); - intr_state.set_finish(true); - vc_top::set_intr_state(intr_state); - } - - fn clear_instruction_fault() { - let mut intr_state = vc_top::get_intr_state(); - intr_state.set_instruction_fault(true); - vc_top::set_intr_state(intr_state); - } - - fn clear_data_fault() { - let mut intr_state = vc_top::get_intr_state(); - intr_state.set_data_fault(true); - vc_top::set_intr_state(intr_state); - } +// TODO(jesionowski): Remove these when error handling is refactored. +// The status will be faulty iff the interrupt line is raised, and +// we won't have the fault registers on Springbok. +fn get_dtcm_slice() -> &'static mut [u32] { + unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / size_of::()) } +} + +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] } diff --git a/apps/system/components/MlCoordinator/kata-vec-core/src/vc_top.rs b/apps/system/components/MlCoordinator/kata-vec-core/src/vc_top.rs index 83ed618..a00cf8a 100644 --- a/apps/system/components/MlCoordinator/kata-vec-core/src/vc_top.rs +++ b/apps/system/components/MlCoordinator/kata-vec-core/src/vc_top.rs @@ -1,9 +1,14 @@ -// Auto-generated hardware structs from vc_top.hjson - #![allow(unused)] + +// Setters and getters for the Vector Core CSRs. + use core::ptr; use modular_bitfield::prelude::*; +extern "C" { + static csr: *mut [u32; 9]; +} + #[bitfield] pub struct IntrState { pub host_req: bool, @@ -85,10 +90,6 @@ pub struct InitStatus { pub _unused0: B30, } -extern "C" { - static csr: *mut [u32; 9]; -} - pub fn get_intr_state() -> IntrState { unsafe { IntrState::from_bytes(ptr::read_volatile(csr)[0].to_ne_bytes()) } }