diff --git a/apps/system/CMakeLists.txt b/apps/system/CMakeLists.txt index ed5d107..21d241b 100644 --- a/apps/system/CMakeLists.txt +++ b/apps/system/CMakeLists.txt @@ -96,6 +96,17 @@ DeclareCAmkESComponent(TimerService INCLUDES interfaces ) +RustAddLibrary( + mailbox_driver + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/components/MailboxDriver + LIB_FILENAME libmailbox_driver.a +) + +DeclareCAmkESComponent(MailboxDriver + LIBS mailbox_driver + INCLUDES interfaces +) + DeclareCAmkESComponent(LogFibonacci SOURCES components/LogFibonacci/src/main.c diff --git a/apps/system/components/DebugConsole/kata-shell/Cargo.toml b/apps/system/components/DebugConsole/kata-shell/Cargo.toml index 2fb5995..b92de6b 100644 --- a/apps/system/components/DebugConsole/kata-shell/Cargo.toml +++ b/apps/system/components/DebugConsole/kata-shell/Cargo.toml @@ -13,6 +13,7 @@ sel4-config = { path = "../../kata-os-common/src/sel4-config" } [features] default = [ "TEST_GLOBAL_ALLOCATOR", + "TEST_MAILBOX", "TEST_MEMORY_MANAGER", "TEST_ML_COORDINATOR", "TEST_PANIC", @@ -25,6 +26,7 @@ CONFIG_KERNEL_MCS = [] FRINGE_CMDS = [] # Runtime tests for various services (please keep sorted) TEST_GLOBAL_ALLOCATOR = [] +TEST_MAILBOX = [] TEST_MEMORY_MANAGER = [] TEST_ML_COORDINATOR = [] TEST_PANIC = [] diff --git a/apps/system/components/DebugConsole/kata-shell/src/test_security_coordinator.rs b/apps/system/components/DebugConsole/kata-shell/src/test_security_coordinator.rs index 60ed115..5a8122f 100644 --- a/apps/system/components/DebugConsole/kata-shell/src/test_security_coordinator.rs +++ b/apps/system/components/DebugConsole/kata-shell/src/test_security_coordinator.rs @@ -22,6 +22,7 @@ pub fn add_cmds(cmds: &mut HashMap::<&str, CmdFn>) { ("delete_key", delete_key_command as CmdFn), ("read_key", read_key_command as CmdFn), ("write_key", write_key_command as CmdFn), + ("test_mailbox", test_mailbox_command as CmdFn), ]); } @@ -157,3 +158,20 @@ fn write_key_command( } Ok(()) } + +fn test_mailbox_command( + _args: &mut dyn Iterator, + _input: &mut dyn io::BufRead, + output: &mut dyn io::Write, + _builtin_cpio: &[u8], +) -> Result<(), CommandError> { + match kata_security_test_mailbox() { + Ok(_) => { + writeln!(output, "Test mailbox OK.")?; + } + Err(_status) => { + writeln!(output, "Test mailbox failed.")?; + } + } + Ok(()) +} diff --git a/apps/system/components/MailboxDriver/Cargo.toml b/apps/system/components/MailboxDriver/Cargo.toml new file mode 100644 index 0000000..4d93535 --- /dev/null +++ b/apps/system/components/MailboxDriver/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["edition2021"] + +[workspace] + +members = [ + "mailbox-driver", +] +resolver = "2" diff --git a/apps/system/components/MailboxDriver/MailboxDriver.camkes b/apps/system/components/MailboxDriver/MailboxDriver.camkes new file mode 100644 index 0000000..71e4d64 --- /dev/null +++ b/apps/system/components/MailboxDriver/MailboxDriver.camkes @@ -0,0 +1,33 @@ +/* + * CAmkES component for accessing Sparrow's SMC -> SEC mailbox. + * + * Copyright 2021, Google LLC + * Apache License 2.0 + */ + +import ; +import ; +import ; + +component MailboxDriver { + provides MailboxAPI api; + + // Mailbox registers + dataport Buf mailbox_mmio; + + // Global mailbox lock + has mutex api_mutex; + + // Mailbox arrival semaphore + has semaphore rx_semaphore; + + // Mailbox interrupts + consumes Interrupt wtirq; + consumes Interrupt rtirq; + consumes Interrupt eirq; + + // Enable KataOS CAmkES support. + attribute int kataos = true; + + uses LoggerInterface logger; +} diff --git a/apps/system/components/MailboxDriver/mailbox-driver/Cargo.toml b/apps/system/components/MailboxDriver/mailbox-driver/Cargo.toml new file mode 100644 index 0000000..81bd63e --- /dev/null +++ b/apps/system/components/MailboxDriver/mailbox-driver/Cargo.toml @@ -0,0 +1,20 @@ +cargo-features = ["edition2021"] + +[package] +name = "mailbox-driver" +version = "0.1.0" +edition = "2018" + +[features] +default = [] + +[dependencies] +kata-os-common = { path = "../../kata-os-common" } +log = "0.4" +cty = "0.2.1" +kata-memory-interface = { path = "../../MemoryManager/kata-memory-interface" } + +[lib] +name = "mailbox_driver" +path = "src/lib.rs" +crate-type = ["staticlib"] diff --git a/apps/system/components/MailboxDriver/mailbox-driver/src/lib.rs b/apps/system/components/MailboxDriver/mailbox-driver/src/lib.rs new file mode 100644 index 0000000..34ae261 --- /dev/null +++ b/apps/system/components/MailboxDriver/mailbox-driver/src/lib.rs @@ -0,0 +1,262 @@ +#![no_std] +// We want to keep all mailbox constants here even if they're currently unused. +#![allow(dead_code)] +#![allow(non_snake_case)] + +use kata_os_common::logger::KataLogger; +use kata_os_common::sel4_sys::seL4_CPtr; +use log::{error, trace}; + +//------------------------------------------------------------------------------ +// TODO(aappleby): Can we replace this with the register_struct! thing? + +const REG_INTR_STATE: u32 = 0x000; // R/W1C +const REG_INTR_ENABLE: u32 = 0x004; // R/W +const REG_INTR_TEST: u32 = 0x008; // R/W +const REG_MBOXW: u32 = 0x00C; // W +const REG_MBOXR: u32 = 0x010; // R +const REG_STATUS: u32 = 0x014; // R +const REG_ERROR: u32 = 0x018; // R +const REG_WIRQT: u32 = 0x01C; // R/W +const REG_RIRQT: u32 = 0x020; // R/W +const REG_CTRL: u32 = 0x024; // R/W + +const INTR_STATE_BIT_WTIRQ: u32 = 0b001; +const INTR_STATE_BIT_RTIRQ: u32 = 0b010; +const INTR_STATE_BIT_EIRQ: u32 = 0b100; +const INTR_STATE_MASK: u32 = 0b111; + +const INTR_ENABLE_BIT_WTIRQ: u32 = 0b001; +const INTR_ENABLE_BIT_RTIRQ: u32 = 0b010; +const INTR_ENABLE_BIT_EIRQ: u32 = 0b100; +const INTR_ENABLE_MASK: u32 = 0b111; + +const INTR_TEST_BIT_WTIRQ: u32 = 0b001; +const INTR_TEST_BIT_RTIRQ: u32 = 0b010; +const INTR_TEST_BIT_EIRQ: u32 = 0b100; +const INTR_TEST_MASK: u32 = 0b111; + +const STATUS_BIT_EMPTY: u32 = 0b0001; +const STATUS_BIT_FULL: u32 = 0b0010; +const STATUS_BIT_WFIFOL: u32 = 0b0100; +const STATUS_BIT_RFIFOL: u32 = 0b1000; +const STATUS_MASK: u32 = 0b1111; + +const ERROR_BIT_READ: u32 = 0b01; +const ERROR_BIT_WRITE: u32 = 0b10; +const ERROR_MASK: u32 = 0b11; + +const FIFO_SIZE: u32 = 8; +const FIFO_MASK: u32 = FIFO_SIZE - 1; +const WIRQT_MASK: u32 = FIFO_MASK; +const RIRQT_MASK: u32 = FIFO_MASK; + +const CTRL_BIT_FLUSH_WFIFO: u32 = 0b01; +const CTRL_BIT_FLUSH_RFIFO: u32 = 0b10; +const CTRL_MASK: u32 = 0b11; + +// The high bit of the message header is used to distinguish between "inline" +// messages that fit in the mailbox and "long" messages that contain the +// physical address of a memory page containing the message. +const HEADER_FLAG_LONG_MESSAGE: u32 = 0x80000000; + +//------------------------------------------------------------------------------ + +extern "C" { + // Mailbox registers + static mailbox_mmio: *mut u32; + + // Global mailbox lock + fn api_mutex_lock() -> u32; + fn api_mutex_unlock() -> u32; + + // Mailbox arrival semaphore + fn rx_semaphore_wait() -> u32; + fn rx_semaphore_post() -> u32; + + // Mailbox interrupts + fn wtirq_acknowledge() -> u32; + fn rtirq_acknowledge() -> u32; + fn eirq_acknowledge() -> u32; + + // Enable KataOS CAmkES support. + static SELF_CNODE: seL4_CPtr; + static SELF_VSPACE_ROOT: seL4_CPtr; +} + +//------------------------------------------------------------------------------ +// Directly manipulate the mailbox registers. + +unsafe fn get_intr_state() -> u32 { + mailbox_mmio.offset(0).read_volatile() +} +unsafe fn get_INTR_ENABLE() -> u32 { + mailbox_mmio.offset(1).read_volatile() +} +unsafe fn get_INTR_TEST() -> u32 { + mailbox_mmio.offset(2).read_volatile() +} +unsafe fn get_MBOXW() -> u32 { + mailbox_mmio.offset(3).read_volatile() +} +unsafe fn get_MBOXR() -> u32 { + mailbox_mmio.offset(4).read_volatile() +} +unsafe fn get_STATUS() -> u32 { + mailbox_mmio.offset(5).read_volatile() +} +unsafe fn get_ERROR() -> u32 { + mailbox_mmio.offset(6).read_volatile() +} +unsafe fn get_WIRQT() -> u32 { + mailbox_mmio.offset(7).read_volatile() +} +unsafe fn get_RIRQT() -> u32 { + mailbox_mmio.offset(8).read_volatile() +} +unsafe fn get_CTRL() -> u32 { + mailbox_mmio.offset(9).read_volatile() +} + +unsafe fn set_INTR_STATE(x: u32) { + mailbox_mmio.offset(0).write_volatile(x); +} +unsafe fn set_INTR_ENABLE(x: u32) { + mailbox_mmio.offset(1).write_volatile(x); +} +unsafe fn set_INTR_TEST(x: u32) { + mailbox_mmio.offset(2).write_volatile(x); +} +unsafe fn set_MBOXW(x: u32) { + mailbox_mmio.offset(3).write_volatile(x); +} +unsafe fn set_MBOXR(x: u32) { + mailbox_mmio.offset(4).write_volatile(x); +} +unsafe fn set_STATUS(x: u32) { + mailbox_mmio.offset(5).write_volatile(x); +} +unsafe fn set_ERROR(x: u32) { + mailbox_mmio.offset(6).write_volatile(x); +} +unsafe fn set_WIRQT(x: u32) { + mailbox_mmio.offset(7).write_volatile(x); +} +unsafe fn set_RIRQT(x: u32) { + mailbox_mmio.offset(8).write_volatile(x); +} +unsafe fn set_CTRL(x: u32) { + mailbox_mmio.offset(9).write_volatile(x); +} + +//------------------------------------------------------------------------------ +// Directly manipulate the hardware FIFOs. Synchronous and busy-waits. Not +// thread-safe, should only be used while holding the api_mutex lock. + +fn enqueue_u32(x: u32) { + unsafe { + while (get_STATUS() & STATUS_BIT_FULL) == STATUS_BIT_FULL {} + set_MBOXW(x); + } +} + +fn dequeue_u32() -> u32 { + unsafe { + while (get_STATUS() & STATUS_BIT_EMPTY) == STATUS_BIT_EMPTY {} + return get_MBOXR(); + } +} + +fn drain_read_fifo() { + unsafe { + while (get_STATUS() & STATUS_BIT_EMPTY) == 0 { + let _ = get_MBOXR(); + } + } +} + +//------------------------------------------------------------------------------ + +#[no_mangle] +pub unsafe extern "C" fn pre_init() { + static KATA_LOGGER: KataLogger = KataLogger; + log::set_logger(&KATA_LOGGER).unwrap(); + log::set_max_level(log::LevelFilter::Trace); + + // We always want our receive interrupt to fire as soon as anything appears + // in the mailbox, so set the threshold to 0. + set_RIRQT(0); + set_INTR_STATE(INTR_STATE_BIT_RTIRQ); + set_INTR_ENABLE(INTR_ENABLE_BIT_RTIRQ); +} + +//------------------------------------------------------------------------------ + +// When outbox.count > write_threshold, this interrupt fires. +#[no_mangle] +pub unsafe extern "C" fn wtirq_handle() { + trace!("wtirq_handle()"); + + // We don't have anything to do here yet, so just clear the interrupt. + set_INTR_STATE(INTR_STATE_BIT_WTIRQ); + wtirq_acknowledge(); +} + +// When inbox.count > read_threshold, this interrupt fires. +#[no_mangle] +pub unsafe extern "C" fn rtirq_handle() { + trace!("rtirq_handle()"); + + // Unblock anyone waiting for a message. api_receive() below will clear + // the interrupt once the message has been deliverd to the client. + rx_semaphore_post(); +} + +// When an error occurs, this interrupt fires. We don't handle errors yet. +#[no_mangle] +pub unsafe extern "C" fn eirq_handle() { + error!("eirq_handle() - error flag is 0x{:X}", get_ERROR()); + + // We don't have anything to do here yet, so just clear the interrupt. + set_INTR_STATE(INTR_STATE_BIT_EIRQ); + eirq_acknowledge(); +} + +//------------------------------------------------------------------------------ + +// Send a message to the security core. The message must be at a _physical_ +// address, as the security core knows nothing about seL4's virtual memory. +#[no_mangle] +pub unsafe extern "C" fn api_send(request_paddr: u32, request_size: u32) { + api_mutex_lock(); + + let request_header = request_size | HEADER_FLAG_LONG_MESSAGE; + enqueue_u32(request_header); + enqueue_u32(request_paddr); + + api_mutex_unlock(); +} + +// Receive a message from the security core. Blocks the calling thread until a +// message arrives. +#[no_mangle] +pub unsafe extern "C" fn api_receive(response_paddr: *mut u32, response_size: *mut u32) { + api_mutex_lock(); + + // When a message arrives, the interrupt handler will raise the semaphore. + rx_semaphore_wait(); + + // Message arrived, dequeue it. + let message_header = dequeue_u32(); + let message_paddr = dequeue_u32(); + response_paddr.write(message_paddr); + response_size.write(message_header & !HEADER_FLAG_LONG_MESSAGE); + + // The interrupt that raised the semaphore has been handled, clear it. + set_INTR_STATE(INTR_STATE_BIT_RTIRQ); + rtirq_acknowledge(); + + api_mutex_unlock(); +} + +//------------------------------------------------------------------------------ diff --git a/apps/system/components/SecurityCoordinator/SecurityCoordinator.camkes b/apps/system/components/SecurityCoordinator/SecurityCoordinator.camkes index ecb0bd3..0df2672 100644 --- a/apps/system/components/SecurityCoordinator/SecurityCoordinator.camkes +++ b/apps/system/components/SecurityCoordinator/SecurityCoordinator.camkes @@ -3,16 +3,21 @@ import ; import ; import ; +import ; component SecurityCoordinator { provides SecurityCoordinatorInterface security; uses LoggerInterface logger; uses MemoryInterface memory; + uses MailboxAPI mailbox_api; // Enable KataOS CAmkES support. attribute int kataos = true; // Add free slots for processing requests. attribute int cnode_headroom = 32; + + // For mailbox use. What should we call this? + has copyregion COPYREGION; } diff --git a/apps/system/components/SecurityCoordinator/kata-security-component/src/run.rs b/apps/system/components/SecurityCoordinator/kata-security-component/src/run.rs index 5597de8..40d9f8f 100644 --- a/apps/system/components/SecurityCoordinator/kata-security-component/src/run.rs +++ b/apps/system/components/SecurityCoordinator/kata-security-component/src/run.rs @@ -232,6 +232,12 @@ fn delete_key_request( unsafe { KATA_SECURITY.delete_key(request.bundle_id, request.key) } } +fn test_mailbox_request( +) -> Result<(), SecurityRequestError> { + trace!("TEST MAILBOX"); + unsafe { KATA_SECURITY.test_mailbox() } +} + #[no_mangle] pub unsafe extern "C" fn security_request( c_request: SecurityRequest, @@ -263,5 +269,7 @@ pub unsafe extern "C" fn security_request( write_key_request(request_buffer, reply_buffer), SecurityRequest::SrDeleteKey => delete_key_request(request_buffer, reply_buffer), + SecurityRequest::SrTestMailbox => + test_mailbox_request(), }.map_or_else(|e| e, |_v| SecurityRequestError::SreSuccess) } diff --git a/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/fakeimpl/mod.rs b/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/fakeimpl/mod.rs index 699e6f2..17510b8 100644 --- a/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/fakeimpl/mod.rs +++ b/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/fakeimpl/mod.rs @@ -3,11 +3,13 @@ extern crate alloc; use alloc::fmt; use alloc::string::{String, ToString}; +use core::mem::size_of; use hashbrown::HashMap; -use kata_memory_interface::ObjDescBundle; -use kata_memory_interface::kata_object_free_in_cnode; +use kata_memory_interface::*; +use kata_os_common::sel4_sys::*; use kata_security_interface::*; use kata_storage_interface::KeyValueData; +use log::trace; struct BundleData { pkg_contents: ObjDescBundle, @@ -21,7 +23,8 @@ impl BundleData { BundleData { pkg_contents: pkg_contents.clone(), pkg_size: size_bytes, - manifest: String::from(r##" + manifest: String::from( + r##" # Comments like this [Manifest] BundleId=com.google.cerebra.hw.HelloWorld @@ -32,7 +35,8 @@ Model=NeuralNetworkName [Storage] Required=1 -"##,), +"##, + ), keys: HashMap::with_capacity(2), } } @@ -84,7 +88,10 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinator { if self.bundles.contains_key(&bundle_id) { return Err(SecurityRequestError::SreDeleteFirst); } - assert!(self.bundles.insert(bundle_id.clone(), BundleData::new(pkg_contents)).is_none()); + assert!(self + .bundles + .insert(bundle_id.clone(), BundleData::new(pkg_contents)) + .is_none()); Ok(bundle_id) } fn uninstall(&mut self, bundle_id: &str) -> Result<(), SecurityRequestError> { @@ -104,7 +111,11 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinator { // XXX just return the package for now Ok(bundle_data.pkg_contents.clone()) } - fn load_model(&self, bundle_id: &str, _model_id: &str) -> Result { + fn load_model( + &self, + bundle_id: &str, + _model_id: &str, + ) -> Result { let bundle_data = self.get_bundle(bundle_id)?; // TODO(sleffler): check model id // XXX just return the package for now @@ -112,9 +123,17 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinator { } fn read_key(&self, bundle_id: &str, key: &str) -> Result<&KeyValueData, SecurityRequestError> { let bundle = self.get_bundle(bundle_id)?; - bundle.keys.get(key).ok_or(SecurityRequestError::SreKeyNotFound) + bundle + .keys + .get(key) + .ok_or(SecurityRequestError::SreKeyNotFound) } - fn write_key(&mut self, bundle_id: &str, key: &str, value: &KeyValueData) -> Result<(), SecurityRequestError> { + fn write_key( + &mut self, + bundle_id: &str, + key: &str, + value: &KeyValueData, + ) -> Result<(), SecurityRequestError> { let bundle = self.get_bundle_mut(bundle_id)?; let _ = bundle.keys.insert(key.to_string(), *value); Ok(()) @@ -125,4 +144,98 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinator { let _ = bundle.keys.remove(key); Ok(()) } + + fn test_mailbox(&mut self) -> Result<(), SecurityRequestError> { + trace!("test_mailbox_command()"); + + const PAGE_SIZE: usize = 1 << seL4_PageBits; + const MESSAGE_SIZE_DWORDS: usize = 17; // Just a random message size for testing. + + extern "C" { + fn mailbox_api_send(paddr: u32, size: u32); + fn mailbox_api_receive(paddr: *mut u32, size: *mut u32); + static SELF_VSPACE_ROOT: seL4_CPtr; + + // This is not actually a block of memory, it's a reserved range in + // the virtual address space that we can map physical memory into. + static mut COPYREGION: [u32; 1024]; + } + + // Allocate a 4k page to serve as our message buffer. + let frame_bundle = + kata_frame_alloc(PAGE_SIZE).map_err(|_| SecurityRequestError::SreTestFailed)?; + trace!("test_mailbox: Frame {:?}", frame_bundle); + + unsafe { + // Map the message buffer into our copyregion so we can access it. + // FIXME(aappleby): We need a drop() impl here somewhere so this + // doesn't leak if something fails. + let message_ptr = core::ptr::addr_of_mut!(COPYREGION[0]); + seL4_Page_Map( + /*sel4_page=*/ frame_bundle.objs[0].cptr, + /*seL4_pd=*/ SELF_VSPACE_ROOT, + /*vaddr=*/ message_ptr as usize, + seL4_CapRights::new( + // NB: RW 'cuz W-only silently gets upgraded by kernel + /*grant_reply=*/ + 0, /*grant=*/ 0, /*read=1*/ 1, /*write=*/ 1, + ), + seL4_Default_VMAttributes, + ) + .map_err(|_| SecurityRequestError::SreTestFailed)?; + + // Write to the message buffer through the copyregion. + let offset_a = 0 as isize; + let offset_b = (MESSAGE_SIZE_DWORDS - 1) as isize; + message_ptr.offset(offset_a).write(0xDEADBEEF); + message_ptr.offset(offset_b).write(0xF00DCAFE); + trace!( + "test_mailbox: old buf contents 0x{:X} 0x{:X}", + message_ptr.offset(offset_a).read(), + message_ptr.offset(offset_b).read() + ); + + // Send the _physical_ address of the message buffer to the security + // core. + let paddr = seL4_Page_GetAddress(frame_bundle.objs[0].cptr); + mailbox_api_send( + paddr.paddr as u32, + (MESSAGE_SIZE_DWORDS * size_of::()) as u32, + ); + + // Wait for the response to arrive. + let mut response_paddr: u32 = 0; + let mut response_size: u32 = 0; + mailbox_api_receive( + &mut response_paddr as *mut u32, + &mut response_size as *mut u32, + ); + + // The security core should have replaced the first and last dwords + // with 0x12345678 and 0x87654321. + trace!("test_mailbox: expected contents 0x12345678 0x87654321"); + trace!( + "test_mailbox: new buf contents 0x{:X} 0x{:X}", + message_ptr.offset(offset_a).read(), + message_ptr.offset(offset_b).read() + ); + + let dword_a = message_ptr.offset(offset_a).read(); + let dword_b = message_ptr.offset(offset_b).read(); + + seL4_Page_Unmap(frame_bundle.objs[0].cptr) + .map_err(|_| SecurityRequestError::SreTestFailed)?; + + // Done, free the message buffer. + kata_object_free_toplevel(&frame_bundle) + .map_err(|_| SecurityRequestError::SreTestFailed)?; + + if dword_a != 0x12345678 || dword_b != 0x87654321 { + return Err(SecurityRequestError::SreTestFailed); + } + } + + trace!("test_mailbox_command() done"); + Ok(()) + } } diff --git a/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/impl.rs b/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/impl.rs index e822c83..a4c2dcb 100644 --- a/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/impl.rs +++ b/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/impl.rs @@ -84,8 +84,9 @@ impl SecurityCoordinatorInterface for SeL4SecurityCoordinator { Err(SreGetManifestFailed) } SecurityRequest::SrLoadApplication => { - let mut request = postcard::from_bytes::(&request_buffer[..]) - .map_err(deserialize_failure)?; + let mut request = + postcard::from_bytes::(&request_buffer[..]) + .map_err(deserialize_failure)?; request.set_container_cap(unsafe { SECURITY_RECV_SLOT }); trace!( "LOAD APPLICATION bundle_id {} app_binary {:?}", diff --git a/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/lib.rs b/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/lib.rs index 8ebb26d..9256244 100644 --- a/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/lib.rs +++ b/apps/system/components/SecurityCoordinator/kata-security-coordinator/src/lib.rs @@ -57,16 +57,34 @@ impl SecurityCoordinatorInterface for KataSecurityCoordinator { fn load_application(&self, bundle_id: &str) -> Result { self.manager.as_ref().unwrap().load_application(bundle_id) } - fn load_model(&self, bundle_id: &str, model_id: &str) -> Result { - self.manager.as_ref().unwrap().load_model(bundle_id, model_id) + fn load_model( + &self, + bundle_id: &str, + model_id: &str, + ) -> Result { + self.manager + .as_ref() + .unwrap() + .load_model(bundle_id, model_id) } fn read_key(&self, bundle_id: &str, key: &str) -> Result<&KeyValueData, SecurityRequestError> { self.manager.as_ref().unwrap().read_key(bundle_id, key) } - fn write_key(&mut self, bundle_id: &str, key: &str, value: &KeyValueData) -> Result<(), SecurityRequestError> { - self.manager.as_mut().unwrap().write_key(bundle_id, key, value) + fn write_key( + &mut self, + bundle_id: &str, + key: &str, + value: &KeyValueData, + ) -> Result<(), SecurityRequestError> { + self.manager + .as_mut() + .unwrap() + .write_key(bundle_id, key, value) } fn delete_key(&mut self, bundle_id: &str, key: &str) -> Result<(), SecurityRequestError> { self.manager.as_mut().unwrap().delete_key(bundle_id, key) } + fn test_mailbox(&mut self) -> Result<(), SecurityRequestError> { + self.manager.as_mut().unwrap().test_mailbox() + } } diff --git a/apps/system/components/SecurityCoordinator/kata-security-interface/src/lib.rs b/apps/system/components/SecurityCoordinator/kata-security-interface/src/lib.rs index f79bd85..9bdc7f5 100644 --- a/apps/system/components/SecurityCoordinator/kata-security-interface/src/lib.rs +++ b/apps/system/components/SecurityCoordinator/kata-security-interface/src/lib.rs @@ -166,6 +166,12 @@ pub struct DeleteKeyRequest<'a> { } impl<'a> SecurityCapability for DeleteKeyRequest<'a> {} +// SecurityRequestTestMailbox +#[derive(Debug, Serialize, Deserialize)] +pub struct TestMailboxRequest { +} +impl SecurityCapability for TestMailboxRequest {} + // NB: this is the union of InstallInterface & StorageInterface because // the camkes-generated interface code uses basic C which does not // tolerate overlapping member names. @@ -197,6 +203,7 @@ pub enum SecurityRequestError { SreReadFailed, SreWriteFailed, SreDeleteFailed, + SreTestFailed, } impl From for StorageError { @@ -232,6 +239,8 @@ pub enum SecurityRequest { SrReadKey, // Read key value [bundle_id, key] -> value SrWriteKey, // Write key value [bundle_id, key, value] SrDeleteKey, // Delete key [bundle_id, key] + + SrTestMailbox, // Run mailbox tests } // Interface to underlying facilities; also used to inject fakes for unit tests. @@ -245,6 +254,7 @@ pub trait SecurityCoordinatorInterface { fn read_key(&self, bundle_id: &str, key: &str) -> Result<&KeyValueData, SecurityRequestError>; fn write_key(&mut self, bundle_id: &str, key: &str, value: &KeyValueData) -> Result<(), SecurityRequestError>; fn delete_key(&mut self, bundle_id: &str, key: &str) -> Result<(), SecurityRequestError>; + fn test_mailbox(&mut self) -> Result<(), SecurityRequestError>; } #[inline] @@ -462,3 +472,13 @@ pub fn kata_security_delete_key( &mut [0u8; SECURITY_REPLY_DATA_SIZE], ) } + +#[inline] +#[allow(dead_code)] +pub fn kata_security_test_mailbox() -> Result<(), SecurityRequestError> { + kata_security_request( + SecurityRequest::SrTestMailbox, + &TestMailboxRequest {}, + &mut [0u8; SECURITY_REPLY_DATA_SIZE], + ) +} diff --git a/apps/system/interfaces/MailboxInterface.camkes b/apps/system/interfaces/MailboxInterface.camkes new file mode 100644 index 0000000..97a1e4b --- /dev/null +++ b/apps/system/interfaces/MailboxInterface.camkes @@ -0,0 +1,4 @@ +procedure MailboxAPI { + void send(in uint32_t request_paddr, in uint32_t request_size); + void receive(out uint32_t response_paddr, out uint32_t response_size); +}; diff --git a/apps/system/system.camkes b/apps/system/system.camkes index 30d85cd..0716326 100644 --- a/apps/system/system.camkes +++ b/apps/system/system.camkes @@ -21,6 +21,7 @@ import "components/MemoryManager/MemoryManager.camkes"; import "components/StorageManager/StorageManager.camkes"; import "components/SecurityCoordinator/SecurityCoordinator.camkes"; import "components/TimerService/TimerService.camkes"; +import "components/MailboxDriver/MailboxDriver.camkes"; component OpenTitanUART { hardware; @@ -55,6 +56,14 @@ component BuiltinCpioArchive { dataport Buf(0x1000000) cpio; } +component MailboxHardware { + hardware; + dataport Buf mmio; + emits Interrupt wtirq; + emits Interrupt rtirq; + emits Interrupt eirq; +} + assembly { composition { component VectorCoreHw vctop; @@ -76,6 +85,20 @@ assembly { connection seL4HardwareMMIO cpio_archive(from debug_console.cpio_archive, to cpio.cpio); + // MailboxDriver + component MailboxHardware mailbox_hardware; + component MailboxDriver mailbox_driver; + connection seL4HardwareMMIO mailbox_driver_mmio( + from mailbox_driver.mailbox_mmio, to mailbox_hardware.mmio); + connection seL4HardwareInterrupt mailbox_driver_wtirq( + from mailbox_hardware.wtirq, to mailbox_driver.wtirq); + connection seL4HardwareInterrupt mailbox_driver_rtirq( + from mailbox_hardware.rtirq, to mailbox_driver.rtirq); + connection seL4HardwareInterrupt mailbox_driver_eirq( + from mailbox_hardware.eirq, to mailbox_driver.eirq); + connection seL4RPCCall security_coordinator_to_mailbox_api( + from security_coordinator.mailbox_api, to mailbox_driver.api); + // OpenTitanUARTDriver connection seL4HardwareMMIO uart_mem(from uart_driver.mmio_region, to uart.mmio_region); @@ -165,6 +188,7 @@ assembly { from security_coordinator.logger, from storage_manager.logger, from timer_service.logger, + from mailbox_driver.logger, to debug_console.logger); } @@ -172,6 +196,14 @@ assembly { cpio.cpio_paddr = 0x46000000; cpio.cpio_size = 0x1000000; + mailbox_hardware.mmio_paddr = 0x540F1000; + mailbox_hardware.mmio_size = 0x00001000; + mailbox_hardware.wtirq_irq_number = 10; // kTopMatchaPlicIrqIdMailboxSmcWtirq + mailbox_hardware.rtirq_irq_number = 11; // kTopMatchaPlicIrqIdMailboxSmcRtirq + mailbox_hardware.eirq_irq_number = 12; // kTopMatchaPlicIrqIdMailboxSmcEirq + + mailbox_driver.rx_semaphore_value = 0; + uart.mmio_region_paddr = 0x50000000; uart.mmio_region_size = 0x1000; uart.tx_watermark_irq_number = 1;