From 4655d42e3b65f906eae8c815fb78331790f6e423 Mon Sep 17 00:00:00 2001 From: Robert Morris <rtm@csail.mit.edu> Date: Mon, 27 Sep 2010 16:14:33 -0400 Subject: copyout() copies data to a va in a pagetable, for exec() &c usertest that passes too many arguments, break exec --- vm.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'vm.c') diff --git a/vm.c b/vm.c index cd6b255..551efbf 100644 --- a/vm.c +++ b/vm.c @@ -6,8 +6,6 @@ #include "proc.h" #include "elf.h" -#define USERTOP 0xA0000 - static pde_t *kpgdir; // for use in scheduler() // Set up CPU's kernel segment descriptors. @@ -126,7 +124,7 @@ setupkvm(void) { pde_t *pgdir; extern char etext[]; - char *rwstart = PGROUNDDOWN(etext) - PGSIZE; + char *rwstart = PGROUNDDOWN(etext); uint rwlen = (uint)rwstart - 0x100000; // Allocate page directory @@ -193,7 +191,10 @@ char* uva2ka(pde_t *pgdir, char *uva) { pte_t *pte = walkpgdir(pgdir, uva, 0); - if(pte == 0) return 0; + if((*pte & PTE_P) == 0) + return 0; + if((*pte & PTE_U) == 0) + return 0; uint pa = PTE_ADDR(*pte); return (char *)pa; } @@ -326,3 +327,26 @@ bad: return 0; } +// copy some data to user address va in page table pgdir. +// most useful when pgdir is not the current page table. +// returns 1 if everthing OK, 0 on error. +// uva2ka ensures this only works for PTE_U pages. +int +copyout(pde_t *pgdir, uint va, void *xbuf, uint len) +{ + char *buf = (char *) xbuf; + while(len > 0){ + uint va0 = (uint)PGROUNDDOWN(va); + char *pa0 = uva2ka(pgdir, (char*) va0); + if(pa0 == 0) + return 0; + uint n = PGSIZE - (va - va0); + if(n > len) + n = len; + memmove(pa0 + (va - va0), buf, n); + len -= n; + buf += n; + va = va0 + PGSIZE; + } + return 1; +} -- cgit v1.2.3