From abfe9999f447c15d904b3c11f32d4a22a45470a0 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Mon, 1 Jul 2019 17:46:06 -0400 Subject: have fork() fail, not panic, if not enough phys mem --- kernel/vm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'kernel/vm.c') diff --git a/kernel/vm.c b/kernel/vm.c index 580669f..7d67464 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -273,7 +273,9 @@ uvmfree(pagetable_t pagetable, uint64 sz) // its memory into a child's page table. // Copies both the page table and the // physical memory. -void +// returns 0 on success, -1 on failure. +// frees any allocated pages on failure. +int uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) { pte_t *pte; @@ -289,10 +291,15 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) pa = PTE2PA(*pte); flags = PTE_FLAGS(*pte); if((mem = kalloc()) == 0) - panic("uvmcopy: kalloc failed"); + goto err; memmove(mem, (char*)pa, PGSIZE); mappages(new, i, PGSIZE, (uint64)mem, flags); } + return 0; + + err: + unmappages(new, 0, i, 1); + return -1; } // Copy from kernel to user. -- cgit v1.2.3 From 1540c8b15ac35de9027e60804a786d23703d383d Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Tue, 2 Jul 2019 11:04:35 -0400 Subject: COW tests --- kernel/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/vm.c') diff --git a/kernel/vm.c b/kernel/vm.c index 7d67464..d5ff594 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -97,8 +97,8 @@ walk(pagetable_t pagetable, uint64 va, int alloc) } // Look up a virtual address, return the physical address, -// Can only be used to look up user pages. // or 0 if not mapped. +// Can only be used to look up user pages. uint64 walkaddr(pagetable_t pagetable, uint64 va) { -- cgit v1.2.3 From f59c1bf1d82da4b445c1cff10c228ea55fa035d4 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Tue, 2 Jul 2019 11:45:06 -0400 Subject: try to continue from walk() failing to allocate a page-table page --- kernel/vm.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'kernel/vm.c') diff --git a/kernel/vm.c b/kernel/vm.c index d5ff594..bdb53c2 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -119,8 +119,9 @@ walkaddr(pagetable_t pagetable, uint64 va) // Create PTEs for virtual addresses starting at va that refer to // physical addresses starting at pa. va and size might not -// be page-aligned. -void +// be page-aligned. Returns 0 on success, -1 if walk() couldn't +// allocate a needed page-table page. +int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) { uint64 a, last; @@ -130,7 +131,7 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) last = PGROUNDDOWN(va + size - 1); for(;;){ if((pte = walk(pagetable, a, 1)) == 0) - panic("mappages: walk"); + return -1; if(*pte & PTE_V) panic("remap"); *pte = PA2PTE(pa) | perm | PTE_V; @@ -139,6 +140,7 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) a += PGSIZE; pa += PGSIZE; } + return 0; } // Remove mappings from a page table. The mappings in @@ -222,7 +224,11 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) return 0; } memset(mem, 0, PGSIZE); - mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U); + if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){ + kfree(mem); + uvmdealloc(pagetable, a, oldsz); + return 0; + } } return newsz; } @@ -293,7 +299,10 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) if((mem = kalloc()) == 0) goto err; memmove(mem, (char*)pa, PGSIZE); - mappages(new, i, PGSIZE, (uint64)mem, flags); + if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){ + kfree(mem); + goto err; + } } return 0; -- cgit v1.2.3