Files
RedBear-OS/src/syscall/process.rs
T
Wildan Mubarok 1ff46c8482 Fix Linter CI
2025-08-04 06:34:31 -06:00

146 lines
4.3 KiB
Rust

use alloc::{sync::Arc, vec::Vec};
use core::{mem, num::NonZeroUsize};
use rmm::Arch;
use spin::RwLock;
use crate::{
context::{
memory::{AddrSpace, Grant, PageSpan},
ContextRef,
},
event,
scheme::GlobalSchemes,
syscall::EventFlags,
};
use crate::{
context,
context::context::FdTbl,
paging::{Page, VirtualAddress, PAGE_SIZE},
syscall::{error::*, flag::MapFlags},
Bootstrap, CurrentRmmArch,
};
use super::usercopy::UserSliceWo;
pub fn exit_this_context(excp: Option<syscall::Exception>) -> ! {
let mut close_files;
let addrspace_opt;
let context_lock = context::current();
{
let mut context = context_lock.write();
close_files = Arc::try_unwrap(mem::take(&mut context.files))
.map_or_else(|_| FdTbl::new(), RwLock::into_inner);
addrspace_opt = context
.set_addr_space(None)
.and_then(|a| Arc::try_unwrap(a).ok());
drop(context.syscall_head.take());
drop(context.syscall_tail.take());
}
// Files must be closed while context is valid so that messages can be passed
close_files.force_close_all();
drop(addrspace_opt);
// TODO: Should status == Status::HardBlocked be handled differently?
let owner = {
let mut guard = context_lock.write();
guard.status = context::Status::Dead { excp };
guard.owner_proc_id
};
if let Some(owner) = owner {
let _ = event::trigger(
GlobalSchemes::Proc.scheme_id(),
owner.get(),
EventFlags::EVENT_READ,
);
}
let _ = context::contexts_mut().remove(&ContextRef(context_lock));
context::switch();
unreachable!();
}
pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result<()> {
// println!("mprotect {:#X}, {}, {:#X}", address, size, flags);
let span = PageSpan::validate_nonempty(VirtualAddress::new(address), size)
.ok_or(Error::new(EINVAL))?;
AddrSpace::current()?.mprotect(span, flags)
}
pub unsafe fn usermode_bootstrap(bootstrap: &Bootstrap) {
assert_ne!(bootstrap.page_count, 0);
{
let addr_space = Arc::clone(
context::current()
.read()
.addr_space()
.expect("expected bootstrap context to have an address space"),
);
let base = Page::containing_address(VirtualAddress::new(PAGE_SIZE));
let flags = MapFlags::MAP_FIXED_NOREPLACE
| MapFlags::PROT_EXEC
| MapFlags::PROT_READ
| MapFlags::PROT_WRITE;
let page_count =
NonZeroUsize::new(bootstrap.page_count).expect("bootstrap contained no pages!");
let _base_page = addr_space
.acquire_write()
.mmap(
&addr_space,
Some(base),
page_count,
flags,
&mut Vec::new(),
|page, flags, mapper, flusher| {
let shared = false;
Ok(Grant::zeroed(
PageSpan::new(page, bootstrap.page_count),
flags,
mapper,
flusher,
shared,
)?)
},
)
.expect("Failed to allocate bootstrap pages");
}
let bootstrap_slice = unsafe { bootstrap_mem(bootstrap) };
UserSliceWo::new(PAGE_SIZE, bootstrap.page_count * PAGE_SIZE)
.expect("failed to create bootstrap user slice")
.copy_from_slice(bootstrap_slice)
.expect("failed to copy memory to bootstrap");
let bootstrap_entry = u64::from_le_bytes(bootstrap_slice[0x1a..0x22].try_into().unwrap());
log::info!("Bootstrap entry point: {:X}", bootstrap_entry);
assert_ne!(bootstrap_entry, 0);
println!("\n");
// Start in a minimal environment without any stack.
match context::current()
.write()
.regs_mut()
.expect("bootstrap needs registers to be available")
{
ref mut regs => {
regs.init();
regs.set_instr_pointer(bootstrap_entry.try_into().unwrap());
}
}
}
pub unsafe fn bootstrap_mem(bootstrap: &crate::Bootstrap) -> &'static [u8] {
core::slice::from_raw_parts(
CurrentRmmArch::phys_to_virt(bootstrap.base.base()).data() as *const u8,
bootstrap.page_count * PAGE_SIZE,
)
}