]> git.corax.cc Git - corax/commitdiff
Print the affected page directory and page table entries, when a page fault occurs...
authorMatthias Kruk <m@m10k.eu>
Tue, 10 Dec 2019 08:46:37 +0000 (17:46 +0900)
committerMatthias Kruk <m@m10k.eu>
Tue, 10 Dec 2019 08:46:37 +0000 (17:46 +0900)
kernel/arch/heap.c
kernel/arch/interrupt.c
kernel/arch/paging.c

index 0a855349f739e2b80ed7bb29e8404216bf5824ad..8a248ae03377cea82577726f53388ebfdc8ede64 100644 (file)
@@ -30,7 +30,7 @@ struct heap_node {
        u32_t hn_flags;
 };
 
-static struct {
+struct {
        void *h_base;
        u32_t h_size;
        u32_t h_free;
index 728c4ce7f2927b4c9785bfa7192fb7bb49383c74..1ad7d04b696c4ccff8f832a0ae18082480eff046 100644 (file)
@@ -25,6 +25,8 @@
 #include "cpu.h"
 #include "defs.h"
 
+extern void pg_fault_debug(pg_dir_t*, void*);
+
 void sched_tick(void);
 extern int sys_cxnet(long, long, long, long, long, long, long);
 extern int sys_cxipc(long, long, long);
@@ -139,9 +141,14 @@ void _exc_handle(stack_frame_t ctx)
 
     if(ctx.intn == EXC_PAGEFAULT) {
         u32_t cr2;
+               pg_dir_t *pd;
 
         asm volatile("movl %%cr2, %%eax; movl %%eax, %0" : "=r"(cr2));
         dbg_printf("Page fault address: 0x%08x\n", cr2);
+
+               if(process_get_pagedir(cproc, &pd) == 0) {
+                       pg_fault_debug(pd, (void*)cr2);
+               }
     }
 
     PANIC("Unhandled exception");
index 978cf541a351b3f1a59e673e39b0a9941899cd4f..fd6460787eee4bfb5159790ec87b6ae1deb048d5 100644 (file)
@@ -887,6 +887,10 @@ int _clone_kernel_region(pg_dir_t *kdir, region_t *reg, void *data)
        dir = (pg_dir_t*)data;
 
        switch(reg->reg_type) {
+       case REGION_DATA:
+               ret_val = pg_dir_clone_region(dir, kdir, reg);
+               break;
+
        case REGION_TEXT:
        case REGION_RODATA:
        case REGION_HEAP:
@@ -895,7 +899,6 @@ int _clone_kernel_region(pg_dir_t *kdir, region_t *reg, void *data)
                 * directory since they cannot be modified or removed anyways.
                 */
        case REGION_BSS:
-       case REGION_DATA:
                /*
                 * The way the interrupt handling is currently implemented, accesses to the
                 * _cpu structure and _kernel_cr3 are made within the context (i.e. using
@@ -1090,6 +1093,11 @@ static int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr,
                        pd->pt_entries[pde] |= PAGE_ATTR_USER;
                }
 
+               /* also make sure the page table is writable, if necessary */
+               if(flags & PAGE_ATTR_WRITABLE) {
+                       pd->pt_entries[pde] |= PAGE_ATTR_WRITABLE;
+               }
+
                if(pt->pt_entries[pte] & PAGE_ATTR_PRESENT) {
                        ret_val = -EALREADY;
                        break;
@@ -1098,7 +1106,6 @@ static int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr,
                /* allocate new frames if caller didn't specify a physical address */
                if(!paddr) {
                        pt->pt_entries[pte] = (u32_t)pg_frame_alloc_end();
-                       dbg_printf("Allocating page: %04u - 0x%08x\n", pte, pt->pt_entries[pte]);
                } else {
                        pt->pt_entries[pte] = paddr;
                        paddr += PAGE_SIZE;
@@ -1309,7 +1316,7 @@ int pg_dir_clone_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg)
 
        /* attempt to map the region */
        ret_val = pg_dir_map(dpd, NULL, reg->reg_base,
-                                                reg->reg_size, reg->reg_attrs);
+                                                reg->reg_size, reg->reg_attrs | PAGE_ATTR_USER);
 
        if(ret_val < 0) {
                goto gtfo;
@@ -1323,7 +1330,7 @@ int pg_dir_clone_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg)
        if(ret_val >= 0) {
                /* also keep track of the region */
                ret_val = _pg_dir_add_region(dpd, reg->reg_base, reg->reg_size,
-                                                                        reg->reg_type, reg->reg_attrs, reg->reg_flags);
+                                                                        reg->reg_type, reg->reg_attrs, reg->reg_flags | PAGE_ATTR_USER);
        }
 
        if(ret_val < 0) {
@@ -1509,3 +1516,37 @@ void* pg_dir_sbrk(pg_dir_t *pd, i32_t increment)
 
        return(ret_val);
 }
+
+void pg_fault_debug(pg_dir_t *pdir, void *addr)
+{
+       u64_t pde;
+       u64_t pte;
+       u32_t pdi;
+       u32_t pti;
+
+       switch(_pg_flags & PG_MODE_MASK) {
+       case PG_MODE_LEGACY:
+               pdi = ((u32_t)addr & 0xffc00000) >> 22;
+               pti = ((u32_t)addr & 0x003ff000) >> 12;
+
+               pde = ((page_table_t*)pdir->pd_base)->pt_entries[pdi];
+
+               dbg_printf("pdir[%03u]      = 0x%08x\n", pdi, (u32_t)pde);
+
+               if(!(pde & PAGE_ATTR_SIZE)) {
+                       pte = ((page_table_t*)(pde & 0xfffff000))->pt_entries[pti];
+                       dbg_printf("pdir[%03u][%03u] = 0x%08x\n", pdi, pti, (u32_t)pte);
+               }
+
+               break;
+
+       case PG_MODE_PAE:
+               break;
+
+       default:
+               /* not handled yet */
+               break;
+       }
+
+       return;
+}