1 use core::{alloc::Layout, intrinsics::unlikely, panic}; 2 3 use alloc::sync::Arc; 4 5 use crate::{ 6 arch::{mm::PageMapper, MMArch}, 7 mm::{ 8 page::{page_manager_lock_irqsave, PageFlags}, 9 ucontext::LockedVMA, 10 VirtAddr, VmFaultReason, VmFlags, 11 }, 12 process::{ProcessManager, ProcessState}, 13 }; 14 15 use crate::mm::MemoryManagementArch; 16 17 bitflags! { 18 pub struct FaultFlags: u64{ 19 const FAULT_FLAG_WRITE = 1 << 0; 20 const FAULT_FLAG_MKWRITE = 1 << 1; 21 const FAULT_FLAG_ALLOW_RETRY = 1 << 2; 22 const FAULT_FLAG_RETRY_NOWAIT = 1 << 3; 23 const FAULT_FLAG_KILLABLE = 1 << 4; 24 const FAULT_FLAG_TRIED = 1 << 5; 25 const FAULT_FLAG_USER = 1 << 6; 26 const FAULT_FLAG_REMOTE = 1 << 7; 27 const FAULT_FLAG_INSTRUCTION = 1 << 8; 28 const FAULT_FLAG_INTERRUPTIBLE =1 << 9; 29 const FAULT_FLAG_UNSHARE = 1 << 10; 30 const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11; 31 const FAULT_FLAG_VMA_LOCK = 1 << 12; 32 } 33 } 34 35 /// # 缺页异常信息结构体 36 /// 包含了页面错误处理的相关信息,例如出错的地址、VMA等 37 #[derive(Debug)] 38 pub struct PageFaultMessage { 39 vma: Arc<LockedVMA>, 40 address: VirtAddr, 41 flags: FaultFlags, 42 } 43 44 impl PageFaultMessage { 45 pub fn new(vma: Arc<LockedVMA>, address: VirtAddr, flags: FaultFlags) -> Self { 46 Self { 47 vma: vma.clone(), 48 address, 49 flags, 50 } 51 } 52 53 #[inline(always)] 54 #[allow(dead_code)] 55 pub fn vma(&self) -> Arc<LockedVMA> { 56 self.vma.clone() 57 } 58 59 #[inline(always)] 60 #[allow(dead_code)] 61 pub fn address(&self) -> VirtAddr { 62 self.address 63 } 64 65 #[inline(always)] 66 #[allow(dead_code)] 67 pub fn address_aligned_down(&self) -> VirtAddr { 68 VirtAddr::new(crate::libs::align::page_align_down(self.address.data())) 69 } 70 71 #[inline(always)] 72 #[allow(dead_code)] 73 pub fn flags(&self) -> FaultFlags { 74 self.flags 75 } 76 } 77 78 impl Clone for PageFaultMessage { 79 fn clone(&self) -> Self { 80 Self { 81 vma: self.vma.clone(), 82 address: self.address, 83 flags: self.flags, 84 } 85 } 86 } 87 88 /// 缺页中断处理结构体 89 pub struct PageFaultHandler; 90 91 impl PageFaultHandler { 92 /// 处理缺页异常 93 /// ## 参数 94 /// 95 /// - `pfm`: 缺页异常信息 96 /// - `mapper`: 页表映射器 97 /// 98 /// ## 返回值 99 /// - VmFaultReason: 页面错误处理信息标志 100 pub unsafe fn handle_mm_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 101 let flags = pfm.flags(); 102 let vma = pfm.vma(); 103 let current_pcb = ProcessManager::current_pcb(); 104 let mut guard = current_pcb.sched_info().inner_lock_write_irqsave(); 105 guard.set_state(ProcessState::Runnable); 106 107 if !MMArch::vma_access_permitted( 108 vma.clone(), 109 flags.contains(FaultFlags::FAULT_FLAG_WRITE), 110 flags.contains(FaultFlags::FAULT_FLAG_INSTRUCTION), 111 flags.contains(FaultFlags::FAULT_FLAG_REMOTE), 112 ) { 113 return VmFaultReason::VM_FAULT_SIGSEGV; 114 } 115 116 let guard = vma.lock(); 117 let vm_flags = *guard.vm_flags(); 118 drop(guard); 119 if unlikely(vm_flags.contains(VmFlags::VM_HUGETLB)) { 120 //TODO: 添加handle_hugetlb_fault处理大页缺页异常 121 } else { 122 Self::handle_normal_fault(pfm, mapper); 123 } 124 125 VmFaultReason::VM_FAULT_COMPLETED 126 } 127 128 /// 处理普通页缺页异常 129 /// ## 参数 130 /// 131 /// - `pfm`: 缺页异常信息 132 /// - `mapper`: 页表映射器 133 /// 134 /// ## 返回值 135 /// - VmFaultReason: 页面错误处理信息标志 136 pub unsafe fn handle_normal_fault( 137 pfm: PageFaultMessage, 138 mapper: &mut PageMapper, 139 ) -> VmFaultReason { 140 let address = pfm.address_aligned_down(); 141 let vma = pfm.vma.clone(); 142 if mapper.get_entry(address, 3).is_none() { 143 mapper 144 .allocate_table(address, 2) 145 .expect("failed to allocate PUD table"); 146 } 147 let page_flags = vma.lock().flags(); 148 149 for level in 2..=3 { 150 let level = MMArch::PAGE_LEVELS - level; 151 if mapper.get_entry(address, level).is_none() { 152 if vma.is_hugepage() { 153 if vma.is_anonymous() { 154 mapper.map_huge_page(address, page_flags); 155 } 156 } else if mapper.allocate_table(address, level - 1).is_none() { 157 return VmFaultReason::VM_FAULT_OOM; 158 } 159 } 160 } 161 162 Self::handle_pte_fault(pfm, mapper) 163 } 164 165 /// 处理页表项异常 166 /// ## 参数 167 /// 168 /// - `pfm`: 缺页异常信息 169 /// - `mapper`: 页表映射器 170 /// 171 /// ## 返回值 172 /// - VmFaultReason: 页面错误处理信息标志 173 pub unsafe fn handle_pte_fault( 174 pfm: PageFaultMessage, 175 mapper: &mut PageMapper, 176 ) -> VmFaultReason { 177 let address = pfm.address_aligned_down(); 178 let flags = pfm.flags; 179 let vma = pfm.vma.clone(); 180 let mut ret = VmFaultReason::VM_FAULT_COMPLETED; 181 if let Some(mut entry) = mapper.get_entry(address, 0) { 182 if !entry.present() { 183 ret = Self::do_swap_page(pfm.clone(), mapper); 184 } 185 if entry.protnone() && vma.is_accessible() { 186 ret = Self::do_numa_page(pfm.clone(), mapper); 187 } 188 if flags.intersects(FaultFlags::FAULT_FLAG_WRITE | FaultFlags::FAULT_FLAG_UNSHARE) { 189 if !entry.write() { 190 ret = Self::do_wp_page(pfm.clone(), mapper); 191 } else { 192 entry.set_flags(PageFlags::from_data(MMArch::ENTRY_FLAG_DIRTY)); 193 } 194 } 195 } else if vma.is_anonymous() { 196 ret = Self::do_anonymous_page(pfm.clone(), mapper); 197 } else { 198 ret = Self::do_fault(pfm.clone(), mapper); 199 } 200 201 vma.lock().set_mapped(true); 202 203 return ret; 204 } 205 206 /// 处理匿名映射页缺页异常 207 /// ## 参数 208 /// 209 /// - `pfm`: 缺页异常信息 210 /// - `mapper`: 页表映射器 211 /// 212 /// ## 返回值 213 /// - VmFaultReason: 页面错误处理信息标志 214 pub unsafe fn do_anonymous_page( 215 pfm: PageFaultMessage, 216 mapper: &mut PageMapper, 217 ) -> VmFaultReason { 218 let address = pfm.address_aligned_down(); 219 let vma = pfm.vma.clone(); 220 let guard = vma.lock(); 221 if let Some(flush) = mapper.map(address, guard.flags()) { 222 flush.flush(); 223 crate::debug::klog::mm::mm_debug_log( 224 klog_types::AllocatorLogType::LazyAlloc(klog_types::AllocLogItem::new( 225 Layout::from_size_align(MMArch::PAGE_SIZE, MMArch::PAGE_SIZE).unwrap(), 226 Some(address.data()), 227 Some(mapper.translate(address).unwrap().0.data()), 228 )), 229 klog_types::LogSource::Buddy, 230 ); 231 let paddr = mapper.translate(address).unwrap().0; 232 let mut anon_vma_guard = page_manager_lock_irqsave(); 233 let page = anon_vma_guard.get_mut(&paddr); 234 page.insert_vma(vma.clone()); 235 VmFaultReason::VM_FAULT_COMPLETED 236 } else { 237 VmFaultReason::VM_FAULT_OOM 238 } 239 } 240 241 /// 处理文件映射页的缺页异常 242 /// ## 参数 243 /// 244 /// - `pfm`: 缺页异常信息 245 /// - `mapper`: 页表映射器 246 /// 247 /// ## 返回值 248 /// - VmFaultReason: 页面错误处理信息标志 249 #[allow(unused_variables)] 250 pub unsafe fn do_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 251 panic!( 252 "do_fault has not yet been implemented, 253 fault message: {:?}, 254 pid: {}\n", 255 pfm, 256 crate::process::ProcessManager::current_pid().data() 257 ); 258 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_fault 259 } 260 261 /// 处理私有文件映射的写时复制 262 /// ## 参数 263 /// 264 /// - `pfm`: 缺页异常信息 265 /// - `mapper`: 页表映射器 266 /// 267 /// ## 返回值 268 /// - VmFaultReason: 页面错误处理信息标志 269 #[allow(dead_code, unused_variables)] 270 pub unsafe fn do_cow_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 271 panic!( 272 "do_cow_fault has not yet been implemented, 273 fault message: {:?}, 274 pid: {}\n", 275 pfm, 276 crate::process::ProcessManager::current_pid().data() 277 ); 278 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_cow_fault 279 } 280 281 /// 处理文件映射页的缺页异常 282 /// ## 参数 283 /// 284 /// - `pfm`: 缺页异常信息 285 /// - `mapper`: 页表映射器 286 /// 287 /// ## 返回值 288 /// - VmFaultReason: 页面错误处理信息标志 289 #[allow(dead_code, unused_variables)] 290 pub unsafe fn do_read_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 291 panic!( 292 "do_read_fault has not yet been implemented, 293 fault message: {:?}, 294 pid: {}\n", 295 pfm, 296 crate::process::ProcessManager::current_pid().data() 297 ); 298 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_read_fault 299 } 300 301 /// 处理对共享文件映射区写入引起的缺页 302 /// ## 参数 303 /// 304 /// - `pfm`: 缺页异常信息 305 /// - `mapper`: 页表映射器 306 /// 307 /// ## 返回值 308 /// - VmFaultReason: 页面错误处理信息标志 309 #[allow(dead_code, unused_variables)] 310 pub unsafe fn do_shared_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 311 panic!( 312 "do_shared_fault has not yet been implemented, 313 fault message: {:?}, 314 pid: {}\n", 315 pfm, 316 crate::process::ProcessManager::current_pid().data() 317 ); 318 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_shared_fault 319 } 320 321 /// 处理被置换页面的缺页异常 322 /// ## 参数 323 /// 324 /// - `pfm`: 缺页异常信息 325 /// - `mapper`: 页表映射器 326 /// 327 /// ## 返回值 328 /// - VmFaultReason: 页面错误处理信息标志 329 #[allow(unused_variables)] 330 pub unsafe fn do_swap_page(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 331 panic!( 332 "do_swap_page has not yet been implemented, 333 fault message: {:?}, 334 pid: {}\n", 335 pfm, 336 crate::process::ProcessManager::current_pid().data() 337 ); 338 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_swap_page 339 } 340 341 /// 处理NUMA的缺页异常 342 /// ## 参数 343 /// 344 /// - `pfm`: 缺页异常信息 345 /// - `mapper`: 页表映射器 346 /// 347 /// ## 返回值 348 /// - VmFaultReason: 页面错误处理信息标志 349 #[allow(unused_variables)] 350 pub unsafe fn do_numa_page(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 351 panic!( 352 "do_numa_page has not yet been implemented, 353 fault message: {:?}, 354 pid: {}\n", 355 pfm, 356 crate::process::ProcessManager::current_pid().data() 357 ); 358 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_numa_page 359 } 360 361 /// 处理写保护页面的写保护异常 362 /// ## 参数 363 /// 364 /// - `pfm`: 缺页异常信息 365 /// - `mapper`: 页表映射器 366 /// 367 /// ## 返回值 368 /// - VmFaultReason: 页面错误处理信息标志 369 pub unsafe fn do_wp_page(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason { 370 let address = pfm.address_aligned_down(); 371 let vma = pfm.vma.clone(); 372 let old_paddr = mapper.translate(address).unwrap().0; 373 let mut page_manager = page_manager_lock_irqsave(); 374 let map_count = page_manager.get_mut(&old_paddr).map_count(); 375 drop(page_manager); 376 377 let mut entry = mapper.get_entry(address, 0).unwrap(); 378 let new_flags = entry.flags().set_write(true); 379 380 if map_count == 1 { 381 let table = mapper.get_table(address, 0).unwrap(); 382 let i = table.index_of(address).unwrap(); 383 entry.set_flags(new_flags); 384 table.set_entry(i, entry); 385 VmFaultReason::VM_FAULT_COMPLETED 386 } else if let Some(flush) = mapper.map(address, new_flags) { 387 let mut page_manager = page_manager_lock_irqsave(); 388 let old_page = page_manager.get_mut(&old_paddr); 389 old_page.remove_vma(&vma); 390 drop(page_manager); 391 392 flush.flush(); 393 let paddr = mapper.translate(address).unwrap().0; 394 let mut anon_vma_guard = page_manager_lock_irqsave(); 395 let page = anon_vma_guard.get_mut(&paddr); 396 page.insert_vma(vma.clone()); 397 398 (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping( 399 MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8, 400 MMArch::PAGE_SIZE, 401 ); 402 403 VmFaultReason::VM_FAULT_COMPLETED 404 } else { 405 VmFaultReason::VM_FAULT_OOM 406 } 407 } 408 } 409