Nothing to see here, move along meow
at main 189 lines 5.2 kB view raw
1use crate::sync::IrqMutex; 2use crate::types::Pid; 3use lancer_core::header::NONE_SENTINEL; 4 5pub const MAX_FRAME_TABLE_ENTRIES: usize = 16384; 6const FREE_STACK_SIZE: usize = MAX_FRAME_TABLE_ENTRIES; 7 8#[derive(Clone, Copy)] 9struct FrameMappingSlot { 10 pid_raw: u32, 11 vaddr: u64, 12} 13 14impl FrameMappingSlot { 15 const EMPTY: Self = Self { 16 pid_raw: NONE_SENTINEL, 17 vaddr: 0, 18 }; 19} 20 21#[derive(Clone, Copy)] 22pub struct IommuMapping { 23 pub bus: u8, 24 pub devfn: u8, 25 pub iova: u64, 26} 27 28pub struct FrameMappingEntry { 29 mappings: [FrameMappingSlot; 4], 30 mapping_count: u8, 31 has_iommu: bool, 32 iommu: IommuMapping, 33} 34 35impl FrameMappingEntry { 36 const fn new() -> Self { 37 Self { 38 mappings: [FrameMappingSlot::EMPTY; 4], 39 mapping_count: 0, 40 has_iommu: false, 41 iommu: IommuMapping { 42 bus: 0, 43 devfn: 0, 44 iova: 0, 45 }, 46 } 47 } 48 49 pub fn add_mapping( 50 &mut self, 51 pid: Pid, 52 vaddr: x86_64::VirtAddr, 53 ) -> Result<(), crate::error::KernelError> { 54 match (self.mapping_count as usize) < 4 { 55 true => { 56 self.mappings[self.mapping_count as usize] = FrameMappingSlot { 57 pid_raw: pid.raw(), 58 vaddr: vaddr.as_u64(), 59 }; 60 self.mapping_count += 1; 61 Ok(()) 62 } 63 false => Err(crate::error::KernelError::ResourceExhausted), 64 } 65 } 66 67 pub fn remove_mapping(&mut self, pid: Pid, vaddr: x86_64::VirtAddr) -> bool { 68 let target_pid = pid.raw(); 69 let target_vaddr = vaddr.as_u64(); 70 let mut found = false; 71 let mut write_idx = 0usize; 72 (0..self.mapping_count as usize).for_each(|read_idx| { 73 let slot = self.mappings[read_idx]; 74 match slot.pid_raw == target_pid && slot.vaddr == target_vaddr && !found { 75 true => { 76 found = true; 77 } 78 false => { 79 self.mappings[write_idx] = slot; 80 write_idx += 1; 81 } 82 } 83 }); 84 if found { 85 self.mapping_count -= 1; 86 self.mappings[self.mapping_count as usize] = FrameMappingSlot::EMPTY; 87 } 88 found 89 } 90 91 pub fn for_each_mapping(&self, mut f: impl FnMut(Pid, x86_64::VirtAddr)) { 92 (0..self.mapping_count as usize).for_each(|i| { 93 let slot = self.mappings[i]; 94 if let Some(pid) = Pid::try_new(slot.pid_raw) { 95 f(pid, x86_64::VirtAddr::new(slot.vaddr)); 96 } 97 }); 98 } 99 100 #[cfg(lancer_test)] 101 pub fn mapping_count(&self) -> u8 { 102 self.mapping_count 103 } 104 105 pub fn set_iommu(&mut self, mapping: IommuMapping) { 106 self.iommu = mapping; 107 self.has_iommu = true; 108 } 109 110 pub fn clear_iommu(&mut self) { 111 self.has_iommu = false; 112 } 113 114 pub fn iommu_mapping(&self) -> Option<&IommuMapping> { 115 match self.has_iommu { 116 true => Some(&self.iommu), 117 false => None, 118 } 119 } 120 121 fn clear(&mut self) { 122 *self = Self::new(); 123 } 124} 125 126pub struct FrameMappingTable { 127 entries: [FrameMappingEntry; MAX_FRAME_TABLE_ENTRIES], 128 free_stack: [u16; FREE_STACK_SIZE], 129 free_count: u16, 130 next_fresh: u16, 131} 132 133impl FrameMappingTable { 134 const fn new() -> Self { 135 Self { 136 entries: [const { FrameMappingEntry::new() }; MAX_FRAME_TABLE_ENTRIES], 137 free_stack: [0u16; FREE_STACK_SIZE], 138 free_count: 0, 139 next_fresh: 0, 140 } 141 } 142 143 pub fn alloc_idx(&mut self) -> Option<u16> { 144 match self.free_count > 0 { 145 true => { 146 self.free_count -= 1; 147 Some(self.free_stack[self.free_count as usize]) 148 } 149 false => match (self.next_fresh as usize) < MAX_FRAME_TABLE_ENTRIES { 150 true => { 151 let idx = self.next_fresh; 152 self.next_fresh += 1; 153 Some(idx) 154 } 155 false => None, 156 }, 157 } 158 } 159 160 pub fn get(&self, idx: u16) -> &FrameMappingEntry { 161 debug_assert!( 162 (idx as usize) < MAX_FRAME_TABLE_ENTRIES, 163 "frame table OOB: {idx}" 164 ); 165 &self.entries[idx as usize] 166 } 167 168 pub fn get_mut(&mut self, idx: u16) -> &mut FrameMappingEntry { 169 debug_assert!( 170 (idx as usize) < MAX_FRAME_TABLE_ENTRIES, 171 "frame table OOB: {idx}" 172 ); 173 &mut self.entries[idx as usize] 174 } 175 176 pub fn clear(&mut self, idx: u16) { 177 debug_assert!( 178 (idx as usize) < MAX_FRAME_TABLE_ENTRIES, 179 "frame table OOB: {idx}" 180 ); 181 self.entries[idx as usize].clear(); 182 if (self.free_count as usize) < FREE_STACK_SIZE { 183 self.free_stack[self.free_count as usize] = idx; 184 self.free_count += 1; 185 } 186 } 187} 188 189pub static FRAME_TABLE: IrqMutex<FrameMappingTable, 2> = IrqMutex::new(FrameMappingTable::new());