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
|
||||
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''
|
||||
|
|
2
defs.h
2
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);
|
||||
|
|
4
mmu.h
4
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
|
||||
|
|
34
usertests.c
34
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();
|
||||
|
|
36
vm.c
36
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue