feat(kernel): per-process budgets (pages, endpoints, notifs, regions) carved from creator, returned on death; init owns pool

This commit is contained in:
2026-10-27 15:08:58 +01:00
parent 7415bab7f5
commit 4049ba5007
46 changed files with 672 additions and 119 deletions

View File

@@ -16,6 +16,7 @@
pub mod abi;
mod board;
mod budget;
mod captree;
pub mod interrupt;
mod memory;
@@ -33,11 +34,12 @@ pub use syscall::{SyscallOutcome, SyscallResult};
mod tests;
use domain::{
capability::{Capability, CapabilityTable},
budget::{Budget, Limits},
capability::Capability,
endpoint::EndpointTable,
error::KernelError,
irq::IrqRoutingTable,
memory::{RegionTable, frame::FrameTable, quota::Quota},
memory::{RegionTable, frame::FrameTable},
notification::NotificationTable,
process::{MAX_PROCESSES, ProcessTable},
resource::Resource,
@@ -61,7 +63,9 @@ pub struct Kernel<P: Platform> {
endpoints: EndpointTable,
scheduler: MultiCoreScheduler,
frames: FrameTable,
quotas: [Quota; MAX_PROCESSES],
budgets: [Budget; MAX_PROCESSES],
/// Whose budget each process was carved from (see budget.rs).
parents: [Option<ProcessId>; MAX_PROCESSES],
regions: RegionTable,
irqs: IrqRoutingTable,
notifications: NotificationTable,
@@ -85,7 +89,8 @@ impl<P: Platform> Kernel<P> {
endpoints: EndpointTable::new(),
scheduler: MultiCoreScheduler::new(num_cores),
frames: FrameTable::new(pool_base, pool_pages),
quotas: [Quota::default(); MAX_PROCESSES],
budgets: [Budget::EMPTY; MAX_PROCESSES],
parents: [None; MAX_PROCESSES],
regions: RegionTable::new(),
irqs: IrqRoutingTable::new(),
notifications: NotificationTable::new(),
@@ -118,7 +123,8 @@ impl<P: Platform> Kernel<P> {
addr_of_mut!((*slot).endpoints).write(EndpointTable::new());
addr_of_mut!((*slot).scheduler).write(MultiCoreScheduler::new(num_cores));
addr_of_mut!((*slot).frames).write(FrameTable::new(pool_base, pool_pages));
addr_of_mut!((*slot).quotas).write([Quota::default(); MAX_PROCESSES]);
addr_of_mut!((*slot).budgets).write([Budget::EMPTY; MAX_PROCESSES]);
addr_of_mut!((*slot).parents).write([None; MAX_PROCESSES]);
addr_of_mut!((*slot).regions).write(RegionTable::new());
addr_of_mut!((*slot).irqs).write(IrqRoutingTable::new());
addr_of_mut!((*slot).notifications).write(NotificationTable::new());
@@ -135,11 +141,14 @@ impl<P: Platform> Kernel<P> {
priority: Priority,
time_slice: TimeSlice,
) -> Result<(ProcessId, ThreadId), KernelError> {
let pid = self.processes.create(CapabilityTable::new(), None)?;
if let Err(e) = self.create_address_space(pid) {
let _ = self.processes.destroy(pid);
return Err(e);
}
// Init holds every frame and every kernel object to start with.
let everything = Limits {
pages: self.frames.free_count(),
endpoints: domain::endpoint::MAX_ENDPOINTS,
notifications: domain::notification::MAX_NOTIFICATIONS,
regions: domain::memory::MAX_REGIONS,
};
let pid = self.new_process(None, everything)?;
let tid = self.threads.spawn(pid, priority, time_slice, None)?;
self.processes.get_mut(pid)?.add_thread(tid)?;
@@ -211,13 +220,13 @@ impl<P: Platform> Kernel<P> {
self.scheduler.next(core)
}
pub fn create_process_internal(&mut self) -> Option<ProcessId> {
let pid = self.processes.create(CapabilityTable::new(), None).ok()?;
if self.create_address_space(pid).is_err() {
let _ = self.processes.destroy(pid);
return None;
}
Some(pid)
/// A process for boot code to load, its `limits` carved from `parent`.
pub fn create_process_internal(
&mut self,
parent: ProcessId,
limits: Limits,
) -> Option<ProcessId> {
self.new_process(Some(parent), limits).ok()
}
pub fn spawn_thread_internal(&mut self, pid: ProcessId) -> Option<ThreadId> {
@@ -237,7 +246,11 @@ impl<P: Platform> Kernel<P> {
owner: ProcessId,
) -> Result<types::id::EndpointId, KernelError> {
self.processes.get(owner)?;
self.endpoints.create(owner).ok_or(KernelError::NoFreeSlot)
self.charge_object(owner, budget::ENDPOINTS)?;
self.endpoints
.create(owner)
.ok_or(KernelError::NoFreeSlot)
.inspect_err(|_| self.uncharge_object(owner, budget::ENDPOINTS))
}
pub fn grant_capability(