// COW pagefault handler #include "types.h" #include "riscv.h" #include "defs.h" int cow_handler(pagetable_t pagetable, uint64 va) { // you can't really write to rediculous pointers if(va >= MAXVA || PGROUNDDOWN(va) == 0) return -1; pte_t *pte = walk(pagetable, va, 0); if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0) return -1; if(*pte & PTE_C){ uint64 pa_orig = PTE2PA(*pte); uint64 pa_new = (uint64)kalloc(); if(pa_new == 0){ printf("cow pagefault: kalloc failed\n"); return -1; } // copy the page and add write permission memmove((void*)pa_new, (void*)pa_orig, PGSIZE); uint64 flags = (PTE_FLAGS(*pte) | PTE_W) & ~PTE_C; *pte = PA2PTE(pa_new) | flags; kfree((void*)pa_orig); } else if ((*pte & PTE_W) == 0) return -1; return 0; }