From 0c53a283ab746559a1f86a1c91a2150689b3fa0e Mon Sep 17 00:00:00 2001 From: foyoodo Date: Wed, 17 Mar 2021 21:47:10 +0800 Subject: [PATCH] Lab pgtbl: ukvmcopy --- kernel/defs.h | 3 ++ kernel/exec.c | 2 ++ kernel/proc.c | 11 ++++++++ kernel/vm.c | 76 +++++++++++++++++---------------------------------- 4 files changed, 41 insertions(+), 51 deletions(-) diff --git a/kernel/defs.h b/kernel/defs.h index 25e330f..567741c 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -173,6 +173,7 @@ uint64 uvmdealloc(pagetable_t, uint64, uint64); #ifdef SOL_COW #else int uvmcopy(pagetable_t, pagetable_t, uint64); +int ukvmcopy(pagetable_t, pagetable_t, uint64, uint64); #endif void uvmfree(pagetable_t, uint64); void uvmunmap(pagetable_t, uint64, uint64, int); @@ -181,7 +182,9 @@ pte_t* walk(pagetable_t, uint64, int); uint64 walkaddr(pagetable_t, uint64); int copyout(pagetable_t, uint64, char *, uint64); int copyin(pagetable_t, char *, uint64, uint64); +int copyin_new(pagetable_t, char *, uint64, uint64); int copyinstr(pagetable_t, char *, uint64, uint64); +int copyinstr_new(pagetable_t, char *, uint64, uint64); void vmprint(pagetable_t); // plic.c diff --git a/kernel/exec.c b/kernel/exec.c index 9d7646e..439141f 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -116,6 +116,8 @@ exec(char *path, char **argv) p->trapframe->sp = sp; // initial stack pointer proc_freepagetable(oldpagetable, oldsz); + ukvmcopy(p->pagetable, p->kpagetable, 0, p->sz); + if (p->pid == 1) vmprint(p->pagetable); return argc; // this ends up in a0, the first argument to main(argc, argv) diff --git a/kernel/proc.c b/kernel/proc.c index bc8011c..2ec73d6 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -268,6 +268,8 @@ userinit(void) uvminit(p->pagetable, initcode, sizeof(initcode)); p->sz = PGSIZE; + ukvmcopy(p->pagetable, p->kpagetable, 0, p->sz); + // prepare for the very first "return" from kernel to user. p->trapframe->epc = 0; // user program counter p->trapframe->sp = PGSIZE; // user stack pointer @@ -290,9 +292,13 @@ growproc(int n) sz = p->sz; if(n > 0){ + // Prevent user process from growing larger than the PLIC address + if (PGROUNDUP(sz + n) > PLIC) + return -1; if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0) { return -1; } + ukvmcopy(p->pagetable, p->kpagetable, sz - n, sz); } else if(n < 0){ sz = uvmdealloc(p->pagetable, sz, sz + n); } @@ -322,6 +328,11 @@ fork(void) } np->sz = p->sz; + if (ukvmcopy(np->pagetable, np->kpagetable, 0, np->sz) < 0) { + release(&np->lock); + return -1; + } + np->parent = p; // copy saved user registers. diff --git a/kernel/vm.c b/kernel/vm.c index cc91a4e..d900ea4 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -359,6 +359,29 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) return -1; } +// Copy the page table from old to new. +int +ukvmcopy(pagetable_t old, pagetable_t new, uint64 oldsz, uint64 newsz) +{ + pte_t *oldpte, *newpte; + uint64 pa, a; + uint flags; + + oldsz = PGROUNDUP(oldsz); + for (a = oldsz; a < newsz; a += PGSIZE) { + if ((oldpte = walk(old, a, 0)) == 0) + panic("ukvmcopy: oldpte should exist"); + if ((*oldpte & PTE_V) == 0) + panic("ukvmcopy: page not present"); + if ((newpte = walk(new, a, 1)) == 0) + panic("ukvmcopy: newpte should exist"); + pa = PTE2PA(*oldpte); + flags = PTE_FLAGS(*oldpte & ~PTE_U); + *newpte = PA2PTE(pa) | flags; + } + return 0; +} + // mark a PTE invalid for user access. // used by exec for the user stack guard page. void @@ -403,23 +426,7 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len) int copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len) { - uint64 n, va0, pa0; - - while(len > 0){ - va0 = PGROUNDDOWN(srcva); - pa0 = walkaddr(pagetable, va0); - if(pa0 == 0) - return -1; - n = PGSIZE - (srcva - va0); - if(n > len) - n = len; - memmove(dst, (void *)(pa0 + (srcva - va0)), n); - - len -= n; - dst += n; - srcva = va0 + PGSIZE; - } - return 0; + return copyin_new(pagetable, dst, srcva, len); } // Copy a null-terminated string from user to kernel. @@ -429,40 +436,7 @@ copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len) int copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max) { - uint64 n, va0, pa0; - int got_null = 0; - - while(got_null == 0 && max > 0){ - va0 = PGROUNDDOWN(srcva); - pa0 = walkaddr(pagetable, va0); - if(pa0 == 0) - return -1; - n = PGSIZE - (srcva - va0); - if(n > max) - n = max; - - char *p = (char *) (pa0 + (srcva - va0)); - while(n > 0){ - if(*p == '\0'){ - *dst = '\0'; - got_null = 1; - break; - } else { - *dst = *p; - } - --n; - --max; - p++; - dst++; - } - - srcva = va0 + PGSIZE; - } - if(got_null){ - return 0; - } else { - return -1; - } + return copyinstr_new(pagetable, dst, srcva, max); } void