Skip to content

Commit

Permalink
Lab pgtbl: ukvmcopy
Browse files Browse the repository at this point in the history
  • Loading branch information
foyoodo committed Mar 17, 2021
1 parent 758490d commit 0c53a28
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 51 deletions.
3 changes: 3 additions & 0 deletions kernel/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions kernel/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions kernel/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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.
Expand Down
76 changes: 25 additions & 51 deletions kernel/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down

0 comments on commit 0c53a28

Please sign in to comment.