Nothing to see here, move along
1use lancer_core::header::KernelObjectHeader;
2use lancer_core::object_layout::{CNodeObject, KernelObject, ProcessObject, SchedContextObject};
3use lancer_core::object_tag::ObjectTag;
4
5use crate::cap::cnode;
6use crate::cap::kernel_objects;
7use crate::cap::pool::POOL;
8use crate::cap::table::{CapRef, Rights};
9use crate::error::KernelError;
10use crate::types::{Pid, Priority};
11
12const SLOT_SELF: u64 = 0;
13const SLOT_INIT_SCHED: u64 = 63;
14
15pub fn bootstrap_root_cnode(pid: Pid, size_bits: u8) -> Result<(), KernelError> {
16 let allocator = &crate::mem::phys::BitmapFrameAllocator;
17 let cnode_data = cnode::create_cnode(size_bits, allocator)?;
18 let frame_count = cnode_data.frame_count;
19
20 let obj_phys = kernel_objects::alloc_slot().ok_or(KernelError::PoolExhausted)?;
21 let header = KernelObjectHeader::new(ObjectTag::CNode, 0, 64);
22 let mut obj = CNodeObject::init_default(header);
23 obj.slots_phys = cnode_data.slots_phys.as_u64();
24 obj.size_bits = cnode_data.size_bits;
25 obj.frame_count = cnode_data.frame_count;
26 kernel_objects::write_at(obj_phys, obj);
27
28 let (cnode_id, cnode_gen) = match POOL.lock().register_object(obj_phys, ObjectTag::CNode) {
29 Ok(pair) => pair,
30 Err(e) => {
31 kernel_objects::free_slot(obj_phys);
32 return Err(e);
33 }
34 };
35
36 let mut ptable = crate::proc::PROCESSES.lock();
37 let _sched = ptable.get(pid).ok_or(KernelError::InvalidObject)?;
38 let exec = ptable.exec_mut(pid).ok_or(KernelError::InvalidObject)?;
39 exec.root_cnode = Some((cnode_id, cnode_gen));
40 exec.cnode_depth = 64;
41 exec.root_guard_bits = 64 - size_bits;
42 exec.root_guard_value = 0;
43 exec.charge_frames(frame_count as u16)?;
44 Ok(())
45}
46
47fn install_cap_phys(pid: Pid, slot: u64, tag: ObjectTag, obj_phys: u64) -> Result<(), KernelError> {
48 let (object_id, generation) = POOL.lock().register_object(obj_phys, tag)?;
49 let cap = CapRef::new(tag, object_id, Rights::ALL, generation);
50 let ptable = crate::proc::PROCESSES.lock();
51 let pool = POOL.lock_after(&ptable);
52 match cnode::resolve_caller_insert(pid, slot, cap, &ptable, &pool) {
53 Ok(()) => Ok(()),
54 Err(e) => {
55 drop(pool);
56 let r = POOL.lock_after(&ptable).free_phys(object_id, generation);
57 debug_assert!(r.is_ok());
58 Err(e)
59 }
60 }
61}
62
63pub fn bootstrap_self_cap(pid: Pid, cnode_size_bits: u8) -> Result<(), KernelError> {
64 bootstrap_root_cnode(pid, cnode_size_bits)?;
65
66 let obj_phys = kernel_objects::alloc_slot().ok_or(KernelError::PoolExhausted)?;
67 let header = KernelObjectHeader::new(ObjectTag::Process, 0, 64);
68 let mut obj = ProcessObject::init_default(header);
69 obj.pid = pid.raw();
70 kernel_objects::write_at(obj_phys, obj);
71 install_cap_phys(pid, SLOT_SELF, ObjectTag::Process, obj_phys)?;
72
73 bootstrap_init_sched(pid)
74}
75
76fn bootstrap_init_sched(pid: Pid) -> Result<(), KernelError> {
77 let priority = Priority::new(200);
78
79 let obj_phys = kernel_objects::alloc_slot().ok_or(KernelError::PoolExhausted)?;
80 let header = KernelObjectHeader::new(ObjectTag::SchedContext, 0, 64);
81 let mut obj = SchedContextObject::init_default(header);
82 obj.budget_us = 10_000_000;
83 obj.period_us = 10_000_000;
84 obj.remaining_us = 10_000_000;
85 obj.priority = priority.raw();
86 kernel_objects::write_at(obj_phys, obj);
87
88 let (sc_id, sc_gen) = match POOL
89 .lock()
90 .register_object(obj_phys, ObjectTag::SchedContext)
91 {
92 Ok(pair) => pair,
93 Err(e) => {
94 kernel_objects::free_slot(obj_phys);
95 return Err(e);
96 }
97 };
98
99 {
100 let mut ptable = crate::proc::PROCESSES.lock();
101 let proc = ptable.get_mut(pid).ok_or(KernelError::InvalidObject)?;
102 proc.attach_sched_context(sc_id, sc_gen, priority);
103 }
104
105 let cap = CapRef::new(ObjectTag::SchedContext, sc_id, Rights::ALL, sc_gen);
106 let ptable = crate::proc::PROCESSES.lock();
107 let pool = POOL.lock_after(&ptable);
108 cnode::resolve_caller_insert(pid, SLOT_INIT_SCHED, cap, &ptable, &pool)
109}