kernel/arch/x86_64/interrupts/exceptions/
_14_page_fault.rs1use crate::arch::x86_64::mm::vmm::page_type::PageType;
7use crate::lib::addr::VirtAddr;
8use crate::lib::panic::kernel_panic;
9use crate::lib::panic_codes::PanicCode;
10use crate::lib::types::fmt_buffer::FmtBuffer;
11use crate::mm::pmm::FRAME_SIZE;
12use crate::mm::vmm::traits::VmmPaging;
13use crate::mm::vmm::Vmm;
14use crate::state::kstate::KSTATE;
15use core::fmt::Write;
16use x86_64::registers::control::Cr2;
17use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
18
19pub extern "x86-interrupt" fn handler(
21 isf: InterruptStackFrame,
22 error_code: PageFaultErrorCode
23) {
24 let faulting_virt = VirtAddr::new(Cr2::read_raw());
25
26 if error_code.contains(PageFaultErrorCode::USER_MODE) {
27 handle_user_pf(faulting_virt);
28 } else {
29 handle_kernel_pf(isf, error_code, faulting_virt);
30 }
31}
32
33#[inline(always)]
35fn handle_kernel_pf(
36 isf: InterruptStackFrame,
37 error_code: PageFaultErrorCode,
38 faulting_virt: VirtAddr
39) {
40 let addr_space = unsafe { KSTATE.mm.kernel_addr_space().lock() };
43 let vma = addr_space.find_vma(faulting_virt).unwrap_or_else(
44 || kernel_pf_panic(
45 "Could not find VMA to map a page for",
46 &isf, error_code, faulting_virt
47 )
48 );
49
50 let flags = vma.flags;
51 let page_ptr = addr_space.page_ptr();
52 drop(addr_space);
53
54 let mut pmm = unsafe { KSTATE.mm.pmm().lock() };
57 let frame = pmm.alloc_frame().unwrap_or_else(
58 || kernel_pf_panic(
59 "Could not map a new page, out of memory",
60 &isf, error_code, faulting_virt
61 )
62 );
63
64 unsafe {
67 if Vmm::map_page(
68 &mut pmm,
69 page_ptr,
70 faulting_virt.align_down(FRAME_SIZE),
71 frame,
72 PageType::Normal,
73 Vmm::vma_flags_to_page_flags(flags)
74 ).is_err() {
75 kernel_panic(
76 PanicCode::OutOfMemory,
77 "Could not lazy-map a page, out of memory"
78 );
79 }
80 }
81}
82
83#[inline(always)]
84fn handle_user_pf(
85 faulting_virt: VirtAddr
86) {
87 todo!();
88}
89
90
91#[inline(always)]
92fn kernel_pf_panic(
93 panic_message: &str,
94 isf: &InterruptStackFrame,
95 error_code: PageFaultErrorCode,
96 faulting_virt: VirtAddr
97) -> ! {
98 let mut fmt_buffer = FmtBuffer::<512>::new();
99 let _ = write!(
100 &mut fmt_buffer,
101 "{}\n\nCR2: {:x}\nError Code: {:?}\n\n{:#?}",
102 panic_message, faulting_virt, error_code, isf
103 );
104 kernel_panic(
105 PanicCode::PageFault,
106 fmt_buffer.as_str(),
107 );
108}