refactor(kernel): split syscall.rs into per-tier modules (simple, memory, lifecycle, capability, ipc)
This commit is contained in:
101
crates/kernel/src/syscall/memory.rs
Normal file
101
crates/kernel/src/syscall/memory.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
use platform::Platform;
|
||||
|
||||
use crate::{Kernel, SyscallOutcome, SyscallResult};
|
||||
|
||||
impl<P: Platform> Kernel<P> {
|
||||
pub(crate) fn handle_request_pages(
|
||||
&mut self,
|
||||
pid: types::id::ProcessId,
|
||||
count: types::bounded::PageCount,
|
||||
) -> SyscallOutcome {
|
||||
let pages = count.value() as usize;
|
||||
|
||||
if let Some(pm) = &mut self.process_memory[pid.raw() as usize] {
|
||||
if pm.grant(pages).is_err() {
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::OutOfMemory,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::InvalidProcess(pid),
|
||||
));
|
||||
}
|
||||
|
||||
let addr = match self.page_pool.allocate(pages) {
|
||||
Some(a) => a,
|
||||
None => {
|
||||
if let Some(pm) = &mut self.process_memory[pid.raw() as usize] {
|
||||
let _ = pm.release(pages);
|
||||
}
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::OutOfMemory,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let region = domain::memory::MemoryRegion::new(
|
||||
types::id::RegionId::from_raw(0),
|
||||
pid,
|
||||
addr,
|
||||
count,
|
||||
types::generation::Generation::initial(),
|
||||
);
|
||||
let region_id = match self.regions.insert(region) {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
self.page_pool.free(addr, pages);
|
||||
if let Some(pm) = &mut self.process_memory[pid.raw() as usize] {
|
||||
let _ = pm.release(pages);
|
||||
}
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::OutOfMemory,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let slot = match self.grant_cap(
|
||||
pid,
|
||||
domain::resource::Resource::Memory(region_id),
|
||||
types::permission::PermissionSet::empty()
|
||||
.with(types::permission::Permission::Read)
|
||||
.with(types::permission::Permission::Write),
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
||||
};
|
||||
|
||||
SyscallOutcome::Complete(SyscallResult::Slot(slot))
|
||||
}
|
||||
|
||||
pub(crate) fn handle_release_pages(
|
||||
&mut self,
|
||||
pid: types::id::ProcessId,
|
||||
addr: types::address::VirtualAddress,
|
||||
count: types::bounded::PageCount,
|
||||
) -> SyscallOutcome {
|
||||
let pages = count.value() as usize;
|
||||
let phys = types::address::PhysicalAddress::from_raw(addr.raw());
|
||||
|
||||
let region_id = match self.regions.find_by_base(pid, phys) {
|
||||
Some((rid, _)) => rid,
|
||||
None => return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::OutOfMemory,
|
||||
)),
|
||||
};
|
||||
|
||||
if !self.page_pool.free(phys, pages) {
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(
|
||||
domain::error::KernelError::OutOfMemory,
|
||||
));
|
||||
}
|
||||
|
||||
let _ = self.regions.remove(region_id);
|
||||
|
||||
if let Some(pm) = &mut self.process_memory[pid.raw() as usize] {
|
||||
let _ = pm.release(pages);
|
||||
}
|
||||
|
||||
SyscallOutcome::Complete(SyscallResult::Ok)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user