Add capscan suport.

Add support to output the contents of the top-level CNode of a CAmkES
service or KataOS application to the serial console. This is dependent
on kernel support that is enabled with CONFIG_PRINTING. Applications
must be running; otherwise there is no CSpace to dump.

Specific changes:
- add a "capscan" shell command
- add capscan method to each CAmkES interface
- add capscan_bundle method to the ProcessControlInterface
- add Camkes::capscan() to dump the top-level CNode
- add ProcessManager support to dump the CNode for a bundle

TODO: fix syscall wrapper error return

Change-Id: If6ca222decdb4c40a1d3a63e69792eb3feb30f6a
GitOrigin-RevId: 504c0182ccccf287b5d58cd8e33981c11d7539d7
This commit is contained in:
Sam Leffler 2022-07-09 18:48:45 +00:00
parent c2accc33b0
commit 05233af12c
32 changed files with 323 additions and 6 deletions

View File

@ -19,6 +19,7 @@ default = [
"TEST_TIMER_SERVICE", "TEST_TIMER_SERVICE",
] ]
CONFIG_DEBUG_BUILD = [] CONFIG_DEBUG_BUILD = []
CONFIG_PRINTING = []
CONFIG_KERNEL_MCS = [] CONFIG_KERNEL_MCS = []
# Commands that are likely not useful # Commands that are likely not useful
FRINGE_CMDS = [] FRINGE_CMDS = []

View File

@ -119,6 +119,7 @@ pub fn repl<T: io::BufRead>(
cmds.extend([ cmds.extend([
("builtins", builtins_command as CmdFn), ("builtins", builtins_command as CmdFn),
("bundles", bundles_command as CmdFn), ("bundles", bundles_command as CmdFn),
("capscan", capscan_command as CmdFn),
("kvdelete", kvdelete_command as CmdFn), ("kvdelete", kvdelete_command as CmdFn),
("kvread", kvread_command as CmdFn), ("kvread", kvread_command as CmdFn),
("kvwrite", kvwrite_command as CmdFn), ("kvwrite", kvwrite_command as CmdFn),
@ -231,12 +232,12 @@ fn ps_command(
) -> Result<(), CommandError> { ) -> Result<(), CommandError> {
#[cfg(feature = "CONFIG_DEBUG_BUILD")] #[cfg(feature = "CONFIG_DEBUG_BUILD")]
unsafe { unsafe {
kata_os_common::sel4_sys::seL4_DebugDumpScheduler(); sel4_sys::seL4_DebugDumpScheduler();
Ok(()) Ok(())
} }
#[cfg(not(feature = "CONFIG_DEBUG_BUILD"))] #[cfg(not(feature = "CONFIG_DEBUG_BUILD"))]
Ok(writeln!(output, "Kernel support not configured!")?) Ok(writeln!(output, "Kernel support not configured with CONFIG_DEBUG_BUILD!")?)
} }
fn bundles_command( fn bundles_command(
@ -258,6 +259,47 @@ fn bundles_command(
Ok(()) Ok(())
} }
/// Implements a "capscan" command that dumps seL4 capabilities to the console.
#[allow(unused_variables)]
fn capscan_command(
args: &mut dyn Iterator<Item = &str>,
_input: &mut dyn io::BufRead,
output: &mut dyn io::Write,
_builtin_cpio: &[u8],
) -> Result<(), CommandError> {
#[cfg(feature = "CONFIG_PRINTING")]
match args.next() {
Some("console") => unsafe { sel4_sys::seL4_DebugDumpCNode(SELF_CNODE); }
Some("memory") => { let _ = kata_memory_interface::kata_memory_capscan(); }
Some("process") => { let _ = kata_proc_interface::kata_proc_ctrl_capscan(); }
Some("mlcoord") => { let _ = kata_mlcoord_capscan(); }
Some("security") => { let _ = kata_security_interface::kata_security_capscan(); }
Some("storage") => { let _ = kata_storage_interface::kata_storage_capscan(); }
Some("timer") => { let _ = kata_timer_interface::timer_service_capscan(); }
Some(bundle_id) => {
if let Err(e) = kata_proc_interface::kata_proc_ctrl_capscan_bundle(bundle_id) {
writeln!(output, "{}: {:?}", bundle_id, e)?;
}
}
None => {
writeln!(output, "capscan <target>, where <target> is one of:")?;
writeln!(output, " console (DebugConsole)")?;
writeln!(output, " memory (MemoryManager)")?;
writeln!(output, " process (ProcessManager)")?;
writeln!(output, " mlcoord (MlCoordinator)")?;
writeln!(output, " securiy (SecurityCoordinator)")?;
writeln!(output, " storage (StorageManager)")?;
writeln!(output, " timer (TimerService)")?;
writeln!(output, "anything else is treated as a bundle_id")?;
}
}
#[cfg(not(feature = "CONFIG_PRINTING"))]
writeln!(output, "Kernel not configured with CONFIG_PRINTING!")?;
Ok(())
}
fn collect_from_cpio( fn collect_from_cpio(
filename: &str, filename: &str,
cpio: &[u8], cpio: &[u8],

View File

@ -163,3 +163,13 @@ pub unsafe extern "C" fn memory_debug() -> MemoryManagerError {
KATA_MEMORY.debug().into() KATA_MEMORY.debug().into()
} }
#[no_mangle]
pub unsafe extern "C" fn memory_capscan() {
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);
let _ = Camkes::capscan();
}

View File

@ -703,3 +703,13 @@ pub fn kata_memory_debug() -> Result<(), MemoryManagerError> {
unsafe { memory_debug() }; unsafe { memory_debug() };
Ok(()) Ok(())
} }
#[inline]
pub fn kata_memory_capscan() -> Result<(), MemoryManagerError> {
extern "C" {
// NB: this assumes the MemoryManager component is named "memory".
fn memory_capscan();
}
unsafe { memory_capscan() };
Ok(())
}

View File

@ -132,3 +132,8 @@ pub unsafe extern "C" fn data_fault_handle() {
pub unsafe extern "C" fn mlcoord_debug_state() { pub unsafe extern "C" fn mlcoord_debug_state() {
ML_COORD.lock().debug_state(); ML_COORD.lock().debug_state();
} }
#[no_mangle]
pub unsafe extern "C" fn mlcoord_capscan() {
let _ = Camkes::capscan();
}

View File

@ -79,3 +79,12 @@ pub fn kata_mlcoord_debug_state() {
} }
unsafe { mlcoord_debug_state() }; unsafe { mlcoord_debug_state() };
} }
#[inline]
pub fn kata_mlcoord_capscan() -> Result<(), MlCoordError> {
extern "C" {
fn mlcoord_capscan();
}
unsafe { mlcoord_capscan() };
Ok(())
}

View File

@ -138,3 +138,21 @@ pub unsafe extern "C" fn proc_ctrl_get_running_bundles(
Err(e) => e, Err(e) => e,
} }
} }
#[no_mangle]
pub unsafe extern "C" fn proc_ctrl_capscan() {
let _ = Camkes::capscan();
}
#[no_mangle]
pub unsafe extern "C" fn proc_ctrl_capscan_bundle(
c_bundle_id: *const cstr_core::c_char
) -> ProcessManagerError {
match CStr::from_ptr(c_bundle_id).to_str() {
Ok(str) => match KATA_PROC.capscan(str) {
Ok(_) => ProcessManagerError::Success,
Err(e) => e,
},
Err(_) => ProcessManagerError::BundleIdInvalid,
}
}

View File

@ -57,6 +57,7 @@ pub trait BundleImplInterface {
fn stop(&mut self) -> Result<(), ProcessManagerError>; fn stop(&mut self) -> Result<(), ProcessManagerError>;
fn suspend(&self) -> Result<(), ProcessManagerError>; fn suspend(&self) -> Result<(), ProcessManagerError>;
fn resume(&self) -> Result<(), ProcessManagerError>; fn resume(&self) -> Result<(), ProcessManagerError>;
fn capscan(&self) -> Result<(), ProcessManagerError>;
} }
// NB: struct's marked repr(C) are processed by cbindgen to get a .h file // NB: struct's marked repr(C) are processed by cbindgen to get a .h file
@ -71,6 +72,7 @@ pub enum ProcessManagerError {
BundleNotFound, BundleNotFound,
BundleFound, BundleFound,
BundleRunning, BundleRunning,
BundleNotRunning,
UnknownError, UnknownError,
DeserializeError, DeserializeError,
SerializeError, SerializeError,
@ -83,6 +85,7 @@ pub enum ProcessManagerError {
// TODO(sleffler): for use if/when ProcessManagerInterface grows // TODO(sleffler): for use if/when ProcessManagerInterface grows
SuspendFailed, SuspendFailed,
ResumeFailed, ResumeFailed,
CapScanFailed,
} }
// Interface to underlying facilities (StorageManager, seL4); also // Interface to underlying facilities (StorageManager, seL4); also
@ -95,6 +98,7 @@ pub trait ProcessManagerInterface {
fn uninstall(&mut self, bundle_id: &str) -> Result<(), ProcessManagerError>; fn uninstall(&mut self, bundle_id: &str) -> Result<(), ProcessManagerError>;
fn start(&mut self, bundle: &Bundle) -> Result<Box<dyn BundleImplInterface>, ProcessManagerError>; fn start(&mut self, bundle: &Bundle) -> Result<Box<dyn BundleImplInterface>, ProcessManagerError>;
fn stop(&mut self, bundle_impl: &mut dyn BundleImplInterface) -> Result<(), ProcessManagerError>; fn stop(&mut self, bundle_impl: &mut dyn BundleImplInterface) -> Result<(), ProcessManagerError>;
fn capscan(&self, bundle_impl: &dyn BundleImplInterface) -> Result<(), ProcessManagerError>;
} }
// NB: bundle_id comes across the C interface as *const cstr_core::c_char // NB: bundle_id comes across the C interface as *const cstr_core::c_char
@ -112,6 +116,7 @@ pub trait ProcessControlInterface {
fn start(&mut self, bundle_id: &str) -> Result<(), ProcessManagerError>; fn start(&mut self, bundle_id: &str) -> Result<(), ProcessManagerError>;
fn stop(&mut self, bundle_id: &str) -> Result<(), ProcessManagerError>; fn stop(&mut self, bundle_id: &str) -> Result<(), ProcessManagerError>;
fn get_running_bundles(&self) -> Result<BundleIdArray, ProcessManagerError>; fn get_running_bundles(&self) -> Result<BundleIdArray, ProcessManagerError>;
fn capscan(&self, bundle_id: &str) -> Result<(), ProcessManagerError>;
} }
impl From<postcard::Error> for ProcessManagerError { impl From<postcard::Error> for ProcessManagerError {
@ -231,6 +236,26 @@ pub fn kata_proc_ctrl_stop(bundle_id: &str) -> Result<(), ProcessManagerError> {
unsafe { proc_ctrl_stop(cstr.as_ptr()) }.into() unsafe { proc_ctrl_stop(cstr.as_ptr()) }.into()
} }
#[inline]
#[allow(dead_code)]
pub fn kata_proc_ctrl_capscan() -> Result<(), ProcessManagerError> {
extern "C" {
fn proc_ctrl_capscan();
}
unsafe { proc_ctrl_capscan() }
Ok(())
}
#[inline]
#[allow(dead_code)]
pub fn kata_proc_ctrl_capscan_bundle(bundle_id: &str) -> Result<(), ProcessManagerError> {
extern "C" {
fn proc_ctrl_capscan_bundle(c_bundle_id: *const cstr_core::c_char) -> ProcessManagerError;
}
let cstr = CString::new(bundle_id)?;
unsafe { proc_ctrl_capscan_bundle(cstr.as_ptr()) }.into()
}
// TODO(sleffler): move out of interface? // TODO(sleffler): move out of interface?
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -13,6 +13,7 @@ default = []
CONFIG_CAPDL_LOADER_CC_REGISTERS = [] CONFIG_CAPDL_LOADER_CC_REGISTERS = []
CONFIG_CAPDL_LOADER_WRITEABLE_PAGES = [] CONFIG_CAPDL_LOADER_WRITEABLE_PAGES = []
CONFIG_DEBUG_BUILD = [] CONFIG_DEBUG_BUILD = []
CONFIG_PRINTING = []
CONFIG_KERNEL_MCS = [] CONFIG_KERNEL_MCS = []
CONFIG_SMP_SUPPORT = [] CONFIG_SMP_SUPPORT = []

View File

@ -84,6 +84,9 @@ impl ProcessControlInterface for KataProcManager {
fn get_running_bundles(&self) -> Result<BundleIdArray, ProcessManagerError> { fn get_running_bundles(&self) -> Result<BundleIdArray, ProcessManagerError> {
self.manager.lock().as_ref().unwrap().get_running_bundles() self.manager.lock().as_ref().unwrap().get_running_bundles()
} }
fn capscan(&self, bundle_id: &str) -> Result<(), ProcessManagerError> {
self.manager.lock().as_ref().unwrap().capscan(bundle_id)
}
} }
struct KataManagerInterface; struct KataManagerInterface;
@ -161,4 +164,9 @@ impl ProcessManagerInterface for KataManagerInterface {
// TODO(sleffler): fill-in 1+2 // TODO(sleffler): fill-in 1+2
bundle_impl.stop() bundle_impl.stop()
} }
fn capscan(&self, bundle_impl: &dyn BundleImplInterface) -> Result<(), ProcessManagerError> {
trace!("ProcessManagerInterface::capscan");
bundle_impl.capscan()
}
} }

View File

@ -167,6 +167,21 @@ impl ProcessControlInterface for ProcessManager {
} }
Ok(result) Ok(result)
} }
fn capscan(&self, bundle_id: &str) -> Result<(), ProcessManagerError> {
trace!("capscan bundle_id {}", bundle_id);
let bid = BundleId::from_str(bundle_id);
if let Some(bundle) = self.bundles.get(&bid) {
trace!("capscan state {:?}", bundle.state);
if bundle.state != BundleState::Running {
return Err(ProcessManagerError::BundleNotRunning)
}
self.manager.capscan(bundle.bundle_impl.as_deref().unwrap())
} else {
trace!("capscan {} not found", bundle_id);
Err(ProcessManagerError::BundleNotFound)
}
}
} }
#[cfg(test)] #[cfg(test)]
@ -192,6 +207,7 @@ mod tests {
fn stop(&mut self) -> Result<(), ProcessManagerError> { Ok(()) } fn stop(&mut self) -> Result<(), ProcessManagerError> { Ok(()) }
fn resume(&self) -> Result<(), ProcessManagerError> { Ok(()) } fn resume(&self) -> Result<(), ProcessManagerError> { Ok(()) }
fn suspend(&self) -> Result<(), ProcessManagerError> { Ok(()) } fn suspend(&self) -> Result<(), ProcessManagerError> { Ok(()) }
fn capscan(&self) -> Result<(), ProcessManagerError> { Ok(()) }
} }
impl ProcessManagerInterface for FakeManager { impl ProcessManagerInterface for FakeManager {
fn install(&mut self, pkg_buffer: *const u8, pkg_buffer_size: u32) -> Result<String, pme> { fn install(&mut self, pkg_buffer: *const u8, pkg_buffer_size: u32) -> Result<String, pme> {
@ -215,6 +231,9 @@ mod tests {
fn stop(&mut self, bundle_impl: &mut dyn BundleImplInterface) -> Result<(), pme> { fn stop(&mut self, bundle_impl: &mut dyn BundleImplInterface) -> Result<(), pme> {
Ok(()) Ok(())
} }
fn capscan(&mut self, bundle_impl: &mut dyn BundleImplInterface) -> Result<(), pme> {
Ok(())
}
} }
#[test] #[test]

View File

@ -608,4 +608,9 @@ impl BundleImplInterface for seL4BundleImpl {
unsafe { seL4_TCB_Suspend(self.cap_tcb.slot) } unsafe { seL4_TCB_Suspend(self.cap_tcb.slot) }
.map_err(|_| ProcessManagerError::SuspendFailed) .map_err(|_| ProcessManagerError::SuspendFailed)
} }
fn capscan(&self) -> Result<(), ProcessManagerError> {
#[cfg(feature = "CONFIG_PRINTING")]
unsafe { sel4_sys::seL4_DebugDumpCNode(self.cspace_root.objs[0].cptr); }
Ok(())
}
} }

View File

@ -239,6 +239,11 @@ fn test_mailbox_request(
unsafe { KATA_SECURITY.test_mailbox() } unsafe { KATA_SECURITY.test_mailbox() }
} }
fn capscan_request() -> Result<(), SecurityRequestError> {
let _ = Camkes::capscan();
Ok(())
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn security_request( pub unsafe extern "C" fn security_request(
c_request: SecurityRequest, c_request: SecurityRequest,
@ -272,5 +277,7 @@ pub unsafe extern "C" fn security_request(
delete_key_request(request_buffer, reply_buffer), delete_key_request(request_buffer, reply_buffer),
SecurityRequest::SrTestMailbox => SecurityRequest::SrTestMailbox =>
test_mailbox_request(), test_mailbox_request(),
SecurityRequest::SrCapScan =>
capscan_request(),
}.map_or_else(|e| e, |_v| SecurityRequestError::SreSuccess) }.map_or_else(|e| e, |_v| SecurityRequestError::SreSuccess)
} }

View File

@ -168,10 +168,14 @@ impl<'a> SecurityCapability for DeleteKeyRequest<'a> {}
// SecurityRequestTestMailbox // SecurityRequestTestMailbox
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct TestMailboxRequest { pub struct TestMailboxRequest {}
}
impl SecurityCapability for TestMailboxRequest {} impl SecurityCapability for TestMailboxRequest {}
// SecurityRequestCapScan
#[derive(Debug, Serialize, Deserialize)]
pub struct CapScanRequest {}
impl SecurityCapability for CapScanRequest {}
// NB: this is the union of InstallInterface & StorageInterface because // NB: this is the union of InstallInterface & StorageInterface because
// the camkes-generated interface code uses basic C which does not // the camkes-generated interface code uses basic C which does not
// tolerate overlapping member names. // tolerate overlapping member names.
@ -241,6 +245,7 @@ pub enum SecurityRequest {
SrDeleteKey, // Delete key [bundle_id, key] SrDeleteKey, // Delete key [bundle_id, key]
SrTestMailbox, // Run mailbox tests SrTestMailbox, // Run mailbox tests
SrCapScan, // Dump contents CNode to console
} }
// Interface to underlying facilities; also used to inject fakes for unit tests. // Interface to underlying facilities; also used to inject fakes for unit tests.
@ -489,3 +494,13 @@ pub fn kata_security_test_mailbox() -> Result<(), SecurityRequestError> {
&mut [0u8; SECURITY_REPLY_DATA_SIZE], &mut [0u8; SECURITY_REPLY_DATA_SIZE],
) )
} }
#[inline]
#[allow(dead_code)]
pub fn kata_security_capscan() -> Result<(), SecurityRequestError> {
kata_security_request(
SecurityRequest::SrCapScan,
&CapScanRequest {},
&mut [0u8; SECURITY_REPLY_DATA_SIZE],
)
}

View File

@ -75,3 +75,8 @@ pub unsafe extern "C" fn storage_delete(
Err(_) => StorageManagerError::SmeKeyInvalid, Err(_) => StorageManagerError::SmeKeyInvalid,
} }
} }
#[no_mangle]
pub unsafe extern "C" fn storage_capscan() {
let _ = Camkes::capscan();
}

View File

@ -139,3 +139,13 @@ pub fn kata_storage_write(key: &str, value: &[u8]) -> Result<(), StorageManagerE
let cstr = CString::new(key)?; let cstr = CString::new(key)?;
unsafe { storage_write(cstr.as_ptr(), value.len(), value.as_ptr()) }.into() unsafe { storage_write(cstr.as_ptr(), value.len(), value.as_ptr()) }.into()
} }
#[inline]
#[allow(dead_code)]
pub fn kata_storage_capscan() -> Result<(), StorageManagerError> {
extern "C" {
fn storage_capscan();
}
unsafe { storage_capscan() }
Ok(())
}

View File

@ -87,3 +87,8 @@ pub unsafe extern "C" fn timer_interrupt_handle() {
TIMER_SRV.lock().service_interrupt(); TIMER_SRV.lock().service_interrupt();
assert!(timer_interrupt_acknowledge() == 0); assert!(timer_interrupt_acknowledge() == 0);
} }
#[no_mangle]
pub unsafe extern "C" fn timer_capscan() {
let _ = Camkes::capscan();
}

View File

@ -81,3 +81,13 @@ pub fn timer_service_wait() -> seL4_Word {
notification_badge notification_badge
} }
#[inline]
#[allow(dead_code)]
pub fn timer_service_capscan() -> Result<(), TimerServiceError> {
extern "C" {
fn timer_capscan();
}
unsafe { timer_capscan() }
Ok(())
}

View File

@ -2,6 +2,13 @@
name = "camkes" name = "camkes"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
build = "build.rs"
[build-dependencies]
sel4-config = { path = "../sel4-config" }
[features]
CONFIG_PRINTING = []
[dependencies] [dependencies]
log = "0.4" log = "0.4"

View File

@ -0,0 +1,21 @@
extern crate sel4_config;
use std::env;
fn main() {
// If SEL4_OUT_DIR is not set we expect the kernel build at a fixed
// location relative to the ROOTDIR env variable.
println!("SEL4_OUT_DIR {:?}", env::var("SEL4_OUT_DIR"));
let sel4_out_dir = env::var("SEL4_OUT_DIR").unwrap_or_else(
|_| format!("{}/out/kata/kernel", env::var("ROOTDIR").unwrap())
);
println!("sel4_out_dir {}", sel4_out_dir);
// Dredge seL4 kernel config for settings we need as features to generate
// correct code: e.g. CONFIG_KERNEL_MCS enables MCS support which changes
// the system call numbering.
let features = sel4_config::get_sel4_features(&sel4_out_dir);
println!("features={:?}", features);
for feature in features {
println!("cargo:rustc-cfg=feature=\"{}\"", feature);
}
}

View File

@ -12,6 +12,7 @@ use sel4_sys;
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_GetCapReceivePath;
use sel4_sys::seL4_Result;
use sel4_sys::seL4_SetCap; use sel4_sys::seL4_SetCap;
use sel4_sys::seL4_SetCapReceivePath; use sel4_sys::seL4_SetCapReceivePath;
use sel4_sys::seL4_Word; use sel4_sys::seL4_Word;
@ -173,4 +174,13 @@ impl Camkes {
"{}: expected cnode in slot {:?} but found cap type {:?}", "{}: expected cnode in slot {:?} but found cap type {:?}",
tag, path, sel4_sys::cap_identify(path.1)); tag, path, sel4_sys::cap_identify(path.1));
} }
// Dumps the contents of the toplevel CNode to the serial console.
pub fn capscan() -> seL4_Result {
// TODO(sleffler): requires CONFIG_PRINTING in the kernel
#[cfg(feature = "CONFIG_PRINTING")]
unsafe { sel4_sys::seL4_DebugDumpCNode(SELF_CNODE); }
// XXX until seL4_Error is correctly returned
Ok(())
}
} }

View File

@ -990,6 +990,16 @@ pub unsafe fn seL4_DebugCapIdentify(mut cap: seL4_CPtr) -> u32 {
cap as _ cap as _
} }
#[cfg(feature = "CONFIG_PRINTING")]
#[inline(always)]
pub unsafe fn seL4_DebugDumpCNode(mut cap: seL4_CPtr) {
asm!("swi 0",
in("r7") swinum!(SyscallId::DebugDumpCNode),
inout("r0") cap,
options(nomem, nostack),
);
}
// Note: name MUST be NUL-terminated. // Note: name MUST be NUL-terminated.
#[cfg(feature = "CONFIG_DEBUG_BUILD")] #[cfg(feature = "CONFIG_DEBUG_BUILD")]
#[inline(always)] #[inline(always)]

View File

@ -986,6 +986,16 @@ pub unsafe fn seL4_DebugCapIdentify(mut cap: seL4_CPtr) -> u32 {
cap as _ cap as _
} }
#[cfg(feature = "CONFIG_PRINTING")]
#[inline(always)]
pub unsafe fn seL4_DebugDumpCNode(mut cap: seL4_CPtr) {
asm!("svc 0",
in("x7") swinum!(SyscallId::DebugDumpCNode),
inout("x0") cap,
options(nomem, nostack),
);
}
// Note: name MUST be NUL-terminated. // Note: name MUST be NUL-terminated.
#[cfg(feature = "CONFIG_DEBUG_BUILD")] #[cfg(feature = "CONFIG_DEBUG_BUILD")]
#[inline(always)] #[inline(always)]

View File

@ -945,6 +945,16 @@ pub unsafe fn seL4_DebugCapIdentify(mut cap: seL4_CPtr) -> u32 {
cap as _ cap as _
} }
#[cfg(feature = "CONFIG_PRINTING")]
#[inline(always)]
pub unsafe fn seL4_DebugDumpCNode(mut cap: seL4_CPtr) {
asm!("ecall",
in("a7") swinum!(SyscallId::DebugDumpCNode),
inout("a0") cap,
options(nomem, nostack),
);
}
// Note: name MUST be NUL-terminated. // Note: name MUST be NUL-terminated.
#[cfg(feature = "CONFIG_DEBUG_BUILD")] #[cfg(feature = "CONFIG_DEBUG_BUILD")]
#[inline(always)] #[inline(always)]

View File

@ -952,6 +952,16 @@ pub unsafe fn seL4_DebugCapIdentify(mut cap: seL4_CPtr) -> u32 {
cap as _ cap as _
} }
#[cfg(feature = "CONFIG_PRINTING")]
#[inline(always)]
pub unsafe fn seL4_DebugDumpCNode(mut cap: seL4_CPtr) {
asm!("ecall",
in("a7") swinum!(SyscallId::DebugDumpCNode),
inout("a0") cap,
options(nomem, nostack),
);
}
// Note: name MUST be NUL-terminated. // Note: name MUST be NUL-terminated.
#[cfg(feature = "CONFIG_DEBUG_BUILD")] #[cfg(feature = "CONFIG_DEBUG_BUILD")]
#[inline(always)] #[inline(always)]

View File

@ -579,11 +579,21 @@ pub unsafe fn seL4_DebugCapIdentify(mut cap: seL4_CPtr) -> u32 {
let mut unused0 = 0; let mut unused0 = 0;
let mut unused1 = 0; let mut unused1 = 0;
let mut unused2 = 0; let mut unused2 = 0;
x86_sys_send_recv(SyscallId::DebugCapIdentify as seL4_Word, x86_sys_send_recv(SyscallId::DebugCapIdentify as seL4_Word,
cap, &mut cap, 0, &mut unused0, &mut unused1, &mut unused2); cap, &mut cap, 0, &mut unused0, &mut unused1, &mut unused2);
cap as _ cap as _
} }
#[cfg(feature = "CONFIG_PRINTING")]
#[inline(always)]
pub unsafe fn seL4_DebugDumpCNode(mut cap: seL4_CPtr) {
let mut unused0 = 0;
let mut unused1 = 0;
let mut unused2 = 0;
x86_sys_send_recv(SyscallId::DebugDumpCNode as seL4_Word,
cap, &mut cap, 0, &mut unused0, &mut unused1, &mut unused2);
}
/// Note: name MUST be NUL-terminated. /// Note: name MUST be NUL-terminated.
#[inline(always)] #[inline(always)]
pub unsafe fn seL4_DebugNameThread(tcb: seL4_CPtr, name: &[u8]) { pub unsafe fn seL4_DebugNameThread(tcb: seL4_CPtr, name: &[u8]) {
@ -631,7 +641,7 @@ pub unsafe fn seL4_BenchmarkSetLogBuffer(mut frame_cptr: seL4_Word) -> seL4_Word
let mut unused0 = 0; let mut unused0 = 0;
let mut unused1 = 0; let mut unused1 = 0;
let mut unused2 = 0; let mut unused2 = 0;
x86_sys_send_recv(SyscallId::BenchmarkSetLogBuffer as seL4_Word, x86_sys_send_recv(SyscallId::BenchmarkSetLogBuffer as seL4_Word,
frame_cptr, &mut cap, 0, &mut unused0 as *mut _ as usize as seL4_Word, &mut unused1 as *mut _ as usize as seL4_Word, &mut unused2 as *mut _ as usize as seL4_Word); frame_cptr, &mut cap, 0, &mut unused0 as *mut _ as usize as seL4_Word, &mut unused1 as *mut _ as usize as seL4_Word, &mut unused2 as *mut _ as usize as seL4_Word);
frame_cptr frame_cptr
} }

View File

@ -1123,6 +1123,21 @@ pub unsafe fn seL4_DebugCapIdentify(mut cap: seL4_CPtr) -> u32 {
cap as _ cap as _
} }
#[cfg(feature = "CONFIG_PRINTING")]
#[inline(always)]
pub unsafe fn seL4_DebugDumpCNode(mut cap: seL4_CPtr) {
asm!("mov r14, rsp
syscall
mov rsp, r14",
in("rdx") swinum!(SyscallId::DebugDumpCNode),
inout("rdi") cap,
lateout("rcx") _,
lateout("r11") _,
lateout("r14") _,
options(nomem, nostack),
);
}
// Note: name MUST be NUL-terminated. // Note: name MUST be NUL-terminated.
#[cfg(feature = "CONFIG_DEBUG_BUILD")] #[cfg(feature = "CONFIG_DEBUG_BUILD")]
#[inline(always)] #[inline(always)]

View File

@ -5,5 +5,6 @@ procedure MemoryInterface {
MemoryManagerError free(in char request[]); MemoryManagerError free(in char request[]);
MemoryManagerError stats(out RawMemoryStatsData data); MemoryManagerError stats(out RawMemoryStatsData data);
void capscan();
void debug(); void debug();
}; };

View File

@ -6,4 +6,5 @@ procedure MlCoordinatorInterface {
MlCoordError cancel(in string bundle_id, in string model_id); MlCoordError cancel(in string bundle_id, in string model_id);
void debug_state(); void debug_state();
void capscan();
}; };

View File

@ -4,4 +4,7 @@ procedure ProcessControlInterface {
ProcessManagerError start(in string bundleId); ProcessManagerError start(in string bundleId);
ProcessManagerError stop(in string bundleId); ProcessManagerError stop(in string bundleId);
ProcessManagerError get_running_bundles(out RawBundleIdData raw_data); ProcessManagerError get_running_bundles(out RawBundleIdData raw_data);
void capscan();
ProcessManagerError capscan_bundle(in string bundleId);
}; };

View File

@ -4,4 +4,6 @@ procedure StorageInterface {
StorageManagerError read(in string key, out KeyValueData value); StorageManagerError read(in string key, out KeyValueData value);
StorageManagerError write(in string key, in char value[]); StorageManagerError write(in string key, in char value[]);
StorageManagerError delete(in string key); StorageManagerError delete(in string key);
void capscan();
}; };

View File

@ -8,4 +8,6 @@ procedure Timer {
TimerServiceError oneshot(uint32_t timer_id, uint32_t duration_in_ms); TimerServiceError oneshot(uint32_t timer_id, uint32_t duration_in_ms);
TimerServiceError periodic(uint32_t timer_id, uint32_t duration_in_ms); TimerServiceError periodic(uint32_t timer_id, uint32_t duration_in_ms);
TimerServiceError cancel(uint32_t timer_id); TimerServiceError cancel(uint32_t timer_id);
void capscan();
}; };