use lancer_core::header::KernelObjectHeader; use lancer_core::object_layout::{CNodeObject, KernelObject, ProcessObject, SchedContextObject}; use lancer_core::object_tag::ObjectTag; use crate::cap::cnode; use crate::cap::kernel_objects; use crate::cap::pool::POOL; use crate::cap::table::{CapRef, Rights}; use crate::error::KernelError; use crate::types::{Pid, Priority}; const SLOT_SELF: u64 = 0; const SLOT_INIT_SCHED: u64 = 63; pub fn bootstrap_root_cnode(pid: Pid, size_bits: u8) -> Result<(), KernelError> { let allocator = &crate::mem::phys::BitmapFrameAllocator; let cnode_data = cnode::create_cnode(size_bits, allocator)?; let frame_count = cnode_data.frame_count; let obj_phys = kernel_objects::alloc_slot().ok_or(KernelError::PoolExhausted)?; let header = KernelObjectHeader::new(ObjectTag::CNode, 0, 64); let mut obj = CNodeObject::init_default(header); obj.slots_phys = cnode_data.slots_phys.as_u64(); obj.size_bits = cnode_data.size_bits; obj.frame_count = cnode_data.frame_count; kernel_objects::write_at(obj_phys, obj); let (cnode_id, cnode_gen) = match POOL.lock().register_object(obj_phys, ObjectTag::CNode) { Ok(pair) => pair, Err(e) => { kernel_objects::free_slot(obj_phys); return Err(e); } }; let mut ptable = crate::proc::PROCESSES.lock(); let _sched = ptable.get(pid).ok_or(KernelError::InvalidObject)?; let exec = ptable.exec_mut(pid).ok_or(KernelError::InvalidObject)?; exec.root_cnode = Some((cnode_id, cnode_gen)); exec.cnode_depth = 64; exec.root_guard_bits = 64 - size_bits; exec.root_guard_value = 0; exec.charge_frames(frame_count as u16)?; Ok(()) } fn install_cap_phys(pid: Pid, slot: u64, tag: ObjectTag, obj_phys: u64) -> Result<(), KernelError> { let (object_id, generation) = POOL.lock().register_object(obj_phys, tag)?; let cap = CapRef::new(tag, object_id, Rights::ALL, generation); let ptable = crate::proc::PROCESSES.lock(); let pool = POOL.lock_after(&ptable); match cnode::resolve_caller_insert(pid, slot, cap, &ptable, &pool) { Ok(()) => Ok(()), Err(e) => { drop(pool); let r = POOL.lock_after(&ptable).free_phys(object_id, generation); debug_assert!(r.is_ok()); Err(e) } } } pub fn bootstrap_self_cap(pid: Pid, cnode_size_bits: u8) -> Result<(), KernelError> { bootstrap_root_cnode(pid, cnode_size_bits)?; let obj_phys = kernel_objects::alloc_slot().ok_or(KernelError::PoolExhausted)?; let header = KernelObjectHeader::new(ObjectTag::Process, 0, 64); let mut obj = ProcessObject::init_default(header); obj.pid = pid.raw(); kernel_objects::write_at(obj_phys, obj); install_cap_phys(pid, SLOT_SELF, ObjectTag::Process, obj_phys)?; bootstrap_init_sched(pid) } fn bootstrap_init_sched(pid: Pid) -> Result<(), KernelError> { let priority = Priority::new(200); let obj_phys = kernel_objects::alloc_slot().ok_or(KernelError::PoolExhausted)?; let header = KernelObjectHeader::new(ObjectTag::SchedContext, 0, 64); let mut obj = SchedContextObject::init_default(header); obj.budget_us = 10_000_000; obj.period_us = 10_000_000; obj.remaining_us = 10_000_000; obj.priority = priority.raw(); kernel_objects::write_at(obj_phys, obj); let (sc_id, sc_gen) = match POOL .lock() .register_object(obj_phys, ObjectTag::SchedContext) { Ok(pair) => pair, Err(e) => { kernel_objects::free_slot(obj_phys); return Err(e); } }; { let mut ptable = crate::proc::PROCESSES.lock(); let proc = ptable.get_mut(pid).ok_or(KernelError::InvalidObject)?; proc.attach_sched_context(sc_id, sc_gen, priority); } let cap = CapRef::new(ObjectTag::SchedContext, sc_id, Rights::ALL, sc_gen); let ptable = crate::proc::PROCESSES.lock(); let pool = POOL.lock_after(&ptable); cnode::resolve_caller_insert(pid, SLOT_INIT_SCHED, cap, &ptable, &pool) }