feat(kernel): shared ABI decoder+proofs, no-panic gate, syscall storm, kani on shrunk kernel
This commit is contained in:
@@ -1,5 +1,20 @@
|
||||
#![no_std]
|
||||
// A kernel panic takes the whole system down, so kernel code may not
|
||||
// contain any way to panic. Tests and proofs are exempt.
|
||||
#![cfg_attr(
|
||||
not(any(test, kani)),
|
||||
deny(
|
||||
clippy::unwrap_used,
|
||||
clippy::expect_used,
|
||||
clippy::panic,
|
||||
clippy::unreachable,
|
||||
clippy::todo,
|
||||
clippy::unimplemented,
|
||||
clippy::indexing_slicing
|
||||
)
|
||||
)]
|
||||
|
||||
pub mod abi;
|
||||
mod captree;
|
||||
pub mod interrupt;
|
||||
mod memory;
|
||||
@@ -136,11 +151,11 @@ impl<P: Platform> Kernel<P> {
|
||||
}
|
||||
|
||||
pub fn pending_result(&self, thread: ThreadId) -> Option<&SyscallResult> {
|
||||
self.pending_results[thread.raw() as usize].as_ref()
|
||||
self.pending_results.get(thread.raw() as usize)?.as_ref()
|
||||
}
|
||||
|
||||
pub fn take_pending_result(&mut self, thread: ThreadId) -> Option<SyscallResult> {
|
||||
self.pending_results[thread.raw() as usize].take()
|
||||
self.pending_results.get_mut(thread.raw() as usize)?.take()
|
||||
}
|
||||
|
||||
pub fn set_thread_running(
|
||||
@@ -268,10 +283,8 @@ impl<P: Platform> Kernel<P> {
|
||||
{
|
||||
Ok(p) => {
|
||||
let mut ids = [None; MAX_THREADS_PER_PROCESS];
|
||||
for (i, tid) in p.thread_ids().enumerate() {
|
||||
if i < MAX_THREADS_PER_PROCESS {
|
||||
ids[i] = Some(tid);
|
||||
}
|
||||
for (slot, tid) in ids.iter_mut().zip(p.thread_ids()) {
|
||||
*slot = Some(tid);
|
||||
}
|
||||
ids
|
||||
}
|
||||
@@ -292,19 +305,19 @@ impl<P: Platform> Kernel<P> {
|
||||
for tid in thread_ids.iter().flatten() {
|
||||
self.endpoints.remove_thread_from_all(*tid);
|
||||
self.notifications.remove_thread_from_all(*tid);
|
||||
let ipc = core::mem::take(&mut self.ipc[tid.raw() as usize]);
|
||||
let ipc = self.ipc_mut(*tid).map(core::mem::take).unwrap_or_default();
|
||||
if let Some(caller) = ipc.reply_to {
|
||||
self.release_caller(caller);
|
||||
}
|
||||
self.scheduler.remove(*tid);
|
||||
self.pending_results[tid.raw() as usize] = None;
|
||||
self.set_pending_result(*tid, None);
|
||||
let _ = self.threads.destroy(*tid);
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys every endpoint `owner` created, waking anyone blocked on
|
||||
/// them with an error instead of leaving them blocked forever.
|
||||
fn destroy_endpoints_owned_by(&mut self, owner: ProcessId) {
|
||||
pub(crate) fn destroy_endpoints_owned_by(&mut self, owner: ProcessId) {
|
||||
let mut owned = [None; domain::endpoint::MAX_ENDPOINTS];
|
||||
for (slot, id) in owned.iter_mut().zip(self.endpoints.ids_owned_by(owner)) {
|
||||
*slot = Some(id);
|
||||
@@ -330,8 +343,10 @@ impl<P: Platform> Kernel<P> {
|
||||
let Some(mut n) = self.notifications.destroy(id) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(bound) = n.bound() {
|
||||
self.ipc[bound.raw() as usize].bound = None;
|
||||
if let Some(bound) = n.bound()
|
||||
&& let Some(s) = self.ipc_mut(bound)
|
||||
{
|
||||
s.bound = None;
|
||||
}
|
||||
while let Some(tid) = n.pop_waiter() {
|
||||
self.wake_with_error(tid, KernelError::NoSuchObject);
|
||||
@@ -342,7 +357,9 @@ impl<P: Platform> Kernel<P> {
|
||||
/// Makes a blocked thread runnable with `error` as its syscall result,
|
||||
/// dropping whatever it was about to send.
|
||||
fn wake_with_error(&mut self, tid: ThreadId, error: KernelError) {
|
||||
self.ipc[tid.raw() as usize].outgoing = None;
|
||||
if let Some(s) = self.ipc_mut(tid) {
|
||||
s.outgoing = None;
|
||||
}
|
||||
self.wake(tid, SyscallResult::Error(error));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user