fault.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. use alloc::boxed::Box;
  2. use core::{
  3. alloc::Layout,
  4. cmp::{max, min},
  5. intrinsics::unlikely,
  6. panic,
  7. };
  8. use alloc::sync::Arc;
  9. use crate::{
  10. arch::{mm::PageMapper, MMArch},
  11. libs::align::align_down,
  12. mm::{
  13. page::{page_manager_lock_irqsave, EntryFlags},
  14. ucontext::LockedVMA,
  15. VirtAddr, VmFaultReason, VmFlags,
  16. },
  17. process::{ProcessManager, ProcessState},
  18. };
  19. use crate::mm::MemoryManagementArch;
  20. use super::page::{Page, PageFlags};
  21. bitflags! {
  22. pub struct FaultFlags: u64{
  23. const FAULT_FLAG_WRITE = 1 << 0;
  24. const FAULT_FLAG_MKWRITE = 1 << 1;
  25. const FAULT_FLAG_ALLOW_RETRY = 1 << 2;
  26. const FAULT_FLAG_RETRY_NOWAIT = 1 << 3;
  27. const FAULT_FLAG_KILLABLE = 1 << 4;
  28. const FAULT_FLAG_TRIED = 1 << 5;
  29. const FAULT_FLAG_USER = 1 << 6;
  30. const FAULT_FLAG_REMOTE = 1 << 7;
  31. const FAULT_FLAG_INSTRUCTION = 1 << 8;
  32. const FAULT_FLAG_INTERRUPTIBLE =1 << 9;
  33. const FAULT_FLAG_UNSHARE = 1 << 10;
  34. const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11;
  35. const FAULT_FLAG_VMA_LOCK = 1 << 12;
  36. }
  37. }
  38. /// # 缺页异常信息结构体
  39. /// 包含了页面错误处理的相关信息,例如出错的地址、VMA等
  40. #[derive(Debug)]
  41. pub struct PageFaultMessage<'a> {
  42. /// 产生缺页的VMA结构体
  43. vma: Arc<LockedVMA>,
  44. /// 缺页地址
  45. address: VirtAddr,
  46. /// 异常处理标志
  47. flags: FaultFlags,
  48. /// 页表映射器
  49. mapper: &'a mut PageMapper,
  50. /// 缺页的文件页在文件中的偏移页号
  51. file_pgoff: Option<usize>,
  52. /// 缺页对应PageCache中的文件页
  53. page: Option<Arc<Page>>,
  54. /// 写时拷贝需要的页面
  55. cow_page: Option<Arc<Page>>,
  56. }
  57. impl<'a> PageFaultMessage<'a> {
  58. pub fn new(
  59. vma: Arc<LockedVMA>,
  60. address: VirtAddr,
  61. flags: FaultFlags,
  62. mapper: &'a mut PageMapper,
  63. ) -> Self {
  64. let guard = vma.lock_irqsave();
  65. let file_pgoff = guard.file_page_offset().map(|file_page_offset| {
  66. ((address - guard.region().start()) >> MMArch::PAGE_SHIFT) + file_page_offset
  67. });
  68. Self {
  69. vma: vma.clone(),
  70. address: VirtAddr::new(crate::libs::align::page_align_down(address.data())),
  71. flags,
  72. file_pgoff,
  73. page: None,
  74. mapper,
  75. cow_page: None,
  76. }
  77. }
  78. #[inline(always)]
  79. #[allow(dead_code)]
  80. pub fn vma(&self) -> Arc<LockedVMA> {
  81. self.vma.clone()
  82. }
  83. #[inline(always)]
  84. #[allow(dead_code)]
  85. pub fn address(&self) -> VirtAddr {
  86. self.address
  87. }
  88. #[inline(always)]
  89. #[allow(dead_code)]
  90. pub fn address_aligned_down(&self) -> VirtAddr {
  91. VirtAddr::new(crate::libs::align::page_align_down(self.address.data()))
  92. }
  93. #[inline(always)]
  94. #[allow(dead_code)]
  95. pub fn flags(&self) -> FaultFlags {
  96. self.flags
  97. }
  98. }
  99. /// 缺页中断处理结构体
  100. pub struct PageFaultHandler;
  101. impl PageFaultHandler {
  102. /// 处理缺页异常
  103. /// ## 参数
  104. ///
  105. /// - `pfm`: 缺页异常信息
  106. /// - `mapper`: 页表映射器
  107. ///
  108. /// ## 返回值
  109. /// - VmFaultReason: 页面错误处理信息标志
  110. pub unsafe fn handle_mm_fault(mut pfm: PageFaultMessage) -> VmFaultReason {
  111. let flags = pfm.flags();
  112. let vma = pfm.vma();
  113. let current_pcb = ProcessManager::current_pcb();
  114. let mut guard = current_pcb.sched_info().inner_lock_write_irqsave();
  115. guard.set_state(ProcessState::Runnable);
  116. if !MMArch::vma_access_permitted(
  117. vma.clone(),
  118. flags.contains(FaultFlags::FAULT_FLAG_WRITE),
  119. flags.contains(FaultFlags::FAULT_FLAG_INSTRUCTION),
  120. flags.contains(FaultFlags::FAULT_FLAG_REMOTE),
  121. ) {
  122. return VmFaultReason::VM_FAULT_SIGSEGV;
  123. }
  124. let guard = vma.lock_irqsave();
  125. let vm_flags = *guard.vm_flags();
  126. drop(guard);
  127. if unlikely(vm_flags.contains(VmFlags::VM_HUGETLB)) {
  128. //TODO: 添加handle_hugetlb_fault处理大页缺页异常
  129. } else {
  130. Self::handle_normal_fault(&mut pfm);
  131. }
  132. VmFaultReason::VM_FAULT_COMPLETED
  133. }
  134. /// 处理普通页缺页异常
  135. /// ## 参数
  136. ///
  137. /// - `pfm`: 缺页异常信息
  138. /// - `mapper`: 页表映射器
  139. ///
  140. /// ## 返回值
  141. /// - VmFaultReason: 页面错误处理信息标志
  142. pub unsafe fn handle_normal_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  143. let address = pfm.address_aligned_down();
  144. let vma = pfm.vma.clone();
  145. let mapper = &mut pfm.mapper;
  146. if mapper.get_entry(address, 3).is_none() {
  147. mapper
  148. .allocate_table(address, 2)
  149. .expect("failed to allocate PUD table");
  150. }
  151. let page_flags = vma.lock_irqsave().flags();
  152. for level in 2..=3 {
  153. let level = MMArch::PAGE_LEVELS - level;
  154. if mapper.get_entry(address, level).is_none() {
  155. if vma.is_hugepage() {
  156. if vma.is_anonymous() {
  157. mapper.map_huge_page(address, page_flags);
  158. }
  159. } else if mapper.allocate_table(address, level - 1).is_none() {
  160. return VmFaultReason::VM_FAULT_OOM;
  161. }
  162. }
  163. }
  164. Self::handle_pte_fault(pfm)
  165. }
  166. /// 处理页表项异常
  167. /// ## 参数
  168. ///
  169. /// - `pfm`: 缺页异常信息
  170. /// - `mapper`: 页表映射器
  171. ///
  172. /// ## 返回值
  173. /// - VmFaultReason: 页面错误处理信息标志
  174. pub unsafe fn handle_pte_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  175. let address = pfm.address_aligned_down();
  176. let flags = pfm.flags;
  177. let vma = pfm.vma.clone();
  178. let mut ret = VmFaultReason::VM_FAULT_COMPLETED;
  179. let mapper = &pfm.mapper;
  180. // pte存在
  181. if let Some(mut entry) = mapper.get_entry(address, 0) {
  182. if !entry.present() {
  183. ret = Self::do_swap_page(pfm);
  184. }
  185. if entry.protnone() && vma.is_accessible() {
  186. ret = Self::do_numa_page(pfm);
  187. }
  188. if flags.intersects(FaultFlags::FAULT_FLAG_WRITE | FaultFlags::FAULT_FLAG_UNSHARE) {
  189. if !entry.write() {
  190. ret = Self::do_wp_page(pfm);
  191. } else {
  192. entry.set_flags(EntryFlags::from_data(MMArch::ENTRY_FLAG_DIRTY));
  193. }
  194. }
  195. } else if vma.is_anonymous() {
  196. ret = Self::do_anonymous_page(pfm);
  197. } else {
  198. ret = Self::do_fault(pfm);
  199. }
  200. vma.lock_irqsave().set_mapped(true);
  201. return ret;
  202. }
  203. /// 处理匿名映射页缺页异常
  204. /// ## 参数
  205. ///
  206. /// - `pfm`: 缺页异常信息
  207. /// - `mapper`: 页表映射器
  208. ///
  209. /// ## 返回值
  210. /// - VmFaultReason: 页面错误处理信息标志
  211. pub unsafe fn do_anonymous_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
  212. let address = pfm.address_aligned_down();
  213. let vma = pfm.vma.clone();
  214. let guard = vma.lock_irqsave();
  215. let mapper = &mut pfm.mapper;
  216. if let Some(flush) = mapper.map(address, guard.flags()) {
  217. flush.flush();
  218. crate::debug::klog::mm::mm_debug_log(
  219. klog_types::AllocatorLogType::LazyAlloc(klog_types::AllocLogItem::new(
  220. Layout::from_size_align(MMArch::PAGE_SIZE, MMArch::PAGE_SIZE).unwrap(),
  221. Some(address.data()),
  222. Some(mapper.translate(address).unwrap().0.data()),
  223. )),
  224. klog_types::LogSource::Buddy,
  225. );
  226. let paddr = mapper.translate(address).unwrap().0;
  227. let mut page_manager_guard = page_manager_lock_irqsave();
  228. let page = page_manager_guard.get_unwrap(&paddr);
  229. page.write_irqsave().insert_vma(vma.clone());
  230. VmFaultReason::VM_FAULT_COMPLETED
  231. } else {
  232. VmFaultReason::VM_FAULT_OOM
  233. }
  234. }
  235. /// 处理文件映射页的缺页异常
  236. /// ## 参数
  237. ///
  238. /// - `pfm`: 缺页异常信息
  239. /// - `mapper`: 页表映射器
  240. ///
  241. /// ## 返回值
  242. /// - VmFaultReason: 页面错误处理信息标志
  243. pub unsafe fn do_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  244. if !pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE) {
  245. Self::do_read_fault(pfm)
  246. } else if !pfm
  247. .vma()
  248. .lock_irqsave()
  249. .vm_flags()
  250. .contains(VmFlags::VM_SHARED)
  251. {
  252. Self::do_cow_fault(pfm)
  253. } else {
  254. Self::do_shared_fault(pfm)
  255. }
  256. }
  257. /// 处理私有文件映射的写时复制
  258. /// ## 参数
  259. ///
  260. /// - `pfm`: 缺页异常信息
  261. /// - `mapper`: 页表映射器
  262. ///
  263. /// ## 返回值
  264. /// - VmFaultReason: 页面错误处理信息标志
  265. pub unsafe fn do_cow_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  266. let mut ret = Self::filemap_fault(pfm);
  267. if unlikely(ret.intersects(
  268. VmFaultReason::VM_FAULT_ERROR
  269. | VmFaultReason::VM_FAULT_NOPAGE
  270. | VmFaultReason::VM_FAULT_RETRY
  271. | VmFaultReason::VM_FAULT_DONE_COW,
  272. )) {
  273. return ret;
  274. }
  275. let cache_page = pfm.page.clone().unwrap();
  276. let mapper = &mut pfm.mapper;
  277. let mut page_manager_guard = page_manager_lock_irqsave();
  278. if let Ok(page) =
  279. page_manager_guard.copy_page(&cache_page.phys_address(), mapper.allocator_mut())
  280. {
  281. pfm.cow_page = Some(page.clone());
  282. } else {
  283. return VmFaultReason::VM_FAULT_OOM;
  284. }
  285. ret = ret.union(Self::finish_fault(pfm));
  286. ret
  287. }
  288. /// 处理文件映射页的缺页异常
  289. /// ## 参数
  290. ///
  291. /// - `pfm`: 缺页异常信息
  292. /// - `mapper`: 页表映射器
  293. ///
  294. /// ## 返回值
  295. /// - VmFaultReason: 页面错误处理信息标志
  296. pub unsafe fn do_read_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  297. let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs();
  298. let mut ret = Self::do_fault_around(pfm);
  299. if !ret.is_empty() {
  300. return ret;
  301. }
  302. ret = fs.fault(pfm);
  303. ret = ret.union(Self::finish_fault(pfm));
  304. ret
  305. }
  306. /// 处理对共享文件映射区写入引起的缺页
  307. /// ## 参数
  308. ///
  309. /// - `pfm`: 缺页异常信息
  310. /// - `mapper`: 页表映射器
  311. ///
  312. /// ## 返回值
  313. /// - VmFaultReason: 页面错误处理信息标志
  314. pub unsafe fn do_shared_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  315. let mut ret = Self::filemap_fault(pfm);
  316. let cache_page = pfm.page.clone().expect("no cache_page in PageFaultMessage");
  317. // 将pagecache页设为脏页,以便回收时能够回写
  318. cache_page.write_irqsave().add_flags(PageFlags::PG_DIRTY);
  319. ret = ret.union(Self::finish_fault(pfm));
  320. ret
  321. }
  322. /// 处理被置换页面的缺页异常
  323. /// ## 参数
  324. ///
  325. /// - `pfm`: 缺页异常信息
  326. /// - `mapper`: 页表映射器
  327. ///
  328. /// ## 返回值
  329. /// - VmFaultReason: 页面错误处理信息标志
  330. #[allow(unused_variables)]
  331. pub unsafe fn do_swap_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
  332. panic!(
  333. "do_swap_page has not yet been implemented,
  334. fault message: {:?},
  335. pid: {}\n",
  336. pfm,
  337. crate::process::ProcessManager::current_pid().data()
  338. );
  339. // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_swap_page
  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: &mut PageFaultMessage) -> 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. /// - `pfm`: 缺页异常信息
  364. /// - `mapper`: 页表映射器
  365. ///
  366. /// ## 返回值
  367. /// - VmFaultReason: 页面错误处理信息标志
  368. pub unsafe fn do_wp_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
  369. let address = pfm.address_aligned_down();
  370. let vma = pfm.vma.clone();
  371. let mapper = &mut pfm.mapper;
  372. let old_paddr = mapper.translate(address).unwrap().0;
  373. let mut page_manager = page_manager_lock_irqsave();
  374. let old_page = page_manager.get_unwrap(&old_paddr);
  375. let map_count = old_page.read_irqsave().map_count();
  376. drop(page_manager);
  377. let mut entry = mapper.get_entry(address, 0).unwrap();
  378. let new_flags = entry.flags().set_write(true).set_dirty(true);
  379. if vma.lock().vm_flags().contains(VmFlags::VM_SHARED) {
  380. // 共享映射,直接修改页表项保护位,标记为脏页
  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. old_page.write_irqsave().add_flags(PageFlags::PG_DIRTY);
  386. VmFaultReason::VM_FAULT_COMPLETED
  387. } else if vma.is_anonymous() {
  388. // 私有匿名映射,根据引用计数判断是否拷贝页面
  389. if map_count == 1 {
  390. let table = mapper.get_table(address, 0).unwrap();
  391. let i = table.index_of(address).unwrap();
  392. entry.set_flags(new_flags);
  393. table.set_entry(i, entry);
  394. VmFaultReason::VM_FAULT_COMPLETED
  395. } else if let Some(flush) = mapper.map(address, new_flags) {
  396. let mut page_manager_guard = page_manager_lock_irqsave();
  397. let old_page = page_manager_guard.get_unwrap(&old_paddr);
  398. old_page.write_irqsave().remove_vma(&vma);
  399. // drop(page_manager_guard);
  400. flush.flush();
  401. let paddr = mapper.translate(address).unwrap().0;
  402. // let mut page_manager_guard = page_manager_lock_irqsave();
  403. let page = page_manager_guard.get_unwrap(&paddr);
  404. page.write_irqsave().insert_vma(vma.clone());
  405. (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
  406. MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
  407. MMArch::PAGE_SIZE,
  408. );
  409. VmFaultReason::VM_FAULT_COMPLETED
  410. } else {
  411. VmFaultReason::VM_FAULT_OOM
  412. }
  413. } else {
  414. // 私有文件映射,必须拷贝页面
  415. if let Some(flush) = mapper.map(address, new_flags) {
  416. let mut page_manager_guard = page_manager_lock_irqsave();
  417. let old_page = page_manager_guard.get_unwrap(&old_paddr);
  418. old_page.write_irqsave().remove_vma(&vma);
  419. // drop(page_manager_guard);
  420. flush.flush();
  421. let paddr = mapper.translate(address).unwrap().0;
  422. // let mut page_manager_guard = page_manager_lock_irqsave();
  423. let page = page_manager_guard.get_unwrap(&paddr);
  424. page.write_irqsave().insert_vma(vma.clone());
  425. (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
  426. MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
  427. MMArch::PAGE_SIZE,
  428. );
  429. VmFaultReason::VM_FAULT_COMPLETED
  430. } else {
  431. VmFaultReason::VM_FAULT_OOM
  432. }
  433. }
  434. }
  435. /// 缺页附近页预读
  436. /// ## 参数
  437. ///
  438. /// - `pfm`: 缺页异常信息
  439. /// - `mapper`: 页表映射器
  440. ///
  441. /// ## 返回值
  442. /// - VmFaultReason: 页面错误处理信息标志
  443. pub unsafe fn do_fault_around(pfm: &mut PageFaultMessage) -> VmFaultReason {
  444. let vma = pfm.vma();
  445. let address = pfm.address();
  446. let mapper = &mut pfm.mapper;
  447. if mapper.get_table(address, 0).is_none() {
  448. mapper
  449. .allocate_table(address, 0)
  450. .expect("failed to allocate pte table");
  451. }
  452. let vma_guard = vma.lock_irqsave();
  453. let vma_region = *vma_guard.region();
  454. drop(vma_guard);
  455. // 缺页在VMA中的偏移量
  456. let vm_pgoff = (address - vma_region.start()) >> MMArch::PAGE_SHIFT;
  457. // 缺页在PTE中的偏移量
  458. let pte_pgoff = (address.data() >> MMArch::PAGE_SHIFT) & (1 << MMArch::PAGE_ENTRY_SHIFT);
  459. // 缺页在文件中的偏移量
  460. let file_pgoff = pfm.file_pgoff.expect("no file_pgoff");
  461. let vma_pages_count = (vma_region.end() - vma_region.start()) >> MMArch::PAGE_SHIFT;
  462. let fault_around_page_number = 16;
  463. // 开始位置不能超出当前pte和vma头部
  464. let from_pte = max(
  465. align_down(pte_pgoff, fault_around_page_number),
  466. pte_pgoff - min(vm_pgoff, pte_pgoff),
  467. );
  468. // pte结束位置不能超过:
  469. // 1.最大预读上限(默认16)
  470. // 2.最大pte(512)
  471. // 3.vma结束位置(pte_pgoff + (vma_pages_count - vm_pgoff)计算出vma结束页号对当前pte开头的偏移)
  472. let to_pte = min(
  473. from_pte + fault_around_page_number,
  474. min(
  475. 1 << MMArch::PAGE_SHIFT,
  476. pte_pgoff + (vma_pages_count - vm_pgoff),
  477. ),
  478. );
  479. // 预先分配pte页表(如果不存在)
  480. if mapper.get_table(address, 0).is_none() && mapper.allocate_table(address, 0).is_none() {
  481. return VmFaultReason::VM_FAULT_OOM;
  482. }
  483. let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs();
  484. // from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移,加上pfm.file_pgoff(缺失页在文件中的偏移)得出起始页在文件中的偏移,结束pte同理
  485. fs.map_pages(
  486. pfm,
  487. file_pgoff + (from_pte - pte_pgoff),
  488. file_pgoff + (to_pte - pte_pgoff),
  489. );
  490. VmFaultReason::empty()
  491. }
  492. /// 通用的VMA文件映射页面映射函数,将PageCache中的页面映射到进程空间
  493. /// ## 参数
  494. ///
  495. /// - `pfm`: 缺页异常信息
  496. /// - `mapper`: 页表映射器
  497. ///
  498. /// ## 返回值
  499. /// - VmFaultReason: 页面错误处理信息标志
  500. pub unsafe fn filemap_map_pages(
  501. pfm: &mut PageFaultMessage,
  502. start_pgoff: usize,
  503. end_pgoff: usize,
  504. ) -> VmFaultReason {
  505. let vma = pfm.vma();
  506. let vma_guard = vma.lock_irqsave();
  507. let file = vma_guard.vm_file().expect("no vm_file in vma");
  508. let page_cache = file.inode().page_cache().unwrap();
  509. let mapper = &mut pfm.mapper;
  510. // 起始页地址
  511. let addr = vma_guard.region().start
  512. + ((start_pgoff
  513. - vma_guard
  514. .file_page_offset()
  515. .expect("file_page_offset is none"))
  516. << MMArch::PAGE_SHIFT);
  517. for pgoff in start_pgoff..=end_pgoff {
  518. if let Some(page) = page_cache.lock_irqsave().get_page(pgoff) {
  519. let page_guard = page.read_irqsave();
  520. if page_guard.flags().contains(PageFlags::PG_UPTODATE) {
  521. let phys = page.phys_address();
  522. let address =
  523. VirtAddr::new(addr.data() + ((pgoff - start_pgoff) << MMArch::PAGE_SHIFT));
  524. mapper
  525. .map_phys(address, phys, vma_guard.flags())
  526. .unwrap()
  527. .flush();
  528. }
  529. }
  530. }
  531. VmFaultReason::empty()
  532. }
  533. /// 通用的VMA文件映射错误处理函数
  534. /// ## 参数
  535. ///
  536. /// - `pfm`: 缺页异常信息
  537. /// - `mapper`: 页表映射器
  538. ///
  539. /// ## 返回值
  540. /// - VmFaultReason: 页面错误处理信息标志
  541. pub unsafe fn filemap_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  542. let vma = pfm.vma();
  543. let vma_guard = vma.lock_irqsave();
  544. let file = vma_guard.vm_file().expect("no vm_file in vma");
  545. let page_cache = file.inode().page_cache().unwrap();
  546. let file_pgoff = pfm.file_pgoff.expect("no file_pgoff");
  547. let mut ret = VmFaultReason::empty();
  548. let page = page_cache.lock_irqsave().get_page(file_pgoff);
  549. if let Some(page) = page {
  550. // TODO 异步从磁盘中预读页面进PageCache
  551. // 直接将PageCache中的页面作为要映射的页面
  552. pfm.page = Some(page.clone());
  553. } else {
  554. // TODO 同步预读
  555. //涉及磁盘IO,返回标志为VM_FAULT_MAJOR
  556. ret = VmFaultReason::VM_FAULT_MAJOR;
  557. let mut buffer = Box::new([0u8; MMArch::PAGE_SIZE]);
  558. file.pread(
  559. file_pgoff * MMArch::PAGE_SIZE,
  560. MMArch::PAGE_SIZE,
  561. buffer.as_mut_slice(),
  562. )
  563. .expect("failed to read file to create pagecache page");
  564. drop(buffer);
  565. let page = page_cache.lock_irqsave().get_page(file_pgoff);
  566. pfm.page = page;
  567. }
  568. ret
  569. }
  570. /// 将文件页映射到缺页地址
  571. /// ## 参数
  572. ///
  573. /// - `pfm`: 缺页异常信息
  574. /// - `mapper`: 页表映射器
  575. ///
  576. /// ## 返回值
  577. /// - VmFaultReason: 页面错误处理信息标志
  578. pub unsafe fn finish_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
  579. let vma = pfm.vma();
  580. let vma_guard = vma.lock_irqsave();
  581. let flags = pfm.flags();
  582. let cache_page = pfm.page.clone();
  583. let cow_page = pfm.cow_page.clone();
  584. let address = pfm.address();
  585. let mapper = &mut pfm.mapper;
  586. let page_to_map = if flags.contains(FaultFlags::FAULT_FLAG_WRITE)
  587. && !vma_guard.vm_flags().contains(VmFlags::VM_SHARED)
  588. {
  589. // 私有文件映射的写时复制
  590. cow_page.expect("no cow_page in PageFaultMessage")
  591. } else {
  592. // 直接映射到PageCache
  593. cache_page.expect("no cache_page in PageFaultMessage")
  594. };
  595. let page_phys = page_to_map.phys_address();
  596. mapper.map_phys(address, page_phys, vma_guard.flags());
  597. page_to_map.write_irqsave().insert_vma(pfm.vma());
  598. VmFaultReason::VM_FAULT_COMPLETED
  599. }
  600. }