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…
Reference in a new issue