103 lines
3.3 KiB
Rust
103 lines
3.3 KiB
Rust
use platform::Platform;
|
|
|
|
use super::{SyscallOutcome, SyscallResult};
|
|
use crate::Kernel;
|
|
|
|
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)
|
|
}
|
|
}
|