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