1use crate::mm::mm_error::MmError;
7use crate::mm::vmm::address_space::AddressSpace;
8use crate::sched::loader::defs::error::ElfError;
9use crate::sched::loader::load::{map_phdrs_and_copy_elf, setup_user_stack};
10use crate::sched::loader::validate::validate_elf;
11use crate::sched::process::{Pid, Process};
12use crate::state::kstate::KSTATE;
13
14pub type SpawnResult<T> = Result<T, SpawnError>;
16
17pub enum SpawnError {
19 InvalidBinary,
20 OutOfMemory,
21 MappingCollision
22}
23impl From<MmError> for SpawnError {
24 fn from(value: MmError) -> Self {
26 match value {
27 MmError::MisalignedAddress | MmError::NotFound => Self::InvalidBinary,
28 MmError::OutOfMemory => Self::OutOfMemory,
29 MmError::Overlap => Self::MappingCollision
30 }
31 }
32}
33impl From<ElfError> for SpawnError {
34 fn from(_: ElfError) -> Self {
36 Self::InvalidBinary
37 }
38}
39
40pub unsafe fn spawn_from_elf(elf: &[u8], parent_pid: Pid) -> SpawnResult<Pid> {
45 let (phdrs, e_entry) = validate_elf(elf)?;
46
47 let mut addr_space = unsafe { AddressSpace::new_user_addr_space() };
48 map_phdrs_and_copy_elf(&mut addr_space, phdrs, elf)?;
49
50 let user_stack_top = setup_user_stack(&mut addr_space)?;
51 let kernel_stack_top = unsafe {
52 crate::mm::kernel::alloc_stack(&mut KSTATE.mm.pmm().lock(), &mut KSTATE.mm.kernel_addr_space().lock())
53 }?;
54
55 let pid = KSTATE.sched.alloc_pid();
56
57 let mut process = Process::new(
58 pid,
59 parent_pid,
60 addr_space,
61 kernel_stack_top
62 );
63 process.regs.rip = e_entry;
64 process.regs.rsp = user_stack_top.as_u64();
65
66 unsafe { KSTATE.sched.insert_process(process) };
67
68 Ok(pid)
69}
70
71