feat(kernel): SystemControl cap for halt, board device table + boot caps to init, RegionAddress syscall, idle loop services irqs
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
use platform::Platform;
|
||||
use types::{
|
||||
address::VirtualAddress, bounded::CapSlot, bounded::PageCount, id::ProcessId,
|
||||
address::{PhysicalAddress, VirtualAddress},
|
||||
bounded::CapSlot,
|
||||
bounded::PageCount,
|
||||
id::ProcessId,
|
||||
mapping::PagePerms,
|
||||
};
|
||||
|
||||
@@ -115,4 +118,18 @@ impl<P: Platform> Kernel<P> {
|
||||
let via = self.cap_ref(pid, slot);
|
||||
self.map_region_via(id, pid, va, perms, via)
|
||||
}
|
||||
|
||||
/// The physical base of the region behind `slot`. Needs Read on the
|
||||
/// capability; pool regions are physically contiguous, so the base is
|
||||
/// enough to program a device.
|
||||
pub(crate) fn region_address_cap(
|
||||
&self,
|
||||
pid: ProcessId,
|
||||
slot: CapSlot,
|
||||
) -> Result<PhysicalAddress, KernelError> {
|
||||
let Resource::Memory(id) = *self.check_cap(pid, slot, Permission::Read)?.resource() else {
|
||||
return Err(KernelError::WrongObject);
|
||||
};
|
||||
self.region_base(id).ok_or(KernelError::InvalidRegion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,10 @@ impl<P: Platform> Kernel<P> {
|
||||
self.map_region_cap(pid, region, va, perms)
|
||||
.map(|()| SyscallResult::Ok),
|
||||
),
|
||||
Syscall::RegionAddress { region } => complete(
|
||||
self.region_address_cap(pid, region)
|
||||
.map(|pa| SyscallResult::Value(pa.raw())),
|
||||
),
|
||||
Syscall::Delegate {
|
||||
slot,
|
||||
to_endpoint,
|
||||
@@ -136,7 +140,7 @@ impl<P: Platform> Kernel<P> {
|
||||
Syscall::AcknowledgeInterrupt { irq } => {
|
||||
complete(self.ack_interrupt(pid, irq).map(|()| SyscallResult::Ok))
|
||||
}
|
||||
Syscall::Halt => self.handle_halt(pid),
|
||||
Syscall::Halt { control } => self.handle_halt(pid, control),
|
||||
Syscall::CreateEndpoint => self.handle_create_endpoint(pid),
|
||||
Syscall::DebugPutchar { byte } => self.handle_debug_putchar(byte),
|
||||
Syscall::MapPage {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use domain::{error::KernelError, resource::Resource};
|
||||
use platform::Platform;
|
||||
use types::{bounded::CapSlot, id::ProcessId, permission::Permission};
|
||||
|
||||
use super::{SyscallOutcome, SyscallResult};
|
||||
use crate::Kernel;
|
||||
@@ -87,12 +89,13 @@ impl<P: Platform> Kernel<P> {
|
||||
SyscallOutcome::Complete(SyscallResult::Ok)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_halt(&mut self, pid: types::id::ProcessId) -> SyscallOutcome {
|
||||
if pid.raw() != 0 {
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::ProcessCreateDenied,
|
||||
));
|
||||
/// Halts the machine for a holder of a SystemControl capability with
|
||||
/// Execute; anyone else gets an error and nothing happens.
|
||||
pub(crate) fn handle_halt(&mut self, pid: ProcessId, control: CapSlot) -> SyscallOutcome {
|
||||
match self.check_cap(pid, control, Permission::Execute) {
|
||||
Ok(cap) if *cap.resource() == Resource::SystemControl => self.platform.halt(),
|
||||
Ok(_) => SyscallOutcome::Complete(SyscallResult::Error(KernelError::WrongObject)),
|
||||
Err(e) => SyscallOutcome::Complete(SyscallResult::Error(e)),
|
||||
}
|
||||
self.platform.halt();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user