1 #include <arch/x86/interrupts.h>
2 #include <lunaix/common.h>
3 #include <lunaix/mm/mm.h>
4 #include <lunaix/mm/pmm.h>
5 #include <lunaix/mm/region.h>
6 #include <lunaix/mm/vmm.h>
7 #include <lunaix/sched.h>
8 #include <lunaix/status.h>
9 #include <lunaix/syslog.h>
12 kprintf(const char* fmt, ...)
16 __kprintf("PFAULT", fmt, args);
21 __print_panic_msg(const char* msg, const isr_param* param);
24 intr_routine_page_fault(const isr_param* param)
26 uintptr_t ptr = cpu_rcr2();
32 if (!vmm_lookup(ptr, &mapping)) {
36 if (!SEL_RPL(param->cs)) {
38 if (do_kernel(&mapping)) {
44 struct mm_region* hit_region = region_get(&__current->mm.regions, ptr);
51 x86_pte_t* pte = PTE_MOUNTED(PD_REFERENCED, ptr >> 12);
52 if (*pte & PG_PRESENT) {
53 if ((hit_region->attr & REGION_PERM_MASK) ==
54 (REGION_RSHARED | REGION_READ)) {
55 // normal page fault, do COW
58 (uintptr_t)vmm_dup_page(__current->pid, PG_ENTRY_ADDR(*pte));
59 pmm_free_page(__current->pid, *pte & ~0xFFF);
60 *pte = (*pte & 0xFFF) | pa | PG_WRITE;
63 // impossible cases or accessing privileged page
71 uintptr_t loc = *pte & ~0xfff;
72 // a writable page, not present, pte attr is not null
73 // and no indication of cached page -> a new page need to be alloc
74 if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) {
76 uintptr_t pa = pmm_alloc_page(__current->pid, 0);
77 *pte = *pte | pa | PG_PRESENT;
80 // page not present, bring it from disk or somewhere else
81 __print_panic_msg("WIP page fault route", param);
86 kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n",
91 terminate_proc(LXSEGFAULT);
96 do_kernel(v_mapping* mapping)
98 uintptr_t addr = mapping->va;
99 if (addr >= KHEAP_START && addr < PROC_START) {
100 // This is kernel heap page
101 uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
102 *mapping->pte = (*mapping->pte & 0xfff) | pa | PG_PRESENT;
103 cpu_invplg(mapping->pte);