Nothing to see here, move along
at main 290 lines 8.5 kB view raw
1pub mod address_space; 2#[cfg(not(lancer_test))] 3pub mod bootstrap; 4pub mod context; 5pub mod elf; 6pub mod loader; 7pub mod manager; 8pub mod pid_table; 9 10use crate::mem::typed_addr::Pml4Phys; 11use crate::ring::RingIndex; 12use crate::types::{BlockedPid, Generation, ObjPhys, Pid, Priority}; 13 14pub(crate) const ROOT_CNODE_SIZE_BITS: u8 = 10; 15use context::{CpuContext, FpuState, IpcMessage}; 16 17pub use lancer_core::process_state::ProcessState; 18pub use manager::{PROCESSES, ProcessManager}; 19 20#[derive(Debug, Clone, Copy, PartialEq, Eq)] 21pub enum BlockedReason { 22 Sending(ObjPhys, Generation), 23 Receiving(ObjPhys, Generation), 24 Calling(ObjPhys, Generation), 25 WaitingNotification(ObjPhys, Generation), 26} 27 28pub(crate) const PROC_NAME_LEN: usize = 32; 29 30#[repr(C, align(64))] 31pub struct SchedEntity { 32 pub(crate) pid: Pid, 33 pub(crate) generation: Generation, 34 pub(crate) state: ProcessState, 35 pub(crate) priority: Priority, 36 pub(crate) effective_priority: Priority, 37 pub(crate) sched_context: Option<(ObjPhys, Generation)>, 38 pub(crate) next_ipc: Option<Pid>, 39 pub(crate) blocked_reason: Option<BlockedReason>, 40 pub(crate) run_cpu: Option<u16>, 41 pub(crate) death_notification: Option<(ObjPhys, Generation, u64)>, 42 pub(crate) bound_notification: Option<(ObjPhys, Generation)>, 43 pub(crate) exec_phys: u64, 44 pub(crate) next_free: u32, 45 pub(crate) run_prev: u32, 46 pub(crate) run_next: u32, 47 pub(crate) run_priority: u8, 48 pub(crate) timer_prev: u32, 49 pub(crate) timer_next: u32, 50 pub(crate) timer_slot: u16, 51 pub(crate) timer_deadline: u64, 52} 53 54#[repr(C, align(64))] 55pub struct ExecContext { 56 pub(crate) saved_context: CpuContext, 57 pub(crate) fpu_state: FpuState, 58 pub(crate) pml4_phys: Pml4Phys, 59 pub(crate) fs_base: u64, 60 pub(crate) context_checksum: u64, 61 pub(crate) ipc_message: IpcMessage, 62 pub(crate) ipc_badge: u64, 63 pub(crate) reply_target: Option<Pid>, 64 pub(crate) ring_region_id: Option<(ObjPhys, Generation)>, 65 pub(crate) ring_sq_head: RingIndex, 66 pub(crate) ring_cq_tail: RingIndex, 67 pub(crate) allocated_frames: u16, 68 pub(crate) name: [u8; PROC_NAME_LEN], 69 pub(crate) name_len: u8, 70 pub(crate) root_cnode: Option<(ObjPhys, Generation)>, 71 pub(crate) cnode_depth: u8, 72 pub(crate) root_guard_value: u64, 73 pub(crate) root_guard_bits: u8, 74 pub(crate) from_untyped: bool, 75} 76 77pub const MAX_FRAMES_PER_PROCESS: u16 = 16384; 78 79const _: () = assert!(core::mem::size_of::<SchedEntity>() <= 256); 80const _: () = assert!(core::mem::size_of::<ExecContext>() <= 1536); 81 82use lancer_core::header::NONE_SENTINEL; 83 84impl SchedEntity { 85 pub const EMPTY: Self = Self { 86 pid: Pid::new(0), 87 generation: Generation::new(0), 88 state: ProcessState::Free, 89 priority: Priority::IDLE, 90 effective_priority: Priority::IDLE, 91 sched_context: None, 92 next_ipc: None, 93 blocked_reason: None, 94 run_cpu: None, 95 death_notification: None, 96 bound_notification: None, 97 exec_phys: 0, 98 next_free: NONE_SENTINEL, 99 run_prev: NONE_SENTINEL, 100 run_next: NONE_SENTINEL, 101 run_priority: 0, 102 timer_prev: NONE_SENTINEL, 103 timer_next: NONE_SENTINEL, 104 timer_slot: 0, 105 timer_deadline: 0, 106 }; 107 108 pub fn state(&self) -> ProcessState { 109 self.state 110 } 111 112 pub fn transition_to(&mut self, to: ProcessState) -> Result<(), crate::error::KernelError> { 113 match to { 114 ProcessState::Dead => Err(crate::error::KernelError::BadState), 115 _ => self.state.transition(to), 116 } 117 } 118 119 pub fn zombify_state(&mut self) -> Result<(), crate::error::KernelError> { 120 self.state.transition(ProcessState::Zombie) 121 } 122 123 pub fn is_runnable(&self) -> bool { 124 matches!(self.state, ProcessState::Ready | ProcessState::Running) 125 } 126 127 pub fn blocked_reason(&self) -> Option<BlockedReason> { 128 self.blocked_reason 129 } 130 131 pub fn blocked_proof(&self) -> BlockedPid { 132 assert!( 133 self.state == ProcessState::Blocked, 134 "blocked_proof called on non-blocked process (pid={}, state={:?})", 135 self.pid.raw(), 136 self.state 137 ); 138 BlockedPid::from_blocked(self.pid, self.generation) 139 } 140 141 pub fn block_on( 142 &mut self, 143 reason: BlockedReason, 144 ) -> Result<BlockedPid, crate::error::KernelError> { 145 self.state.transition(ProcessState::Blocked)?; 146 self.blocked_reason = Some(reason); 147 Ok(BlockedPid::from_blocked(self.pid, self.generation)) 148 } 149 150 pub fn unblock(&mut self, _proof: BlockedPid) -> Result<(), crate::error::KernelError> { 151 self.state.transition(ProcessState::Ready)?; 152 self.blocked_reason = None; 153 Ok(()) 154 } 155 156 pub fn effective_priority(&self) -> Priority { 157 self.effective_priority 158 } 159 160 pub fn boost_effective_priority(&mut self, donor: Priority) { 161 if donor > self.effective_priority { 162 self.effective_priority = donor; 163 } 164 } 165 166 pub fn reset_effective_priority(&mut self) { 167 self.effective_priority = self.priority; 168 } 169 170 pub fn sched_context(&self) -> Option<(ObjPhys, Generation)> { 171 self.sched_context 172 } 173 174 pub fn attach_sched_context( 175 &mut self, 176 id: ObjPhys, 177 generation: Generation, 178 priority: Priority, 179 ) { 180 self.sched_context = Some((id, generation)); 181 self.priority = priority; 182 self.effective_priority = priority; 183 } 184 185 pub fn detach_sched_context(&mut self) { 186 self.sched_context = None; 187 } 188 189 pub fn death_notification(&self) -> Option<(ObjPhys, Generation, u64)> { 190 self.death_notification 191 } 192 193 pub fn set_death_notification( 194 &mut self, 195 notif_id: ObjPhys, 196 generation: Generation, 197 bits: u64, 198 ) { 199 self.death_notification = Some((notif_id, generation, bits)); 200 } 201 202 pub fn bound_notification(&self) -> Option<(ObjPhys, Generation)> { 203 self.bound_notification 204 } 205 206 pub fn bind_notification(&mut self, notif_id: ObjPhys, generation: Generation) { 207 self.bound_notification = Some((notif_id, generation)); 208 } 209 210 pub fn unbind_notification(&mut self) { 211 self.bound_notification = None; 212 } 213} 214 215impl ExecContext { 216 pub fn seal_context(&mut self) { 217 self.context_checksum = self.saved_context.checksum(); 218 } 219 220 pub fn verify_context(&self, pid: Pid) { 221 let computed = self.saved_context.checksum(); 222 assert!( 223 self.context_checksum == computed, 224 "context checksum mismatch for pid {} (stored={:#x}, computed={:#x})", 225 pid.raw(), 226 self.context_checksum, 227 computed 228 ); 229 } 230 231 pub fn set_name(&mut self, src: &[u8]) { 232 let copy_len = src.len().min(PROC_NAME_LEN); 233 self.name[..copy_len].copy_from_slice(&src[..copy_len]); 234 (copy_len..PROC_NAME_LEN).for_each(|i| self.name[i] = 0); 235 self.name_len = copy_len as u8; 236 } 237 238 pub fn name_str(&self) -> &str { 239 let len = self.name_len as usize; 240 match len { 241 0 => "?", 242 _ => core::str::from_utf8(&self.name[..len]).unwrap_or("?"), 243 } 244 } 245 246 pub fn charge_frames(&mut self, count: u16) -> Result<(), crate::error::KernelError> { 247 let new_total = self 248 .allocated_frames 249 .checked_add(count) 250 .filter(|&t| t <= MAX_FRAMES_PER_PROCESS) 251 .ok_or(crate::error::KernelError::ResourceExhausted)?; 252 self.allocated_frames = new_total; 253 Ok(()) 254 } 255 256 pub fn root_cnode(&self) -> Option<(ObjPhys, Generation)> { 257 self.root_cnode 258 } 259 260 pub fn cnode_depth(&self) -> u8 { 261 self.cnode_depth 262 } 263 264 pub fn root_guard_value(&self) -> u64 { 265 self.root_guard_value 266 } 267 268 pub fn root_guard_bits(&self) -> u8 { 269 self.root_guard_bits 270 } 271} 272 273#[cfg(lancer_test)] 274pub fn report_refcount_audit() { 275 let ptable = PROCESSES.lock(); 276 let cap = ptable.capacity(); 277 let (total, violations) = (0..cap as u32) 278 .filter_map(crate::types::Pid::try_new) 279 .filter_map(|pid| ptable.exec(pid).map(|e| e.pml4_phys.raw())) 280 .fold((0usize, 0usize), |(t, v), pml4| { 281 let (pt, pv) = address_space::audit_user_pages(pml4); 282 (t + pt, v + pv) 283 }); 284 crate::klog!( 285 "test", 286 "refcount audit {} PTEs checked, {} violations", 287 total, 288 violations 289 ); 290}