fix allocuvm() to handle sbrk() with non-page-granularity argument
(maybe this never worked, but it works now)
This commit is contained in:
		
							parent
							
								
									b738a4f1a2
								
							
						
					
					
						commit
						eb18645f17
					
				
					 5 changed files with 65 additions and 13 deletions
				
			
		
							
								
								
									
										2
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
					@ -38,7 +38,7 @@ AS = $(TOOLPREFIX)gas
 | 
				
			||||||
LD = $(TOOLPREFIX)ld
 | 
					LD = $(TOOLPREFIX)ld
 | 
				
			||||||
OBJCOPY = $(TOOLPREFIX)objcopy
 | 
					OBJCOPY = $(TOOLPREFIX)objcopy
 | 
				
			||||||
OBJDUMP = $(TOOLPREFIX)objdump
 | 
					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)
 | 
					CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
 | 
				
			||||||
ASFLAGS = -m32 -gdwarf-2
 | 
					ASFLAGS = -m32 -gdwarf-2
 | 
				
			||||||
# FreeBSD ld wants ``elf_i386_fbsd''
 | 
					# FreeBSD ld wants ``elf_i386_fbsd''
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								defs.h
									
										
									
									
									
								
							| 
						 | 
					@ -153,8 +153,6 @@ void            uartintr(void);
 | 
				
			||||||
void            uartputc(int);
 | 
					void            uartputc(int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// vm.c
 | 
					// vm.c
 | 
				
			||||||
#define PGROUNDUP(sz)  ((sz+PGSIZE-1) & ~(PGSIZE-1))
 | 
					 | 
				
			||||||
extern pde_t    *kpgdir;
 | 
					 | 
				
			||||||
void            pminit(void);
 | 
					void            pminit(void);
 | 
				
			||||||
void            ksegment(void);
 | 
					void            ksegment(void);
 | 
				
			||||||
void            kvmalloc(void);
 | 
					void            kvmalloc(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								mmu.h
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								mmu.h
									
										
									
									
									
								
							| 
						 | 
					@ -126,6 +126,9 @@ struct segdesc {
 | 
				
			||||||
#define PTXSHIFT	12		// offset of PTX in a linear address
 | 
					#define PTXSHIFT	12		// offset of PTX in a linear address
 | 
				
			||||||
#define PDXSHIFT	22		// offset of PDX 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.
 | 
					// Page table/directory entry flags.
 | 
				
			||||||
#define PTE_P		0x001	// Present
 | 
					#define PTE_P		0x001	// Present
 | 
				
			||||||
#define PTE_W		0x002	// Writeable
 | 
					#define PTE_W		0x002	// Writeable
 | 
				
			||||||
| 
						 | 
					@ -148,6 +151,7 @@ struct segdesc {
 | 
				
			||||||
#define PTE_ADDR(pte)	((uint) (pte) & ~0xFFF)
 | 
					#define PTE_ADDR(pte)	((uint) (pte) & ~0xFFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef uint pte_t;
 | 
					typedef uint pte_t;
 | 
				
			||||||
 | 
					extern pde_t    *kpgdir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Control Register flags
 | 
					// Control Register flags
 | 
				
			||||||
#define CR0_PE		0x00000001	// Protection Enable
 | 
					#define CR0_PE		0x00000001	// Protection Enable
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								usertests.c
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								usertests.c
									
										
									
									
									
								
							| 
						 | 
					@ -1229,6 +1229,38 @@ forktest(void)
 | 
				
			||||||
  printf(1, "fork test OK\n");
 | 
					  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
 | 
					int
 | 
				
			||||||
main(int argc, char *argv[])
 | 
					main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1240,6 +1272,8 @@ main(int argc, char *argv[])
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  close(open("usertests.ran", O_CREATE));
 | 
					  close(open("usertests.ran", O_CREATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sbrktest();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  opentest();
 | 
					  opentest();
 | 
				
			||||||
  writetest();
 | 
					  writetest();
 | 
				
			||||||
  writetest1();
 | 
					  writetest1();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								vm.c
									
										
									
									
									
								
							| 
						 | 
					@ -54,6 +54,9 @@ printpgdir(pde_t *pgdir)
 | 
				
			||||||
  cprintf("printpgdir done\n", 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 *
 | 
					static pte_t *
 | 
				
			||||||
walkpgdir(pde_t *pgdir, const void *va, int create)
 | 
					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)];
 | 
					  return &pgtab[PTX(va)];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// create PTEs for linear addresses starting at la that refer to
 | 
				
			||||||
 | 
					// physical addresses starting at pa. 
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)
 | 
					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) {
 | 
					  for (i = 0; i < size; i += PGSIZE) {
 | 
				
			||||||
    if (!(pte = walkpgdir(pgdir, (void*)(la + i), 1)))
 | 
					    if (!(pte = walkpgdir(pgdir, (void*)(la + i), 1)))
 | 
				
			||||||
      return 0;
 | 
					      return 0;
 | 
				
			||||||
 | 
					    if(*pte & PTE_P)
 | 
				
			||||||
 | 
					      panic("remap");
 | 
				
			||||||
    *pte = (pa + i) | perm | PTE_P;
 | 
					    *pte = (pa + i) | perm | PTE_P;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return 1;
 | 
					  return 1;
 | 
				
			||||||
| 
						 | 
					@ -177,21 +184,30 @@ uva2ka(pde_t *pgdir, char *uva)
 | 
				
			||||||
  return (char *)pa;
 | 
					  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
 | 
					int
 | 
				
			||||||
allocuvm(pde_t *pgdir, char *addr, uint sz)
 | 
					allocuvm(pde_t *pgdir, char *addr, uint sz)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  uint i, n;
 | 
					  if (addr + sz >= (char*)USERTOP)
 | 
				
			||||||
  char *mem;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  n = PGROUNDUP(sz);
 | 
					 | 
				
			||||||
  if (addr + n >= USERTOP)
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
  for (i = 0; i < n; i += PGSIZE) {
 | 
					  char *start = PGROUNDDOWN(addr);
 | 
				
			||||||
    if (!(mem = kalloc(PGSIZE))) {   // XXX cleanup what we did?
 | 
					  char *last = PGROUNDDOWN(addr + sz - 1);
 | 
				
			||||||
      return 0;
 | 
					  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;
 | 
					  return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue