feat: No more kernel page table switching upon interrupt.
[lunaix-os.git] / lunaix-os / kernel / asm / x86 / pfault.c
index f07c74faa54cc4f5afdaa4acd44a88f97195b4de..c16385a892c05a487b50465fbbbcea48112be00a 100644 (file)
@@ -27,10 +27,9 @@ intr_routine_page_fault (const isr_param* param)
         goto segv_term;
     }
 
-    if (param->eip == ptr && !(hit_region->attr & REGION_EXEC)) {
-        // Attempt to execute non-executable page
-        goto segv_term;
-    }
+    // if (param->eip == ptr && !(hit_region->attr & REGION_EXEC)) {
+    //     goto segv_term;
+    // }
 
     x86_pte_t* pte = CURPROC_PTE(ptr >> 12);
     if (*pte & PG_PRESENT) {
@@ -41,22 +40,27 @@ intr_routine_page_fault (const isr_param* param)
                 *pte = (*pte & 0xFFF) | pa | PG_WRITE;
                 return;
         }
-        else {
-            // impossible cases or accessing privileged page
-            goto segv_term;
-        }
-    } else {
-        if (!(*pte)) {
-            // Invalid location
-            goto segv_term;
-        }
-        // page not present, bring it from disk or somewhere else
-        __print_panic_msg("WIP page fault route", param);
-        while (1);
+        // impossible cases or accessing privileged page
+        goto segv_term;
+    }
+
+    if (!(*pte)) {
+        // Invalid location
+        goto segv_term;
+    }
+    uintptr_t loc = *pte & ~0xfff;
+    // a writable page, not present, pte attr is not null and no indication of cached page -> a new page need to be alloc
+    if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) {
+        uintptr_t pa = pmm_alloc_page(__current->pid, 0);
+        *pte = *pte | pa | PG_PRESENT;
+        return;
     }
+    // page not present, bring it from disk or somewhere else
+    __print_panic_msg("WIP page fault route", param);
+    while (1);
 
 segv_term:
-    kprintf(KERROR "(pid: %d) Segmentation fault on %p\n", __current->pid, ptr);
+    kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n", __current->pid, ptr, param->cs, param->eip);
     terminate_proc(LXSEGFAULT);
     // should not reach
 }
\ No newline at end of file