]> Devi Nivas Git - cs3210-lab1.git/commitdiff
fix allocuvm() to handle sbrk() with non-page-granularity argument
authorRobert Morris <rtm@nephron.lcs.mit.edu>
Thu, 5 Aug 2010 16:10:54 +0000 (12:10 -0400)
committerRobert Morris <rtm@nephron.lcs.mit.edu>
Thu, 5 Aug 2010 16:10:54 +0000 (12:10 -0400)
(maybe this never worked, but it works now)

Makefile
defs.h
mmu.h
usertests.c
vm.c

index a0c901dc41ec15e4b341aa9f8f22c4a517beea05..ef9b66d7238234ecff06a3df6fdfa0f229bb70c9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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''
diff --git a/defs.h b/defs.h
index 86268b21ab32d05d91c89c46956f91b03bcb6c80..b414a5f8fdefb62c51c4be4e91c523eee84e1f90 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -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);
diff --git a/mmu.h b/mmu.h
index 378ae22d308c17371d704ba73deb7169a4cb84c0..e3ea46f01396aefd9befc53d769585124524f1f9 100644 (file)
--- a/mmu.h
+++ b/mmu.h
@@ -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
index cc2601ceed91ad962b6bcf80aa8ddd2b28df4d13..2bd21ba810a36d2a358e62c6a494f4fa6334e4a4 100644 (file)
@@ -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();
diff --git a/vm.c b/vm.c
index 231e1339c58304f3269901ded81b8f45ec599f19..b89efd5614b27e111b2d7e1bea361d3c3ed3d3a2 100644 (file)
--- a/vm.c
+++ b/vm.c
@@ -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;
 }