diff options
| author | Robert Morris <rtm@nephron.lcs.mit.edu> | 2010-08-05 12:10:54 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@nephron.lcs.mit.edu> | 2010-08-05 12:10:54 -0400 | 
| commit | eb18645f17877de4ced951eed5abac61bdfcd5c5 (patch) | |
| tree | d5a40a1839ef1264a84f9eeff5723c7c67cad711 | |
| parent | b738a4f1a2dd2956123a734327aeaf9d09b5faca (diff) | |
| download | xv6-labs-eb18645f17877de4ced951eed5abac61bdfcd5c5.tar.gz xv6-labs-eb18645f17877de4ced951eed5abac61bdfcd5c5.tar.bz2 xv6-labs-eb18645f17877de4ced951eed5abac61bdfcd5c5.zip | |
fix allocuvm() to handle sbrk() with non-page-granularity argument
(maybe this never worked, but it works now)
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | defs.h | 2 | ||||
| -rw-r--r-- | mmu.h | 4 | ||||
| -rw-r--r-- | usertests.c | 34 | ||||
| -rw-r--r-- | vm.c | 36 | 
5 files changed, 65 insertions, 13 deletions
| @@ -38,7 +38,7 @@ AS = $(TOOLPREFIX)gas  LD = $(TOOLPREFIX)ld  OBJCOPY = $(TOOLPREFIX)objcopy  OBJDUMP = $(TOOLPREFIX)objdump -CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 +CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror  CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)  ASFLAGS = -m32 -gdwarf-2  # FreeBSD ld wants ``elf_i386_fbsd'' @@ -153,8 +153,6 @@ void            uartintr(void);  void            uartputc(int);  // vm.c -#define PGROUNDUP(sz)  ((sz+PGSIZE-1) & ~(PGSIZE-1)) -extern pde_t    *kpgdir;  void            pminit(void);  void            ksegment(void);  void            kvmalloc(void); @@ -126,6 +126,9 @@ struct segdesc {  #define PTXSHIFT	12		// offset of PTX in a linear address  #define PDXSHIFT	22		// offset of PDX in a linear address +#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) & ~(PGSIZE-1)) +#define PGROUNDDOWN(a) ((char*)((((unsigned int)a) & ~(PGSIZE-1)))) +  // Page table/directory entry flags.  #define PTE_P		0x001	// Present  #define PTE_W		0x002	// Writeable @@ -148,6 +151,7 @@ struct segdesc {  #define PTE_ADDR(pte)	((uint) (pte) & ~0xFFF)  typedef uint pte_t; +extern pde_t    *kpgdir;  // Control Register flags  #define CR0_PE		0x00000001	// Protection Enable diff --git a/usertests.c b/usertests.c index cc2601c..2bd21ba 100644 --- a/usertests.c +++ b/usertests.c @@ -1229,6 +1229,38 @@ forktest(void)    printf(1, "fork test OK\n");  } +void +sbrktest(void) +{ +  printf(stdout, "sbrk test\n"); +  char *a = sbrk(0); +  int i; +  for(i = 0; i < 5000; i++){ +    char *b = sbrk(1); +    if(b != a){ +      printf(stdout, "sbrk test failed %d %x %x\n", i, a, b); +      exit(); +    } +    *b = 1; +    a = b + 1; +  } +  int pid = fork(); +  if(pid < 0){ +    printf(stdout, "sbrk test fork failed\n"); +    exit(); +  } +  char *c = sbrk(1); +  c = sbrk(1); +  if(c != a + 1){ +    printf(stdout, "sbrk test failed post-fork\n"); +    exit(); +  } +  if(pid == 0) +    exit(); +  wait(); +  printf(stdout, "sbrk test OK\n"); +} +  int  main(int argc, char *argv[])  { @@ -1240,6 +1272,8 @@ main(int argc, char *argv[])    }    close(open("usertests.ran", O_CREATE)); +  sbrktest(); +    opentest();    writetest();    writetest1(); @@ -54,6 +54,9 @@ printpgdir(pde_t *pgdir)    cprintf("printpgdir done\n", pgdir);  } +// return the address of the PTE in page table pgdir +// that corresponds to linear address va.  if create!=0, +// create any required page table pages.  static pte_t *  walkpgdir(pde_t *pgdir, const void *va, int create)  { @@ -80,6 +83,8 @@ walkpgdir(pde_t *pgdir, const void *va, int create)    return &pgtab[PTX(va)];  } +// create PTEs for linear addresses starting at la that refer to +// physical addresses starting at pa.   static int  mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)  { @@ -89,6 +94,8 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)    for (i = 0; i < size; i += PGSIZE) {      if (!(pte = walkpgdir(pgdir, (void*)(la + i), 1)))        return 0; +    if(*pte & PTE_P) +      panic("remap");      *pte = (pa + i) | perm | PTE_P;    }    return 1; @@ -177,21 +184,30 @@ uva2ka(pde_t *pgdir, char *uva)    return (char *)pa;  } +// allocate sz bytes more memory for a process starting at the +// given user address; allocates physical memory and page +// table entries. addr and sz need not be page-aligned. +// it is a no-op for any parts of the requested memory +// that are already allocated.  int  allocuvm(pde_t *pgdir, char *addr, uint sz)  { -  uint i, n; -  char *mem; - -  n = PGROUNDUP(sz); -  if (addr + n >= USERTOP) +  if (addr + sz >= (char*)USERTOP)      return 0; -  for (i = 0; i < n; i += PGSIZE) { -    if (!(mem = kalloc(PGSIZE))) {   // XXX cleanup what we did? -      return 0; +  char *start = PGROUNDDOWN(addr); +  char *last = PGROUNDDOWN(addr + sz - 1); +  char *a; +  for(a = start; a <= last; a += PGSIZE){ +    pte_t *pte = walkpgdir(pgdir, a, 0); +    if(pte == 0 || (*pte & PTE_P) == 0){ +      char *mem = kalloc(PGSIZE); +      if(mem == 0){ +        // XXX clean up? +        return 0; +      } +      memset(mem, 0, PGSIZE); +      mappages(pgdir, a, PGSIZE, PADDR(mem), PTE_W|PTE_U);      } -    memset(mem, 0, PGSIZE); -    mappages(pgdir, addr + i, PGSIZE, PADDR(mem), PTE_W|PTE_U);    }    return 1;  } | 
