Add kata-os-common::camkes support.

Add a new "camkes" submodule that consolidates KataOS CAmkES component
integration boilerplate. Each component is expected to declare:

static mut CAMKES: Camkes = Camkes::new("ProcessManager");

and then (typically) use "pre_init" to setup the logger, heap, and the
slot allocator. More fine-grained control is provided by:

fn init_logger(self: &Cmakes, level: Log::LevelFilter);
fn init_allocator(self: &Camkes, heap: &'static mut [u8]);
fn init_slot_allocator(self: &Camkes, first_slot: seL4_CPtr, last_slot: seL4_CPtr);

When receiving capabilities use "init_recv_path" to setup the IPCBuffer
receive path and "assert_recv_path" & "check_recv_path" calls to verify
noting has clobbered the setting.

The debug_assert_slot_* macros are wrapped in Camkes:: functions and a
"top_level_path" function for constructing seL4_CPath objects. Altogether
this normally allows a component to be written without direct use of the
CAmkES global static identifiers SELF_CNODE*.

Change-Id: Ia1351e411a5355789cf74bc0fcfe0e41a418b7d4
GitOrigin-RevId: fb81a8e0687ed9321c9961410edd5dbd54093ce5
This commit is contained in:
Sam Leffler 2022-05-20 20:45:53 +00:00
parent 3bd8389a4c
commit ddacc3762e
11 changed files with 214 additions and 301 deletions

View File

@ -12,51 +12,23 @@
#![no_std] #![no_std]
use core::slice; use core::slice;
use kata_os_common::allocator; use kata_os_common::camkes::Camkes;
use kata_os_common::logger::KataLogger;
use kata_os_common::sel4_sys;
use kata_os_common::slot_allocator;
use log::trace;
use sel4_sys::seL4_CPtr;
use slot_allocator::KATA_CSPACE_SLOTS;
extern "C" { extern "C" {
static SELF_CNODE_FIRST_SLOT: seL4_CPtr;
static SELF_CNODE_LAST_SLOT: seL4_CPtr;
static cpio_archive: *const u8; // CPIO archive of built-in files static cpio_archive: *const u8; // CPIO archive of built-in files
} }
#[no_mangle] static mut CAMKES: Camkes = Camkes::new("DebugConsole");
pub extern "C" fn pre_init() {
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
// NB: set to Trace for early-boot msgs
log::set_max_level(log::LevelFilter::Debug);
#[no_mangle]
pub unsafe extern "C" fn pre_init() {
// TODO(b/200946906): Review per-component heap allocations, including this one. // TODO(b/200946906): Review per-component heap allocations, including this one.
const HEAP_SIZE: usize = 1 << 20; const HEAP_SIZE: usize = 1 << 20;
static mut HEAP_MEMORY: [u8; HEAP_SIZE] = [0; HEAP_SIZE]; static mut HEAP_MEMORY: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
unsafe { CAMKES.pre_init(
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); log::LevelFilter::Debug,
trace!( &mut HEAP_MEMORY,
"setup heap: start_addr {:p} size {}", );
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
);
}
unsafe {
KATA_CSPACE_SLOTS.init(
/*first_slot=*/ SELF_CNODE_FIRST_SLOT,
/*size=*/ SELF_CNODE_LAST_SLOT - SELF_CNODE_FIRST_SLOT
);
trace!("setup cspace slots: first slot {} free {}",
KATA_CSPACE_SLOTS.base_slot(),
KATA_CSPACE_SLOTS.free_slots());
}
} }
/// Entry point for DebugConsole. Runs the shell with UART IO. /// Entry point for DebugConsole. Runs the shell with UART IO.

View File

@ -6,56 +6,37 @@
use core::ops::Range; use core::ops::Range;
use core::slice; use core::slice;
use kata_os_common::allocator;
use kata_os_common::logger::KataLogger;
use kata_os_common::slot_allocator;
use kata_memory_interface::MemoryManagerError; use kata_memory_interface::MemoryManagerError;
use kata_memory_interface::MemoryManagerInterface; use kata_memory_interface::MemoryManagerInterface;
use kata_memory_interface::ObjDescBundle; use kata_memory_interface::ObjDescBundle;
use kata_memory_interface::RawMemoryStatsData; use kata_memory_interface::RawMemoryStatsData;
use kata_memory_manager::KataMemoryManager; use kata_memory_manager::KataMemoryManager;
use kata_os_common::camkes::Camkes;
use kata_os_common::sel4_sys; use kata_os_common::sel4_sys;
use log::{info, trace}; use log::trace;
use slot_allocator::KATA_CSPACE_SLOTS;
use sel4_sys::seL4_BootInfo; use sel4_sys::seL4_BootInfo;
use sel4_sys::seL4_CNode_Delete; use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr; use sel4_sys::seL4_CPtr;
use sel4_sys::seL4_GetCapReceivePath;
use sel4_sys::seL4_SetCapReceivePath; static mut CAMKES: Camkes = Camkes::new("MemoryManager");
use sel4_sys::seL4_Word;
use sel4_sys::seL4_WordBits;
// NB: KATA_MEMORY cannot be used before setup is completed with a call to init() // NB: KATA_MEMORY cannot be used before setup is completed with a call to init()
static mut KATA_MEMORY: KataMemoryManager = KataMemoryManager::empty(); static mut KATA_MEMORY: KataMemoryManager = KataMemoryManager::empty();
extern "C" { extern "C" {
// Each CAmkES-generated CNode has a writable self-reference to itself in // Each CAmkES-component has a CNode setup at a well-known top-level slot.
// the slot SELF_CNODE. This is used to pass CNode containers of dynamically
// allocated objects between clients & the MemoryManager.
static SELF_CNODE: seL4_CPtr;
// Each CAmkES-component has a CNode setup at a well-known slot in SELF_CNODE.
// We re-use that slot to receive CNode caps passed with alloc & free requests. // We re-use that slot to receive CNode caps passed with alloc & free requests.
static MEMORY_RECV_CNODE: seL4_CPtr; static MEMORY_RECV_CNODE: seL4_CPtr;
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pre_init() { pub unsafe extern "C" fn pre_init() {
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
// NB: set to max; the LoggerInterface will filter // NB: set to max; the LoggerInterface will filter
log::set_max_level(log::LevelFilter::Trace); CAMKES.init_logger(log::LevelFilter::Trace);
// TODO(sleffler): temp until we integrate with seL4
static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024]; static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024];
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); CAMKES.init_allocator(&mut HEAP_MEMORY);
trace!(
"setup heap: start_addr {:p} size {}",
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
);
extern "C" { extern "C" {
fn sel4runtime_bootinfo() -> *const seL4_BootInfo; fn sel4runtime_bootinfo() -> *const seL4_BootInfo;
@ -77,18 +58,12 @@ pub unsafe extern "C" fn pre_init() {
); );
} }
KATA_CSPACE_SLOTS.init( CAMKES.init_slot_allocator(bootinfo.empty.start, bootinfo.empty.end);
/*first_slot=*/ bootinfo.empty.start,
/*size=*/ bootinfo.empty.end - bootinfo.empty.start
);
trace!("setup cspace slots: first slot {} free {}",
KATA_CSPACE_SLOTS.base_slot(),
KATA_CSPACE_SLOTS.free_slots());
// Delete the CAmkES-setup CNode; we're going to reuse the // Delete the CAmkES-setup CNode; we're going to reuse the
// well-known slot once it is empty (see memory__init below). // well-known slot once it is empty (see memory__init below).
seL4_CNode_Delete(SELF_CNODE, MEMORY_RECV_CNODE, seL4_WordBits as u8) let path = Camkes::top_level_path(MEMORY_RECV_CNODE);
.expect("recv_node"); seL4_CNode_Delete(path.0, path.1, path.2 as u8).expect("recv_node");
} }
#[no_mangle] #[no_mangle]
@ -100,30 +75,19 @@ pub unsafe extern "C" fn memory__init() {
// NB: this must be done here (rather than someplace like pre_init) // NB: this must be done here (rather than someplace like pre_init)
// so it's in the context of the MemoryInterface thread (so we write // so it's in the context of the MemoryInterface thread (so we write
// the correct ipc buffer). // the correct ipc buffer).
seL4_SetCapReceivePath(SELF_CNODE, MEMORY_RECV_CNODE, seL4_WordBits); CAMKES.init_recv_path(&Camkes::top_level_path(MEMORY_RECV_CNODE));
trace!("Cap receive path {}:{}:{}", SELF_CNODE, MEMORY_RECV_CNODE, seL4_WordBits);
} }
// MemoryInterface glue stubs. // MemoryInterface glue stubs.
// Clears any capability the specified path points to.
fn clear_path(&(root, index, depth): &(seL4_CPtr, seL4_CPtr, seL4_Word)) {
// TODO(sleffler): assert since future receives are likely to fail?
if let Err(e) = unsafe { seL4_CNode_Delete(root, index, depth as u8) } {
// NB: no error is returned if the slot is empty.
info!("Failed to clear receive path {:?}: {:?}",
(root, index, depth), e);
}
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn memory_alloc( pub unsafe extern "C" fn memory_alloc(
c_raw_data_len: u32, c_raw_data_len: u32,
c_raw_data: *const u8, c_raw_data: *const u8,
) -> MemoryManagerError { ) -> MemoryManagerError {
let recv_path = seL4_GetCapReceivePath(); let recv_path = CAMKES.get_current_recv_path();
// NB: make sure noone clobbers the setup done in memory__init // NB: make sure noone clobbers the setup done in memory__init
assert_eq!(recv_path, (SELF_CNODE, MEMORY_RECV_CNODE, seL4_WordBits)); CAMKES.assert_recv_path();
let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize); let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize);
let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) { let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) {
@ -136,7 +100,7 @@ pub unsafe extern "C" fn memory_alloc(
Err(_) => MemoryManagerError::MmeDeserializeFailed, Err(_) => MemoryManagerError::MmeDeserializeFailed,
}; };
// NB: must clear ReceivePath for next request // NB: must clear ReceivePath for next request
clear_path(&recv_path); CAMKES.clear_recv_path();
ret_status ret_status
} }
@ -145,9 +109,9 @@ pub unsafe extern "C" fn memory_free(
c_raw_data_len: u32, c_raw_data_len: u32,
c_raw_data: *const u8, c_raw_data: *const u8,
) -> MemoryManagerError { ) -> MemoryManagerError {
let recv_path = seL4_GetCapReceivePath(); let recv_path = CAMKES.get_current_recv_path();
// NB: make sure noone clobbers the setup done in memory__init // NB: make sure noone clobbers the setup done in memory__init
assert_eq!(recv_path, (SELF_CNODE, MEMORY_RECV_CNODE, seL4_WordBits)); CAMKES.assert_recv_path();
let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize); let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize);
let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) { let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) {
@ -160,7 +124,7 @@ pub unsafe extern "C" fn memory_free(
Err(_) => MemoryManagerError::MmeDeserializeFailed, Err(_) => MemoryManagerError::MmeDeserializeFailed,
}; };
// NB: must clear ReceivePath for next request // NB: must clear ReceivePath for next request
clear_path(&recv_path); CAMKES.clear_recv_path();
ret_status ret_status
} }

View File

@ -8,46 +8,18 @@ use cstr_core::CStr;
use kata_ml_coordinator::MLCoordinator; use kata_ml_coordinator::MLCoordinator;
use kata_ml_coordinator::ModelIdx; use kata_ml_coordinator::ModelIdx;
use kata_ml_interface::MlCoordError; use kata_ml_interface::MlCoordError;
use kata_os_common::allocator; use kata_os_common::camkes::Camkes;
use kata_os_common::logger::KataLogger;
use kata_os_common::sel4_sys;
use kata_os_common::slot_allocator::KATA_CSPACE_SLOTS;
use kata_timer_interface::*; use kata_timer_interface::*;
use log::{error, trace}; use log::error;
use sel4_sys::seL4_CPtr;
use spin::Mutex; use spin::Mutex;
static mut CAMKES: Camkes = Camkes::new("MlCoordinator");
static mut ML_COORD: Mutex<MLCoordinator> = Mutex::new(MLCoordinator::new()); static mut ML_COORD: Mutex<MLCoordinator> = Mutex::new(MLCoordinator::new());
extern "C" {
static SELF_CNODE_FIRST_SLOT: seL4_CPtr;
static SELF_CNODE_LAST_SLOT: seL4_CPtr;
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pre_init() { 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);
// TODO(sleffler): temp until we integrate with seL4
static mut HEAP_MEMORY: [u8; 4 * 1024] = [0; 4 * 1024]; static mut HEAP_MEMORY: [u8; 4 * 1024] = [0; 4 * 1024];
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); CAMKES.pre_init(log::LevelFilter::Trace, &mut HEAP_MEMORY);
trace!(
"setup heap: start_addr {:p} size {}",
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
);
KATA_CSPACE_SLOTS.init(
/*first_slot=*/ SELF_CNODE_FIRST_SLOT,
/*size=*/ SELF_CNODE_LAST_SLOT - SELF_CNODE_FIRST_SLOT,
);
trace!(
"setup cspace slots: first slot {} free {}",
KATA_CSPACE_SLOTS.base_slot(),
KATA_CSPACE_SLOTS.free_slots()
);
} }
#[no_mangle] #[no_mangle]
@ -56,7 +28,7 @@ pub unsafe extern "C" fn mlcoord__init() {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn run() { pub unsafe extern "C" fn run() {
loop { loop {
timer_service_wait(); timer_service_wait();
let completed = timer_service_completed_timers(); let completed = timer_service_completed_timers();
@ -64,10 +36,8 @@ pub extern "C" fn run() {
for i in 0..31 { for i in 0..31 {
let idx: u32 = 1 << i; let idx: u32 = 1 << i;
if completed & idx != 0 { if completed & idx != 0 {
unsafe { if let Err(e) = ML_COORD.lock().timer_completed(i as ModelIdx) {
if let Err(e) = ML_COORD.lock().timer_completed(i as ModelIdx) { error!("Error when trying to run periodic model: {:?}", e);
error!("Error when trying to run periodic model: {:?}", e);
}
} }
} }
} }

View File

@ -7,83 +7,34 @@
use core::slice; use core::slice;
use cstr_core::CStr; use cstr_core::CStr;
use kata_memory_interface::ObjDescBundle; use kata_memory_interface::ObjDescBundle;
use kata_os_common::allocator; use kata_os_common::camkes::Camkes;
use kata_os_common::logger::KataLogger;
use kata_os_common::slot_allocator; use kata_os_common::slot_allocator;
use kata_os_common::sel4_sys; use kata_os_common::sel4_sys;
use kata_proc_interface::*; use kata_proc_interface::*;
use kata_proc_manager::KATA_PROC; use kata_proc_manager::KATA_PROC;
use log::{info, trace}; use log::trace;
use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr; use sel4_sys::seL4_CPtr;
use sel4_sys::seL4_GetCapReceivePath;
use sel4_sys::seL4_SetCapReceivePath;
use sel4_sys::seL4_Word;
use sel4_sys::seL4_WordBits;
use slot_allocator::KATA_CSPACE_SLOTS; use slot_allocator::KATA_CSPACE_SLOTS;
// TODO(sleffler): belongs in sel4-sys static mut CAMKES: Camkes = Camkes::new("ProcessManager");
#[allow(non_camel_case_types)]
type seL4_Path = (seL4_CPtr, seL4_CPtr, seL4_Word);
extern "C" {
// Each CAmkES-generated CNode has a writable self-reference to itself in
// the slot SELF_CNODE.
static SELF_CNODE: seL4_CPtr;
static SELF_CNODE_FIRST_SLOT: seL4_CPtr;
static SELF_CNODE_LAST_SLOT: seL4_CPtr;
}
// TODO(sleffler): 0 is valid // TODO(sleffler): 0 is valid
static mut PKG_MGMT_RECV_SLOT: seL4_CPtr = 0; static mut PKG_MGMT_RECV_SLOT: seL4_CPtr = 0;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pre_init() { pub unsafe extern "C" fn pre_init() {
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
// NB: set to max; the LoggerInterface will filter
log::set_max_level(log::LevelFilter::Trace);
static mut HEAP_MEMORY: [u8; 16 * 1024] = [0; 16 * 1024]; static mut HEAP_MEMORY: [u8; 16 * 1024] = [0; 16 * 1024];
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); CAMKES.pre_init(log::LevelFilter::Trace, &mut HEAP_MEMORY);
trace!(
"setup heap: start_addr {:p} size {}",
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
);
// Complete KATA_PROC setup. This is as early as we can do it given that // Complete KATA_PROC setup now that Global allocator is setup.
// it needs the GlobalAllocator.
KATA_PROC.init(); KATA_PROC.init();
trace!("ProcessManager has capacity for {} bundles", KATA_PROC.capacity()); trace!("ProcessManager has capacity for {} bundles", KATA_PROC.capacity());
KATA_CSPACE_SLOTS.init(
/*first_slot=*/ SELF_CNODE_FIRST_SLOT,
/*size=*/ SELF_CNODE_LAST_SLOT - SELF_CNODE_FIRST_SLOT
);
trace!("setup cspace slots: first slot {} free {}",
KATA_CSPACE_SLOTS.base_slot(),
KATA_CSPACE_SLOTS.free_slots());
PKG_MGMT_RECV_SLOT = KATA_CSPACE_SLOTS.alloc(1).unwrap(); PKG_MGMT_RECV_SLOT = KATA_CSPACE_SLOTS.alloc(1).unwrap();
} }
fn debug_check_empty(tag: &str, path: &seL4_Path) {
sel4_sys::debug_assert_slot_empty!(path.1,
"{}: expected slot {:?} empty but has cap type {:?}",
tag, path, sel4_sys::cap_identify(path.1));
}
fn init_recv_path(tag: &str, path: &seL4_Path) {
unsafe { seL4_SetCapReceivePath(path.0, path.1, path.2); }
info!("{}: cap receive path {:?}", tag, path);
debug_check_empty("init_recv_path", path);
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pkg_mgmt__init() { pub unsafe extern "C" fn pkg_mgmt__init() {
// Point the receive path to the well-known slot for receiving // Point the receive path to the well-known slot for receiving
@ -92,14 +43,7 @@ pub unsafe extern "C" fn pkg_mgmt__init() {
// NB: this must be done here (rather than someplace like pre_init) // NB: this must be done here (rather than someplace like pre_init)
// so it's in the context of the PackageManagementInterface thread // so it's in the context of the PackageManagementInterface thread
// (so we write the correct ipc buffer). // (so we write the correct ipc buffer).
init_recv_path("pkg_mgmt", CAMKES.init_recv_path(&Camkes::top_level_path(PKG_MGMT_RECV_SLOT));
&(SELF_CNODE, PKG_MGMT_RECV_SLOT, seL4_WordBits));
}
// Clears any capability the specified path points to.
fn clear_path(path: &seL4_Path) {
assert!(unsafe { seL4_CNode_Delete(path.0, path.1, path.2 as u8) }.is_ok());
debug_check_empty("clear_path", path);
} }
// PackageManagerInterface glue stubs. // PackageManagerInterface glue stubs.
@ -109,16 +53,14 @@ pub unsafe extern "C" fn pkg_mgmt_install(
c_request: *const u8, c_request: *const u8,
c_raw_data: *mut RawBundleIdData, c_raw_data: *mut RawBundleIdData,
) -> ProcessManagerError { ) -> ProcessManagerError {
let recv_path = seL4_GetCapReceivePath(); let recv_path = CAMKES.get_current_recv_path();
// NB: make sure noone clobbers the setup done in pkg_mgmt__init // NB: make sure noone clobbers the setup done in pkg_mgmt__init
assert_eq!(recv_path, (SELF_CNODE, PKG_MGMT_RECV_SLOT, seL4_WordBits)); CAMKES.assert_recv_path();
let request_slice = slice::from_raw_parts(c_request, c_request_len as usize); let request_slice = slice::from_raw_parts(c_request, c_request_len as usize);
let ret_status = match postcard::from_bytes::<ObjDescBundle>(request_slice) { let ret_status = match postcard::from_bytes::<ObjDescBundle>(request_slice) {
Ok(mut pkg_contents) => { Ok(mut pkg_contents) => {
sel4_sys::debug_assert_slot_cnode!(recv_path.1, Camkes::debug_assert_slot_cnode("pkg_mgmt_install", &recv_path);
"Expected cnode in slot {} but has cap type {:?}",
recv_path.1, sel4_sys::cap_identify(recv_path.1));
pkg_contents.cnode = recv_path.1; pkg_contents.cnode = recv_path.1;
match KATA_PROC.install(&pkg_contents) { match KATA_PROC.install(&pkg_contents) {
Ok(bundle_id) => match postcard::to_slice(&bundle_id, &mut (*c_raw_data)[..]) { Ok(bundle_id) => match postcard::to_slice(&bundle_id, &mut (*c_raw_data)[..]) {
@ -130,25 +72,17 @@ pub unsafe extern "C" fn pkg_mgmt_install(
} }
Err(e) => e.into(), Err(e) => e.into(),
}; };
clear_path(&recv_path); CAMKES.clear_recv_path();
ret_status ret_status
} }
fn check_pkg_mgmt_empty(tag: &str) -> seL4_Path {
unsafe {
let recv_path = seL4_GetCapReceivePath();
// NB: make sure noone clobbers the setup done in pkg_mgmt__init
assert_eq!(recv_path, (SELF_CNODE, PKG_MGMT_RECV_SLOT, seL4_WordBits));
debug_check_empty(tag, &recv_path);
recv_path
}
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pkg_mgmt_uninstall( pub unsafe extern "C" fn pkg_mgmt_uninstall(
c_bundle_id: *const cstr_core::c_char c_bundle_id: *const cstr_core::c_char
) -> ProcessManagerError { ) -> ProcessManagerError {
let recv_path = check_pkg_mgmt_empty("pkg_mgmt_uninstall"); let recv_path = CAMKES.get_current_recv_path();
CAMKES.assert_recv_path();
Camkes::debug_assert_slot_empty("pkg_mgmt_uninstall", &recv_path);
let ret_status = match CStr::from_ptr(c_bundle_id).to_str() { let ret_status = match CStr::from_ptr(c_bundle_id).to_str() {
Ok(bundle_id) => match KATA_PROC.uninstall(bundle_id) { Ok(bundle_id) => match KATA_PROC.uninstall(bundle_id) {
Ok(_) => ProcessManagerError::Success, Ok(_) => ProcessManagerError::Success,
@ -156,7 +90,7 @@ pub unsafe extern "C" fn pkg_mgmt_uninstall(
}, },
Err(_) => ProcessManagerError::BundleIdInvalid, Err(_) => ProcessManagerError::BundleIdInvalid,
}; };
debug_check_empty("pkg_mgmt_uninstall", &recv_path); Camkes::debug_assert_slot_empty("pkg_mgmt_uninstall", &recv_path);
ret_status ret_status
} }

View File

@ -5,64 +5,32 @@
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
use core::slice; use core::slice;
use kata_os_common::allocator; use kata_os_common::camkes::Camkes;
use kata_os_common::cspace_slot::CSpaceSlot; use kata_os_common::cspace_slot::CSpaceSlot;
use kata_os_common::logger::KataLogger;
use kata_os_common::sel4_sys; use kata_os_common::sel4_sys;
use kata_os_common::slot_allocator::KATA_CSPACE_SLOTS; use kata_os_common::slot_allocator::KATA_CSPACE_SLOTS;
use kata_security_coordinator::KATA_SECURITY; use kata_security_coordinator::KATA_SECURITY;
use kata_security_interface::*; use kata_security_interface::*;
use kata_storage_interface::KEY_VALUE_DATA_SIZE; use kata_storage_interface::KEY_VALUE_DATA_SIZE;
use log::{info, trace}; use log::trace;
use SecurityRequestError::*; use SecurityRequestError::*;
use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr; use sel4_sys::seL4_CPtr;
use sel4_sys::seL4_GetCapReceivePath;
use sel4_sys::seL4_SetCap; use sel4_sys::seL4_SetCap;
use sel4_sys::seL4_SetCapReceivePath;
use sel4_sys::seL4_Word;
use sel4_sys::seL4_WordBits;
extern "C" {
// Each CAmkES-generated CNode has a writable self-reference to itself in
// the slot SELF_CNODE.
static SELF_CNODE: seL4_CPtr;
static SELF_CNODE_FIRST_SLOT: seL4_CPtr;
static SELF_CNODE_LAST_SLOT: seL4_CPtr;
}
static mut CAMKES: Camkes = Camkes::new("SecurityCoordinator");
static mut SECURITY_RECV_SLOT: seL4_CPtr = 0; static mut SECURITY_RECV_SLOT: seL4_CPtr = 0;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pre_init() { pub unsafe extern "C" fn pre_init() {
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
// NB: set to max; the LoggerInterface will filter
log::set_max_level(log::LevelFilter::Trace);
static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024]; static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024];
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); // NB: set to max; the LoggerInterface will filter
trace!( CAMKES.pre_init(log::LevelFilter::Trace, &mut HEAP_MEMORY);
"setup heap: start_addr {:p} size {}",
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
);
// Complete KATA_SECURITY setup. This is as early as we can do it given that // Complete KATA_SECURITY setup after Global allocator is setup.
// it needs the GlobalAllocator.
KATA_SECURITY.init(); KATA_SECURITY.init();
KATA_CSPACE_SLOTS.init(
/*first_slot=*/ SELF_CNODE_FIRST_SLOT,
/*size=*/ SELF_CNODE_LAST_SLOT - SELF_CNODE_FIRST_SLOT
);
trace!("setup cspace slots: first slot {} free {}",
KATA_CSPACE_SLOTS.base_slot(),
KATA_CSPACE_SLOTS.free_slots());
SECURITY_RECV_SLOT = KATA_CSPACE_SLOTS.alloc(1).unwrap(); SECURITY_RECV_SLOT = KATA_CSPACE_SLOTS.alloc(1).unwrap();
} }
@ -75,26 +43,9 @@ pub unsafe extern "C" fn security__init() {
// NB: this must be done here (rather than someplace like pre_init) // NB: this must be done here (rather than someplace like pre_init)
// so it's in the context of the SecurityCoordinatorInterface thread // so it's in the context of the SecurityCoordinatorInterface thread
// (so we write the correct ipc buffer). // (so we write the correct ipc buffer).
let path = (SELF_CNODE, SECURITY_RECV_SLOT, seL4_WordBits); let path = &Camkes::top_level_path(SECURITY_RECV_SLOT);
seL4_SetCapReceivePath(path.0, path.1, path.2); CAMKES.init_recv_path(path);
info!("security cap receive path {:?}", path); Camkes::debug_assert_slot_empty("security__init", path);
debug_check_empty("security__init", &path);
}
fn debug_check_empty(tag: &str, path: &(seL4_CPtr, seL4_CPtr, seL4_Word)) {
sel4_sys::debug_assert_slot_empty!(path.1,
"{}: expected slot {:?} empty but has cap type {:?}",
tag, path, sel4_sys::cap_identify(path.1));
}
// Clears any capability the specified path points to.
fn _clear_path(path: &(seL4_CPtr, seL4_CPtr, seL4_Word)) {
// TODO(sleffler): assert since future receives are likely to fail?
if let Err(e) = unsafe { seL4_CNode_Delete(path.0, path.1, path.2 as u8) } {
// NB: no error is returned if the slot is empty.
info!("Failed to clear receive path {:?}: {:?}", path, e);
}
debug_check_empty("clear_path", path);
} }
fn serialize_failure(e: postcard::Error) -> SecurityRequestError { fn serialize_failure(e: postcard::Error) -> SecurityRequestError {
@ -123,10 +74,8 @@ fn install_request(
request_buffer: &[u8], request_buffer: &[u8],
reply_buffer: &mut [u8] reply_buffer: &mut [u8]
) -> Result<(), SecurityRequestError> { ) -> Result<(), SecurityRequestError> {
let recv_path = unsafe { seL4_GetCapReceivePath() }; let recv_path = unsafe { CAMKES.get_current_recv_path() };
sel4_sys::debug_assert_slot_cnode!(recv_path.1, Camkes::debug_assert_slot_cnode("install_request", &recv_path);
"install_request: expected cnode in slot {:?} but found cap type {:?}",
recv_path, sel4_sys::cap_identify(recv_path.1));
let mut request = postcard::from_bytes::<InstallRequest>(request_buffer) let mut request = postcard::from_bytes::<InstallRequest>(request_buffer)
.map_err(deserialize_failure)?; // XXX clear_path .map_err(deserialize_failure)?; // XXX clear_path

View File

@ -7,29 +7,18 @@
extern crate alloc; extern crate alloc;
use core::slice; use core::slice;
use cstr_core::CStr; use cstr_core::CStr;
use kata_os_common::allocator; use kata_os_common::camkes::Camkes;
use kata_os_common::logger::KataLogger;
use kata_storage_interface::KeyValueData; use kata_storage_interface::KeyValueData;
use kata_storage_interface::StorageManagerError; use kata_storage_interface::StorageManagerError;
use kata_storage_interface::StorageManagerInterface; use kata_storage_interface::StorageManagerInterface;
use kata_storage_manager::KATA_STORAGE; use kata_storage_manager::KATA_STORAGE;
use log::trace;
static mut CAMKES: Camkes = Camkes::new("StorageManager");
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pre_init() { pub unsafe extern "C" fn pre_init() {
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
// NB: set to max; the LoggerInterface will filter
log::set_max_level(log::LevelFilter::Trace);
// TODO(sleffler): temp until we integrate with seL4
static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024]; static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024];
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); CAMKES.pre_init(log::LevelFilter::Trace, &mut HEAP_MEMORY);
trace!(
"setup heap: start_addr {:p} size {}",
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
);
} }
// StorageInterface glue stubs. // StorageInterface glue stubs.

View File

@ -3,26 +3,19 @@
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
use core::time::Duration; use core::time::Duration;
use kata_os_common::allocator; use kata_os_common::camkes::Camkes;
use kata_os_common::logger::KataLogger;
use kata_os_common::sel4_sys::seL4_Word; use kata_os_common::sel4_sys::seL4_Word;
use kata_timer_interface::{TimerId, TimerServiceError}; use kata_timer_interface::{TimerId, TimerServiceError};
use kata_timer_service::TIMER_SRV; use kata_timer_service::TIMER_SRV;
use log::trace;
static mut CAMKES: Camkes = Camkes::new("TimerService");
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pre_init() { 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);
// TODO(jesionowski): temp until we integrate with seL4
static mut HEAP_MEMORY: [u8; 4 * 1024] = [0; 4 * 1024]; static mut HEAP_MEMORY: [u8; 4 * 1024] = [0; 4 * 1024];
allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len()); CAMKES.pre_init(
trace!( log::LevelFilter::Debug,
"setup heap: start_addr {:p} size {}", &mut HEAP_MEMORY,
HEAP_MEMORY.as_ptr(),
HEAP_MEMORY.len()
); );
} }

View File

@ -11,6 +11,7 @@ camkes_support = []
[dependencies] [dependencies]
allocator = { path = "src/allocator" } allocator = { path = "src/allocator" }
camkes = { path = "src/camkes" }
capdl = { path = "src/capdl" } capdl = { path = "src/capdl" }
cspace-slot = { path = "src/cspace-slot" } cspace-slot = { path = "src/cspace-slot" }
logger = { path = "src/logger" } logger = { path = "src/logger" }

View File

@ -0,0 +1,13 @@
cargo-features = ["edition2021"]
[package]
name = "camkes"
version = "0.1.0"
edition = "2021"
[dependencies]
log = "0.4"
allocator = { path = "../allocator" }
logger = { path = "../logger" }
sel4-sys = { path = "../sel4-sys" }
slot-allocator = { path = "../slot-allocator" }

View File

@ -0,0 +1,126 @@
//! Kata OS CAmkES component helpers
#![no_std]
#![allow(non_camel_case_types)]
use allocator;
use logger::KataLogger;
use slot_allocator::KATA_CSPACE_SLOTS;
use log::trace;
use sel4_sys;
use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr;
use sel4_sys::seL4_GetCapReceivePath;
use sel4_sys::seL4_SetCapReceivePath;
use sel4_sys::seL4_Word;
use sel4_sys::seL4_WordBits;
pub type seL4_CPath = (seL4_CPtr, seL4_CPtr, seL4_Word);
extern "C" {
// CAmkES components marked with
// attribute integer kataos = 1;
// automatically get a self-reference to their top-level CNode and
// the slot #'s of the first & last free slots in the CNode.
static SELF_CNODE: seL4_CPtr;
static SELF_CNODE_FIRST_SLOT: seL4_CPtr;
static SELF_CNODE_LAST_SLOT: seL4_CPtr;
}
pub struct Camkes {
name: &'static str, // Component name
recv_path: seL4_CPath, // IPCBuffer receive path
}
impl Camkes {
pub const fn new(name: &'static str) -> Self {
Camkes {
name,
recv_path: (seL4_CPtr::MAX, seL4_CPtr::MAX, seL4_Word::MAX),
}
}
pub fn init_logger(self: &Camkes, level: log::LevelFilter) {
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
log::set_max_level(level);
}
pub fn init_allocator(self: &Camkes, heap: &'static mut [u8]) {
unsafe {
allocator::ALLOCATOR.init(heap.as_mut_ptr() as usize, heap.len());
}
trace!("setup heap: start_addr {:p} size {}", heap.as_ptr(), heap.len());
}
pub fn init_slot_allocator(self: &Camkes, first_slot: seL4_CPtr, last_slot: seL4_CPtr) {
unsafe {
KATA_CSPACE_SLOTS.init(first_slot, last_slot - first_slot);
trace!("setup cspace slots: first slot {} free {}",
KATA_CSPACE_SLOTS.base_slot(),
KATA_CSPACE_SLOTS.free_slots());
}
}
pub fn pre_init(
self: &Camkes,
level: log::LevelFilter,
heap: &'static mut [u8],
) {
self.init_logger(level);
self.init_allocator(heap);
unsafe { self.init_slot_allocator(SELF_CNODE_FIRST_SLOT, SELF_CNODE_LAST_SLOT); }
}
pub fn top_level_path(slot: seL4_CPtr) -> seL4_CPath {
unsafe { (SELF_CNODE, slot, seL4_WordBits) }
}
// Initializes the IPCBuffer receive path with |path|.
pub fn init_recv_path(self: &mut Camkes, path: &seL4_CPath) {
self.recv_path = *path;
unsafe { seL4_SetCapReceivePath(path.0, path.1, path.2); }
trace!("Cap receive path {:?}", path);
}
// Returns the path specified with init_recv_path.
pub fn get_recv_path(self: &Camkes) -> seL4_CPath { self.recv_path }
// Returns the current receive path from the IPCBuffer.
pub fn get_current_recv_path(self: &Camkes) -> seL4_CPath {
unsafe { seL4_GetCapReceivePath() }
}
// Clears any capability the receive path path points to.
pub fn clear_recv_path(self: &Camkes) {
let path = &self.recv_path;
// Assert since future receives are likely to fail
unsafe { seL4_CNode_Delete(path.0, path.1, path.2 as u8) }.expect(self.name);
}
// Check the current receive path in the IPCBuffer against what was
// setup with init_recv_path.
pub fn check_recv_path(self: &Camkes) -> bool {
self.get_current_recv_path() == self.get_recv_path()
}
// Like check_recv_path but asserts if there is an inconsistency.
pub fn assert_recv_path(self: &Camkes) {
assert!(self.check_recv_path(),
"Current receive path {:?} does not match init'd path {:?}",
self.get_current_recv_path(), self.recv_path);
}
// Wrappers for sel4_sys::debug_assert macros.
pub fn debug_assert_slot_empty(tag: &str, path: &seL4_CPath) {
sel4_sys::debug_assert_slot_empty!(path.1,
"{}: expected slot {:?} empty but has cap type {:?}",
tag, path, sel4_sys::cap_identify(path.1));
}
pub fn debug_assert_slot_cnode(tag: &str, path: &seL4_CPath) {
sel4_sys::debug_assert_slot_cnode!(path.1,
"{}: expected cnode in slot {:?} but found cap type {:?}",
tag, path, sel4_sys::cap_identify(path.1));
}
}

View File

@ -1,11 +1,13 @@
#![no_std] #![no_std]
pub extern crate capdl;
pub extern crate model;
pub extern crate allocator; pub extern crate allocator;
pub extern crate logger; #[cfg(feature = "camkes_support")]
pub extern crate panic; pub extern crate camkes;
pub extern crate capdl;
#[cfg(feature = "camkes_support")] #[cfg(feature = "camkes_support")]
pub extern crate cspace_slot; pub extern crate cspace_slot;
pub extern crate slot_allocator; pub extern crate logger;
pub extern crate model;
pub extern crate panic;
pub extern crate sel4_sys; pub extern crate sel4_sys;
pub extern crate slot_allocator;