- badges + Mint, Call/Reply/ReplyRecv w/ gen-checked reply slot - cap transfer (1/msg, copy, needs Delegate, rechecked at delivery) - notifications: signal/wait/poll/bind, irq -> notification routing - WaitAny/WaitForInterrupt removed; a0=status, ErrorCode - libkos: single ecall primitive, compat wrappers + typed new api - fix: trap return clobbered user t0 on every trap - fix: wait queues FIFO, delegate keeps badge, fault cap checked - docs/ipc.md spec, ipc tests, ipc fuzz, kani ntfn + waitqueue
99 lines
2.3 KiB
Rust
99 lines
2.3 KiB
Rust
use types::{badge::Badge, bounded::CapSlot, generation::Generation, permission::PermissionSet};
|
|
|
|
pub mod authority;
|
|
|
|
use crate::{error::KernelError, resource::Resource};
|
|
|
|
#[cfg(test)]
|
|
#[path = "tests.rs"]
|
|
mod tests;
|
|
|
|
// Sized so that every representable `CapSlot` indexes a real slot.
|
|
pub const MAX_CAPS_PER_PROCESS: usize = CapSlot::MAX as usize + 1;
|
|
|
|
#[derive(Clone)]
|
|
pub struct Capability {
|
|
resource: Resource,
|
|
permissions: PermissionSet,
|
|
generation: Generation,
|
|
badge: Badge,
|
|
}
|
|
|
|
impl Capability {
|
|
pub fn new(resource: Resource, permissions: PermissionSet, generation: Generation) -> Self {
|
|
Self {
|
|
resource,
|
|
permissions,
|
|
generation,
|
|
badge: Badge::NONE,
|
|
}
|
|
}
|
|
|
|
/// The same capability with `badge` stamped on it.
|
|
pub fn with_badge(mut self, badge: Badge) -> Self {
|
|
self.badge = badge;
|
|
self
|
|
}
|
|
|
|
pub fn badge(&self) -> Badge {
|
|
self.badge
|
|
}
|
|
|
|
pub fn resource(&self) -> &Resource {
|
|
&self.resource
|
|
}
|
|
|
|
pub fn permissions(&self) -> &PermissionSet {
|
|
&self.permissions
|
|
}
|
|
|
|
pub fn generation(&self) -> &Generation {
|
|
&self.generation
|
|
}
|
|
}
|
|
|
|
pub struct CapabilityTable {
|
|
slots: [Option<Capability>; MAX_CAPS_PER_PROCESS],
|
|
}
|
|
|
|
impl CapabilityTable {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
slots: [const { None }; MAX_CAPS_PER_PROCESS],
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, slot: CapSlot) -> Result<&Capability, KernelError> {
|
|
let idx = slot.value() as usize;
|
|
self.slots[idx]
|
|
.as_ref()
|
|
.ok_or(KernelError::InvalidSlot(slot))
|
|
}
|
|
|
|
pub fn insert(&mut self, cap: Capability) -> Result<CapSlot, KernelError> {
|
|
let idx = self
|
|
.slots
|
|
.iter()
|
|
.position(|s| s.is_none())
|
|
.ok_or(KernelError::NoFreeSlot)?;
|
|
|
|
self.slots[idx] = Some(cap);
|
|
CapSlot::new(idx as u8).ok_or(KernelError::NoFreeSlot)
|
|
}
|
|
|
|
pub fn remove(&mut self, slot: CapSlot) -> Result<(), KernelError> {
|
|
let idx = slot.value() as usize;
|
|
if self.slots[idx].is_none() {
|
|
return Err(KernelError::InvalidSlot(slot));
|
|
}
|
|
self.slots[idx] = None;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Default for CapabilityTable {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|