From c2accc33b0e2353fa51b795b618efd4a1f5e2fa1 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Fri, 8 Jul 2022 18:17:51 +0000 Subject: [PATCH] MemoryManager: correct initial memory use and add mdebug command - Use seL4_Untyped_Describe to get an accurate view of each UntypedMemory slab being managed; this makes mstats reflect rootserver allocations. - Track memory allocated before we run as "overhead" (was meant to track fragmentation but was always zero). - Add an "mdebug" command to describe each managed memory slab; this is useful to see whether the kernel's view of memory use is consistent with MemoryManager. Change-Id: I53b2738c430ad3356ecd16a1cad29ca92dc74beb GitOrigin-RevId: 2ad43f9b7760c722a6590ea049a3814c8dcccba7 --- .../DebugConsole/kata-shell/src/lib.rs | 13 ++++++ .../kata-memory-component/src/run.rs | 10 +++++ .../kata-memory-interface/src/lib.rs | 11 +++++ .../kata-memory-manager/src/lib.rs | 3 ++ .../src/memory_manager/mod.rs | 44 ++++++++++++++++--- apps/system/interfaces/MemoryInterface.camkes | 2 + 6 files changed, 76 insertions(+), 7 deletions(-) diff --git a/apps/system/components/DebugConsole/kata-shell/src/lib.rs b/apps/system/components/DebugConsole/kata-shell/src/lib.rs index 0476b5f..ee56000 100644 --- a/apps/system/components/DebugConsole/kata-shell/src/lib.rs +++ b/apps/system/components/DebugConsole/kata-shell/src/lib.rs @@ -124,6 +124,7 @@ pub fn repl( ("kvwrite", kvwrite_command as CmdFn), ("install", install_command as CmdFn), ("loglevel", loglevel_command as CmdFn), + ("mdebug", mdebug_command as CmdFn), ("mstats", mstats_command as CmdFn), ("ps", ps_command as CmdFn), ("start", start_command as CmdFn), @@ -462,6 +463,18 @@ fn kvwrite_command( Ok(()) } +fn mdebug_command( + _args: &mut dyn Iterator, + _input: &mut dyn io::BufRead, + output: &mut dyn io::Write, + _builtin_cpio: &[u8], +) -> Result<(), CommandError> { + if let Err(status) = kata_memory_debug() { + writeln!(output, "stats failed: {:?}", status)?; + } + Ok(()) +} + fn mstats(output: &mut dyn io::Write, stats: &MemoryManagerStats) -> Result<(), CommandError> { diff --git a/apps/system/components/MemoryManager/kata-memory-component/src/run.rs b/apps/system/components/MemoryManager/kata-memory-component/src/run.rs index 4753eb0..f3beb46 100644 --- a/apps/system/components/MemoryManager/kata-memory-component/src/run.rs +++ b/apps/system/components/MemoryManager/kata-memory-component/src/run.rs @@ -153,3 +153,13 @@ pub unsafe extern "C" fn memory_stats( Err(e) => e.into(), } } + +#[no_mangle] +pub unsafe extern "C" fn memory_debug() -> MemoryManagerError { + let recv_path = CAMKES.get_current_recv_path(); + // NB: make sure noone clobbers the setup done in memory__init + CAMKES.assert_recv_path(); + Camkes::debug_assert_slot_empty("memory_debug", &recv_path); + + KATA_MEMORY.debug().into() +} diff --git a/apps/system/components/MemoryManager/kata-memory-interface/src/lib.rs b/apps/system/components/MemoryManager/kata-memory-interface/src/lib.rs index 8fd4a97..92a384e 100644 --- a/apps/system/components/MemoryManager/kata-memory-interface/src/lib.rs +++ b/apps/system/components/MemoryManager/kata-memory-interface/src/lib.rs @@ -317,6 +317,7 @@ pub trait MemoryManagerInterface { fn alloc(&mut self, bundle: &ObjDescBundle) -> Result<(), MemoryError>; fn free(&mut self, bundle: &ObjDescBundle) -> Result<(), MemoryError>; fn stats(&self) -> Result; + fn debug(&self) -> Result<(), MemoryError>; } // Public version of MemoryError presented over rpc interface. @@ -692,3 +693,13 @@ pub fn kata_memory_stats() -> Result { status => Err(status), } } + +#[inline] +pub fn kata_memory_debug() -> Result<(), MemoryManagerError> { + extern "C" { + // NB: this assumes the MemoryManager component is named "memory". + fn memory_debug(); + } + unsafe { memory_debug() }; + Ok(()) +} diff --git a/apps/system/components/MemoryManager/kata-memory-manager/src/lib.rs b/apps/system/components/MemoryManager/kata-memory-manager/src/lib.rs index ca6bde1..663bde8 100644 --- a/apps/system/components/MemoryManager/kata-memory-manager/src/lib.rs +++ b/apps/system/components/MemoryManager/kata-memory-manager/src/lib.rs @@ -47,4 +47,7 @@ impl MemoryManagerInterface for KataMemoryManager { fn stats(&self) -> Result { self.manager.lock().as_ref().unwrap().stats() } + fn debug(&self) -> Result<(), MemoryError> { + self.manager.lock().as_ref().unwrap().debug() + } } diff --git a/apps/system/components/MemoryManager/kata-memory-manager/src/memory_manager/mod.rs b/apps/system/components/MemoryManager/kata-memory-manager/src/memory_manager/mod.rs index 59a07fe..bd4e65d 100644 --- a/apps/system/components/MemoryManager/kata-memory-manager/src/memory_manager/mod.rs +++ b/apps/system/components/MemoryManager/kata-memory-manager/src/memory_manager/mod.rs @@ -8,15 +8,21 @@ use kata_memory_interface::MemoryError; use kata_memory_interface::MemoryManagerInterface; use kata_memory_interface::MemoryManagerStats; use kata_os_common::sel4_sys; -use log::{debug, error, warn, trace}; +use log::{debug, error, info, warn, trace}; +use smallvec::SmallVec; + use sel4_sys::seL4_CPtr; use sel4_sys::seL4_CNode_Delete; use sel4_sys::seL4_Error; use sel4_sys::seL4_Result; use sel4_sys::seL4_Word; use sel4_sys::seL4_UntypedDesc; +use sel4_sys::seL4_Untyped_Describe; use sel4_sys::seL4_Untyped_Retype; -use smallvec::SmallVec; + +fn untyped_describe(cptr: seL4_CPtr) -> seL4_Untyped_Describe { + unsafe { seL4_Untyped_Describe(cptr) } +} // SmallVec capacity for untyped memory slabs. There are two instances; // one for anonymous memory and one for device-backed memory. The memory @@ -63,6 +69,7 @@ pub struct MemoryManager { total_bytes: usize, // Total available space allocated_bytes: usize, // Amount of space currently allocated requested_bytes: usize, // Amount of space allocated over all time + overhead_bytes: usize, allocated_objs: usize, // # seL4 objects currently allocated requested_objs: usize, // # seL4 objects allocated over all time @@ -100,6 +107,7 @@ impl MemoryManager { total_bytes: 0, allocated_bytes: 0, requested_bytes: 0, + overhead_bytes: 0, allocated_objs: 0, requested_objs: 0, @@ -114,7 +122,15 @@ impl MemoryManager { m._device_untypeds.push(UntypedSlab::new(ut, slots.start + ut_index)); } else { m.untypeds.push(UntypedSlab::new(ut, slots.start + ut_index)); - m.total_bytes += l2tob(ut.size_bits()); + // NB: must get current state of ut as it will reflect resources + // allocated before we run. + let info = untyped_describe(slots.start + ut_index); + assert_eq!(info.sizeBits, ut.size_bits()); + let size = l2tob(info.sizeBits); + // We only have the remainder available for allocations. + m.total_bytes += info.remainingBytes; + // Use overhead to track memory allocated out of our control. + m.overhead_bytes += size - info.remainingBytes; } } // Sort non-device slabs by descending size. @@ -138,6 +154,10 @@ impl MemoryManager { pub fn total_requested_space(&self) -> usize { self.requested_bytes } + // Current allocated space out of our control. + pub fn overhead_space(&self) -> usize { + self.overhead_bytes + } // Current allocated objects pub fn allocated_objs(&self) -> usize { @@ -254,7 +274,7 @@ impl MemoryManagerInterface for MemoryManager { self.allocated_bytes -= size_bytes; self.allocated_objs -= od.retype_count(); } else { - debug!("Undeflow on free of {:?}", od); + debug!("Underflow on free of {:?}", od); } } } @@ -265,9 +285,7 @@ impl MemoryManagerInterface for MemoryManager { allocated_bytes: self.allocated_space(), free_bytes: self.free_space(), total_requested_bytes: self.total_requested_space(), - // TODO(sleffler): track fragmentation - // NB: assumes all heap usage is for the buddy allocator - overhead_bytes: 0, + overhead_bytes: self.overhead_space(), allocated_objs: self.allocated_objs(), total_requested_objs: self.total_requested_objs(), @@ -276,4 +294,16 @@ impl MemoryManagerInterface for MemoryManager { out_of_memory: self.out_of_memory(), }) } + fn debug(&self) -> Result<(), MemoryError> { + // TODO(sleffler): only shows !device slabs + for ut in &self.untypeds { + let info = untyped_describe(ut.cptr); + let size = l2tob(info.sizeBits); + info!("[{}] allocated {} free {}", ut.cptr, + size - info.remainingBytes, + info.remainingBytes, + ); + } + Ok(()) + } } diff --git a/apps/system/interfaces/MemoryInterface.camkes b/apps/system/interfaces/MemoryInterface.camkes index 9a37cd2..4d72b8f 100644 --- a/apps/system/interfaces/MemoryInterface.camkes +++ b/apps/system/interfaces/MemoryInterface.camkes @@ -4,4 +4,6 @@ procedure MemoryInterface { MemoryManagerError alloc(in char request[]); MemoryManagerError free(in char request[]); MemoryManagerError stats(out RawMemoryStatsData data); + + void debug(); };