fault.rs 23 KB

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