summaryrefslogtreecommitdiff
path: root/src/kernel/mm/vm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/mm/vm.cc')
-rw-r--r--src/kernel/mm/vm.cc29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc
index 29e9eb7..41d1aa1 100644
--- a/src/kernel/mm/vm.cc
+++ b/src/kernel/mm/vm.cc
@@ -261,6 +261,8 @@ namespace VM
return 0;
}
+ int handle_cow_fault(uint64 *pagetable, uint64 va);
+
int copyout(uint64 *pagetable, uint64 dstva, char *src, uint64 len)
{
uint64 n, va0, pa0;
@@ -273,6 +275,17 @@ namespace VM
if (pte == nullptr || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0)
return -1;
+ // Note: Maybe a bug
+ if (*pte & PTE_COW)
+ {
+ if (handle_cow_fault(pagetable, va0) < 0)
+ return -1;
+ // Re-walk because handle_cow_fault replaced the page mapping
+ pte = walk(pagetable, va0, 0);
+ if (pte == nullptr || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0)
+ return -1;
+ }
+
pa0 = PTE2PA(*pte);
n = PGSIZE - (dstva - va0);
if (n > len)
@@ -419,4 +432,20 @@ namespace VM
sfence_vma();
Drivers::uart_puts("[Boot] MMU ENABLED! Using virtual addresses.\n");
}
+
+ uint64 walkaddr(uint64 *pagetable, uint64 va)
+ {
+ uint64 *pte;
+ uint64 pa;
+
+ if (va >= MAXVA)
+ return 0;
+
+ pte = walk(pagetable, va, 0);
+ if (pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0)
+ return 0;
+
+ pa = PTE2PA(*pte);
+ return pa;
+ }
} \ No newline at end of file