chore: make things more general
[lunaix-os.git] / lunaix-os / kernel / asm / x86 / pfault.c
index 9d5e1d1bdbe2bc10fab8514bec0fe71f6b915bb7..3ad640e9a0e84588bcb03e9324df3d7608b7ae8e 100644 (file)
@@ -20,6 +20,8 @@ kprintf(const char* fmt, ...)
 extern void
 __print_panic_msg(const char* msg, const isr_param* param);
 
+extern void __kernel_heap_start;
+
 void
 intr_routine_page_fault(const isr_param* param)
 {
@@ -28,7 +30,20 @@ intr_routine_page_fault(const isr_param* param)
         goto segv_term;
     }
 
-    struct mm_region* hit_region = region_get(__current, ptr);
+    v_mapping mapping;
+    if (!vmm_lookup(ptr, &mapping)) {
+        goto segv_term;
+    }
+
+    if (!SEL_RPL(param->cs)) {
+        // 如果是内核页错误……
+        if (do_kernel(&mapping)) {
+            return;
+        }
+        goto segv_term;
+    }
+
+    struct mm_region* hit_region = region_get(&__current->mm.regions, ptr);
 
     if (!hit_region) {
         // Into the void...
@@ -77,4 +92,22 @@ segv_term:
             param->eip);
     terminate_proc(LXSEGFAULT);
     // should not reach
+}
+
+int
+do_kernel(v_mapping* mapping)
+{
+    uintptr_t addr = mapping->va;
+    if (addr >= &__kernel_heap_start && addr < L2_BASE_VADDR) {
+        // This is kernel heap page
+        uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
+        *mapping->pte = (*mapping->pte & 0xfff) | pa | PG_PRESENT;
+        cpu_invplg(mapping->pte);
+        cpu_invplg(addr);
+        goto done;
+    }
+
+    return 0;
+done:
+    return 1;
 }
\ No newline at end of file