feat(kernel): seL4-style IPC, notifications, status ABI
- 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
This commit is contained in:
21
crates/types/src/badge.rs
Normal file
21
crates/types/src/badge.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
/// A word stamped on an endpoint or notification capability by `Mint`.
|
||||
/// Receivers see the badge of the capability a sender used, which is how a
|
||||
/// server tells its clients apart. Zero means "unbadged".
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Badge(usize);
|
||||
|
||||
impl Badge {
|
||||
pub const NONE: Self = Self(0);
|
||||
|
||||
pub const fn new(value: usize) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
|
||||
pub const fn raw(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub const fn is_none(&self) -> bool {
|
||||
self.0 == 0
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,6 @@ kernel_id!(ProcessId, u16);
|
||||
kernel_id!(ThreadId, u16);
|
||||
kernel_id!(EndpointId, u16);
|
||||
kernel_id!(RegionId, u16);
|
||||
kernel_id!(NotificationId, u16);
|
||||
kernel_id!(IrqId, u16);
|
||||
kernel_id!(CoreId, u8);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
pub mod address;
|
||||
pub mod badge;
|
||||
pub mod bounded;
|
||||
pub mod display;
|
||||
pub mod generation;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
//! Register-level syscall contract shared by the kernel and libkos.
|
||||
//! See docs/ipc.md for the meaning of each call.
|
||||
|
||||
pub const SYS_SEND: usize = 0;
|
||||
pub const SYS_RECEIVE: usize = 1;
|
||||
pub const SYS_DELEGATE: usize = 2;
|
||||
pub const SYS_WAIT_FOR_INTERRUPT: usize = 3;
|
||||
// 3 was WaitForInterrupt; interrupts are delivered through notifications.
|
||||
pub const SYS_ACKNOWLEDGE_INTERRUPT: usize = 4;
|
||||
pub const SYS_WAIT_ANY: usize = 5;
|
||||
// 5 was WaitAny; superseded by notifications.
|
||||
pub const SYS_CREATE_PROCESS: usize = 6;
|
||||
pub const SYS_KILL: usize = 7;
|
||||
pub const SYS_REVOKE: usize = 8;
|
||||
@@ -21,3 +24,63 @@ pub const SYS_DEBUG_PUTCHAR: usize = 19;
|
||||
pub const SYS_MAP_PAGE: usize = 20;
|
||||
pub const SYS_SPAWN_THREAD_IN: usize = 21;
|
||||
pub const SYS_DROP_CAP: usize = 22;
|
||||
pub const SYS_CALL: usize = 23;
|
||||
pub const SYS_REPLY: usize = 24;
|
||||
pub const SYS_REPLY_RECV: usize = 25;
|
||||
pub const SYS_MINT: usize = 26;
|
||||
pub const SYS_CREATE_NOTIFICATION: usize = 27;
|
||||
pub const SYS_SIGNAL: usize = 28;
|
||||
pub const SYS_WAIT: usize = 29;
|
||||
pub const SYS_POLL: usize = 30;
|
||||
pub const SYS_BIND_NOTIFICATION: usize = 31;
|
||||
pub const SYS_SET_IRQ_NOTIFICATION: usize = 32;
|
||||
|
||||
/// "No capability" in a capability argument or result register.
|
||||
pub const NONE: usize = usize::MAX;
|
||||
|
||||
/// What a receiving syscall got, returned in `a7`.
|
||||
pub const KIND_MESSAGE: usize = 0;
|
||||
pub const KIND_CALL: usize = 1;
|
||||
pub const KIND_SIGNAL: usize = 2;
|
||||
|
||||
/// Status returned in `a0`; `0` is success.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(usize)]
|
||||
pub enum ErrorCode {
|
||||
/// No capability in that slot, or it names a dead or revoked object.
|
||||
InvalidCap = 1,
|
||||
/// The capability lacks the permission the operation needs.
|
||||
PermissionDenied = 2,
|
||||
/// The capability names the wrong kind of object.
|
||||
WrongObject = 3,
|
||||
NoFreeSlot = 4,
|
||||
OutOfMemory = 5,
|
||||
InvalidAddress = 6,
|
||||
AddressInUse = 7,
|
||||
InvalidArgument = 8,
|
||||
/// `Reply` with nothing to reply to, or a call whose reply was dropped.
|
||||
NoReply = 9,
|
||||
/// A table (threads, processes, queue) is full.
|
||||
LimitReached = 10,
|
||||
UnknownSyscall = 11,
|
||||
}
|
||||
|
||||
impl ErrorCode {
|
||||
pub fn from_raw(code: usize) -> Option<Self> {
|
||||
use ErrorCode::*;
|
||||
Some(match code {
|
||||
1 => InvalidCap,
|
||||
2 => PermissionDenied,
|
||||
3 => WrongObject,
|
||||
4 => NoFreeSlot,
|
||||
5 => OutOfMemory,
|
||||
6 => InvalidAddress,
|
||||
7 => AddressInUse,
|
||||
8 => InvalidArgument,
|
||||
9 => NoReply,
|
||||
10 => LimitReached,
|
||||
11 => UnknownSyscall,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user