kata-os-model: misc fixups

Fallout from rootserver memory reclamation work:
- add CDL_Object::next_free_slot
- add CONFIG_NOISY_UNTYPEDS feature for spammy debug msgs
- add CONFIG_NOISY_CREATE_OBJECT msgs
- assert if bootinfo/untyped_cnode setup is wrong instead of
  logging msgs and then failing later
- bury ugly BIT usage in is_obj_inside_untyped
- revise handoff_cap api for future use in memory reclamation
- remove some unneeded type coercions
- streamline printing seL4_CPath's
- simplify get_object & get_asid

Change-Id: Ib2c3d717dd41b307cb7afd4821dee4b6be173d57
GitOrigin-RevId: 99f4b79e1df257d373accf96190a77a65ba3305f
This commit is contained in:
Sam Leffler
2022-07-13 19:04:23 +00:00
parent 0539aae221
commit a28057ea73
4 changed files with 62 additions and 54 deletions

View File

@@ -649,6 +649,15 @@ impl<'a> CDL_Object {
pub fn num_slots(&self) -> seL4_Word { pub fn num_slots(&self) -> seL4_Word {
self.slots.num self.slots.num
} }
// Returns the next available slot past those specified in the spec.
// Note we cannot use num_slots since there may be gaps in the
// numbering due to empty slots.
#[inline]
pub fn next_free_slot(&self) -> seL4_Word {
self.slots_slice().iter()
.max_by_key(|slot| slot.slot)
.map_or(0, |slot| slot.slot + 1)
}
#[inline] #[inline]
pub fn slot(&self, index: seL4_Word) -> CDL_CapSlot { pub fn slot(&self, index: seL4_Word) -> CDL_CapSlot {
#[allow(unaligned_references)] #[allow(unaligned_references)]

View File

@@ -31,6 +31,7 @@ CONFIG_PRINTING = []
CONFIG_SMP_SUPPORT = [] CONFIG_SMP_SUPPORT = []
CONFIG_VTX = [] CONFIG_VTX = []
# Enable inclusion of noisy logging in various areas # Enable inclusion of noisy logging in various areas
CONFIG_NOISY_UNTYPEDS = []
CONFIG_NOISY_CREATE_OBJECT = [] CONFIG_NOISY_CREATE_OBJECT = []
CONFIG_NOISY_INIT_CNODE = [] CONFIG_NOISY_INIT_CNODE = []
CONFIG_NOISY_INIT_VSPACE = [] CONFIG_NOISY_INIT_VSPACE = []

View File

@@ -5,7 +5,7 @@ use capdl::CDL_FrameFill_BootInfoEnum_t::*;
use capdl::CDL_FrameFillType_t::*; use capdl::CDL_FrameFillType_t::*;
use capdl::CDL_ObjectType::*; use capdl::CDL_ObjectType::*;
use crate::KataOsModel; use crate::KataOsModel;
use log::{debug, info, trace}; use log::{debug, trace};
use smallvec::SmallVec; use smallvec::SmallVec;
use sel4_sys::seL4_ASIDControl_MakePool; use sel4_sys::seL4_ASIDControl_MakePool;
@@ -72,12 +72,9 @@ impl<'a> KataOsModel<'a> {
{ {
let free_slot = self.free_slot_start + free_slot_index; let free_slot = self.free_slot_start + free_slot_index;
// trace!( #[cfg(feature = "CONFIG_NOISY_CREATE_OBJECT")]
// "Creating object {} in slot {} from untyped {:#x}...", trace!("Creating object {} in slot {} from untyped {:#x}...",
// obj.name(), obj.name(), free_slot, self.state.get_untyped_cptr(ut_index));
// free_slot,
// self.state.get_untyped_cptr(ut_index)
// );
// NB: create_object may use free_slot + 1 and free_slot + 2 // NB: create_object may use free_slot + 1 and free_slot + 2
while let Err(e) = while let Err(e) =
@@ -112,18 +109,18 @@ impl<'a> KataOsModel<'a> {
// NB: can instantiate multiple frames but only one // NB: can instantiate multiple frames but only one
// CNode can receive the untypeds since we must move // CNode can receive the untypeds since we must move
// 'em from the rootserver (since they are "derived"). // 'em from the rootserver (since they are "derived").
// XXX maybe just complain & ignore assert!(!is_objid_valid(bootinfo_frame),
trace!("Found bootinfo Frame at {}", obj_id); "Duplicate bootinfo Frame at {}, prev {}",
assert!(!is_objid_valid(bootinfo_frame)); obj_id, bootinfo_frame);
bootinfo_frame = obj_id; bootinfo_frame = obj_id;
} }
} }
// Look for a CNode associated with any bootinfo frame. // Look for a CNode associated with any bootinfo frame.
CDL_CNode => { CDL_CNode => {
if obj.cnode_has_untyped_memory() { if obj.cnode_has_untyped_memory() {
if is_objid_valid(untyped_cnode) { assert!(!is_objid_valid(untyped_cnode),
info!("Duplicate bootinfo cnode at {}, prev {}", obj_id, untyped_cnode); "Duplicate bootinfo cnode at {}, prev {}",
} obj_id, untyped_cnode);
untyped_cnode = obj_id; untyped_cnode = obj_id;
} }
} }
@@ -216,16 +213,18 @@ impl<'a> KataOsModel<'a> {
if !ut.is_device() { if !ut.is_device() {
let index = ut.size_bits(); let index = ut.size_bits();
// trace!("Untyped {:3} (cptr={:#x}) (addr={:#x}) is of size {:2}. Placing in slot {}...", #[cfg(feature = "CONFIG_NOISY_UNTYPEDS")]
// untyped_index, untyped_start + untyped_index, ut.paddr, index, count[index]); trace!("Untyped {:3} (cptr={:#x}) (addr={:#x}) is of size {:2}. Placing in slot {}...",
untyped_index, untyped_start + untyped_index, ut.paddr, index, count[index]);
self.state self.state
.set_untyped_cptr(count[index], untyped_start + untyped_index); .set_untyped_cptr(count[index], untyped_start + untyped_index);
count[index] += 1; count[index] += 1;
num_normal_untypes += 1; num_normal_untypes += 1;
} else { } else {
// trace!("Untyped {:3} (cptr={:#x}) (addr={:#x}) is of size {:2}. Skipping as it is device", #[cfg(feature = "CONFIG_NOISY_UNTYPEDS")]
// untyped_index, untyped_start + untyped_index, ut.paddr, ut.size_bits()); trace!("Untyped {:3} (cptr={:#x}) (addr={:#x}) is of size {:2}. Skipping as it is device",
untyped_index, untyped_start + untyped_index, ut.paddr, ut.size_bits());
} }
} }
num_normal_untypes num_normal_untypes
@@ -292,7 +291,7 @@ impl<'a> KataOsModel<'a> {
obj_size_bits: usize, obj_size_bits: usize,
ut: &seL4_UntypedDesc, ut: &seL4_UntypedDesc,
) -> bool { ) -> bool {
ut.paddr <= obj_addr && obj_addr + obj_size_bits <= ut.paddr + BIT(ut.size_bits()) ut.paddr <= obj_addr && obj_addr + BIT(obj_size_bits) <= ut.paddr + BIT(ut.size_bits())
} }
fn get_address(ut_slot: seL4_CPtr) -> Result<seL4_Page_GetAddress, seL4_Error> { fn get_address(ut_slot: seL4_CPtr) -> Result<seL4_Page_GetAddress, seL4_Error> {
// Create a temporary frame to get the address. We load this at slot + 2 // Create a temporary frame to get the address. We load this at slot + 2
@@ -316,7 +315,7 @@ impl<'a> KataOsModel<'a> {
} }
} }
if is_obj_inside_untyped(paddr, BIT(obj_size_bits), &untypedList[i]) { if is_obj_inside_untyped(paddr, obj_size_bits, &untypedList[i]) {
// See above, loop looking for a Frame in the untyped object // See above, loop looking for a Frame in the untyped object
// that matches our object's address. If we run out of space // that matches our object's address. If we run out of space
// in the untyped the kernel will return seL4_NotEnoughMemory // in the untyped the kernel will return seL4_NotEnoughMemory

View File

@@ -229,7 +229,7 @@ impl<'a> KataOsModel<'a> {
// as part of the work done by init_cspsace. // as part of the work done by init_cspsace.
if is_objid_valid(self.untyped_cnode) { if is_objid_valid(self.untyped_cnode) {
self.handoff_untypeds(self.untyped_cnode)?; self.handoff_untypeds()?;
} }
Ok(()) Ok(())
} }
@@ -885,15 +885,16 @@ impl<'a> KataOsModel<'a> {
Ok(()) Ok(())
} }
fn handoff_untypeds(&mut self, cnode_obj_id: CDL_ObjID) -> seL4_Result { pub fn handoff_untypeds(&mut self) -> seL4_Result {
let num_untypeds = self.bootinfo.untyped.end - self.bootinfo.untyped.start; assert!(is_objid_valid(self.untyped_cnode), "No handoff CNode found");
// NB: UntypedMemory caps are appended to the CAmkES-generated slots // UntypedMemory caps are appended to the CAmkES-generated slots
let dest_start = self.spec.obj_slice()[cnode_obj_id] // in the CNode identified for handoff. CAmkES is assumed to have
.slots_slice() // sized the CNode to handle moving the untyped memory slabs.
.iter() let cnode = self.get_object(self.untyped_cnode);
.max_by_key(|slot| slot.slot) let dest_root = self.get_orig_cap(self.untyped_cnode);
.map_or(0, |slot| slot.slot + 1); let dest_start = cnode.next_free_slot();
let num_untypeds = self.bootinfo.untyped.end - self.bootinfo.untyped.start;
trace!("Hand-off {} untypeds from {} to {}", trace!("Hand-off {} untypeds from {} to {}",
num_untypeds, num_untypeds,
@@ -901,26 +902,27 @@ impl<'a> KataOsModel<'a> {
dest_start); dest_start);
// NB: we let kernel tell us if the CNode is too small. // NB: we let kernel tell us if the CNode is too small.
for ut in 0..num_untypeds { for ut in 0..num_untypeds {
self.handoff_cap(cnode_obj_id, self.handoff_cap(self.untyped_cnode,
/*src_index=*/ self.bootinfo.untyped.start + ut, /*src_index=*/ self.bootinfo.untyped.start + ut,
/*dest_root=*/ dest_root,
/*dest_index=*/ dest_start + ut)?; /*dest_index=*/ dest_start + ut)?;
} }
Ok(()) Ok(())
} }
fn handoff_cap( fn handoff_cap(
&mut self, &self,
cnode_obj_id: CDL_ObjID, cnode_obj_id: CDL_ObjID,
src_index: seL4_CPtr, src_index: seL4_CPtr,
dest_root: seL4_CPtr,
dest_index: seL4_CPtr dest_index: seL4_CPtr
) -> seL4_Result { ) -> seL4_Result {
let cnode = &self.spec.obj_slice()[cnode_obj_id]; let cnode = self.get_object(cnode_obj_id);
assert_eq!(cnode.r#type(), CDL_CNode); assert_eq!(cnode.r#type(), CDL_CNode);
let src_root = seL4_CapInitThreadCNode; let src_root = seL4_CapInitThreadCNode;
let src_depth = seL4_WordBits as u8; let src_depth = seL4_WordBits as u8;
let dest_root = self.get_orig_cap(cnode_obj_id);
let dest_depth: u8 = cnode.size_bits.try_into().unwrap(); let dest_depth: u8 = cnode.size_bits.try_into().unwrap();
unsafe { unsafe {
@@ -991,11 +993,11 @@ impl<'a> KataOsModel<'a> {
CDL_SchedControlCap => (false, self.get_sched_ctrl_cap(target_cap_obj)), CDL_SchedControlCap => (false, self.get_sched_ctrl_cap(target_cap_obj)),
CDL_DomainCap => { CDL_DomainCap => {
// there's only one cap // there's only one cap
(false, seL4_CapDomain as seL4_CPtr) (false, seL4_CapDomain)
} }
CDL_ASIDControlCap => { CDL_ASIDControlCap => {
// there's only one cap // there's only one cap
(false, seL4_CapASIDControl as seL4_CPtr) (false, seL4_CapASIDControl)
} }
_ => (false, self.get_orig_cap(target_cap_obj)), _ => (false, self.get_orig_cap(target_cap_obj)),
}; };
@@ -1004,22 +1006,22 @@ impl<'a> KataOsModel<'a> {
if mode == InitCnodeCmode::MOVE && move_cap { if mode == InitCnodeCmode::MOVE && move_cap {
if is_ep_cap || is_irq_handler_cap { if is_ep_cap || is_irq_handler_cap {
#[cfg(feature = "CONFIG_NOISY_INIT_CNODE")] #[cfg(feature = "CONFIG_NOISY_INIT_CNODE")]
debug!(" Populate {:?} slot {} by moving {}:{}:{} -> {}:{}:{}", debug!(" Populate {:?} slot {} by moving {:?} -> {:?}",
target_cap_type, cnode_slot.slot, target_cap_type, cnode_slot.slot,
src_root, src_index, src_depth, (src_root, src_index, src_depth),
dest_root, dest_index, dest_depth, (dest_root, dest_index, dest_depth),
); );
unsafe { unsafe {
seL4_CNode_Move( seL4_CNode_Move(
dest_root, dest_index, dest_depth, src_root, src_index, src_depth, dest_root, dest_index, dest_depth, src_root, src_index, src_depth,
) )
}? }?;
} else { } else {
#[cfg(feature = "CONFIG_NOISY_INIT_CNODE")] #[cfg(feature = "CONFIG_NOISY_INIT_CNODE")]
debug!(" Populate {:?} slot {} by mutating {}:{}:{} -> {}:{}:{}", debug!(" Populate {:?} slot {} by mutating {:?} -> {:?}",
target_cap_type, cnode_slot.slot, target_cap_type, cnode_slot.slot,
src_root, src_index, src_depth, (src_root, src_index, src_depth),
dest_root, dest_index, dest_depth, (dest_root, dest_index, dest_depth),
); );
unsafe { unsafe {
seL4_CNode_Mutate( seL4_CNode_Mutate(
@@ -1052,10 +1054,10 @@ impl<'a> KataOsModel<'a> {
// NB: the mapped frame cap is stored in the dup table. // NB: the mapped frame cap is stored in the dup table.
let mapped_frame_cap = self.get_dup_cap(frame_cap.obj_id); let mapped_frame_cap = self.get_dup_cap(frame_cap.obj_id);
#[cfg(feature = "CONFIG_NOISY_INIT_CNODE")] #[cfg(feature = "CONFIG_NOISY_INIT_CNODE")]
debug!(" Map {:?} slot {} by moving {}:{}:{} -> {}:{}:{}", debug!(" Map {:?} slot {} by moving {:?} -> {:?}",
target_cap_type, cnode_slot.slot, target_cap_type, cnode_slot.slot,
src_root, mapped_frame_cap, src_depth, (src_root, mapped_frame_cap, src_depth),
dest_root, dest_index, dest_depth, (dest_root, dest_index, dest_depth),
); );
// Move the cap to the frame used for the mapping into the // Move the cap to the frame used for the mapping into the
// destination slot. // destination slot.
@@ -1071,10 +1073,10 @@ impl<'a> KataOsModel<'a> {
}?; }?;
} else { } else {
#[cfg(feature = "CONFIG_NOISY_INIT_CNODE")] #[cfg(feature = "CONFIG_NOISY_INIT_CNODE")]
debug!(" Populate {:?} slot {} by minting {}:{}:{} -> {}:{}:{} {:?} data {:#x}", debug!(" Populate {:?} slot {} by minting {:?} -> {:?} {:?} data {:#x}",
target_cap_type, cnode_slot.slot, target_cap_type, cnode_slot.slot,
src_root, src_index, src_depth, (src_root, src_index, src_depth),
dest_root, dest_index, dest_depth, (dest_root, dest_index, dest_depth),
target_cap_rights, target_cap_data, target_cap_rights, target_cap_data,
); );
unsafe { unsafe {
@@ -1095,13 +1097,10 @@ impl<'a> KataOsModel<'a> {
} }
fn get_object(&self, object_id: CDL_ObjID) -> &'a CDL_Object { fn get_object(&self, object_id: CDL_ObjID) -> &'a CDL_Object {
&(unsafe { core::slice::from_raw_parts(self.spec.objects, self.spec.num) }[object_id]) &self.spec.obj_slice()[object_id]
} }
fn get_asid(&self, asid_num: usize) -> Option<CDL_ObjID> { fn get_asid(&self, asid_num: usize) -> Option<CDL_ObjID> {
Some( Some(self.spec.asid_slot_slice()[asid_num])
unsafe { core::slice::from_raw_parts(self.spec.asid_slots, self.spec.num_asid_slots) }
[asid_num],
)
} }
// Top-level CSpace management: a one-level CSpace impl for now // Top-level CSpace management: a one-level CSpace impl for now
@@ -1146,7 +1145,7 @@ impl<'a> KataOsModel<'a> {
// interrupt notifications and fault endpoints when MCS is enabled. // interrupt notifications and fault endpoints when MCS is enabled.
fn mint_cap( fn mint_cap(
&mut self, &mut self,
object_id: CDL_ObjID, obj_id: CDL_ObjID,
badge: seL4_Word, badge: seL4_Word,
) -> Result<seL4_CPtr, seL4_Error> { ) -> Result<seL4_CPtr, seL4_Error> {
let seL4_AllRights = seL4_CapRights::new( let seL4_AllRights = seL4_CapRights::new(
@@ -1159,7 +1158,7 @@ impl<'a> KataOsModel<'a> {
/*dest_index=*/ free_slot, /*dest_index=*/ free_slot,
/*dest_depth*/ seL4_WordBits as u8, /*dest_depth*/ seL4_WordBits as u8,
/*src_root=*/ seL4_CapInitThreadCNode, /*src_root=*/ seL4_CapInitThreadCNode,
/*src_index=*/ self.get_orig_cap(object_id), /*src_index=*/ self.get_orig_cap(obj_id),
/*src_depth=*/ seL4_WordBits as u8, /*src_depth=*/ seL4_WordBits as u8,
seL4_AllRights, seL4_AllRights,
badge, badge,