提交 550d1798 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

soft page faults, seems like fork is buggy though

上级 0d19e203
...@@ -169,11 +169,11 @@ struct vmap * vmap_copy(struct vmap *); ...@@ -169,11 +169,11 @@ struct vmap * vmap_copy(struct vmap *);
int allocuvm(pde_t*, uint, uint); int allocuvm(pde_t*, uint, uint);
int deallocuvm(pde_t*, uint, uint); int deallocuvm(pde_t*, uint, uint);
void freevm(pde_t*); void freevm(pde_t*);
pde_t* copyuvm(pde_t*, uint);
void switchuvm(struct proc*); void switchuvm(struct proc*);
void switchkvm(void); void switchkvm(void);
int copyout(struct vmap *, uint, void*, uint); int copyout(struct vmap *, uint, void*, uint);
int copyin(struct vmap *, uint, void*, uint); int copyin(struct vmap *, uint, void*, uint);
int pagefault(pde_t*, struct vmap *, uint);
// number of elements in fixed-size array // number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0])) #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
...@@ -86,7 +86,7 @@ userinit(void) ...@@ -86,7 +86,7 @@ userinit(void)
panic("userinit: out of memory?"); panic("userinit: out of memory?");
if((p->vmap = vmap_alloc()) == 0) if((p->vmap = vmap_alloc()) == 0)
panic("userinit: out of vmaps?"); panic("userinit: out of vmaps?");
struct vmnode *vmn = vmn_allocpg(PGROUNDUP((int)_binary_initcode_size)); struct vmnode *vmn = vmn_allocpg(PGROUNDUP((int)_binary_initcode_size) / PGSIZE);
if(vmn == 0) if(vmn == 0)
panic("userinit: vmn_allocpg"); panic("userinit: vmn_allocpg");
if(vmap_insert(p->vmap, vmn, 0) < 0) if(vmap_insert(p->vmap, vmn, 0) < 0)
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
int int
fetchint(struct proc *p, uint addr, int *ip) fetchint(struct proc *p, uint addr, int *ip)
{ {
#if 0 /* XXX */ #if 0 /* XXX use pagefault() */
if(addr >= p->sz || addr+4 > p->sz) if(addr >= p->sz || addr+4 > p->sz)
return -1; return -1;
#endif #endif
...@@ -32,12 +32,12 @@ fetchstr(struct proc *p, uint addr, char **pp) ...@@ -32,12 +32,12 @@ fetchstr(struct proc *p, uint addr, char **pp)
{ {
char *s, *ep; char *s, *ep;
#if 0 /* XXX */ #if 0 /* XXX use pagefault() */
if(addr >= p->sz) if(addr >= p->sz)
return -1; return -1;
#endif #endif
*pp = (char*)addr; *pp = (char*)addr;
#if 0 /* XXX */ #if 0 /* XXX use pagefault() */
ep = (char*)p->sz; ep = (char*)p->sz;
#else #else
ep = (char *) 0xffffffff; ep = (char *) 0xffffffff;
...@@ -65,7 +65,7 @@ argptr(int n, char **pp, int size) ...@@ -65,7 +65,7 @@ argptr(int n, char **pp, int size)
if(argint(n, &i) < 0) if(argint(n, &i) < 0)
return -1; return -1;
#if 0 /* XXX */ #if 0 /* XXX use pagefault() */
if((uint)i >= proc->sz || (uint)i+size > proc->sz) if((uint)i >= proc->sz || (uint)i+size > proc->sz)
return -1; return -1;
#endif #endif
......
...@@ -45,6 +45,16 @@ trap(struct trapframe *tf) ...@@ -45,6 +45,16 @@ trap(struct trapframe *tf)
return; return;
} }
if(tf->trapno == T_PGFLT){
cprintf("[%d] page fault for %x\n", cpunum(), rcr2());
if(pagefault(proc->pgdir, proc->vmap, rcr2()) >= 0){
cprintf("[%d] xxx1\n", cpunum());
switchuvm(proc);
return;
}
cprintf("[%d] xxx2\n", cpunum());
}
switch(tf->trapno){ switch(tf->trapno){
case T_IRQ0 + IRQ_TIMER: case T_IRQ0 + IRQ_TIMER:
if(cpu->id == 0){ if(cpu->id == 0){
......
...@@ -210,8 +210,10 @@ struct vmnode * ...@@ -210,8 +210,10 @@ struct vmnode *
vmn_allocpg(uint npg) vmn_allocpg(uint npg)
{ {
struct vmnode *n = vmn_alloc(); struct vmnode *n = vmn_alloc();
if(npg > sizeof(n->page) / sizeof(n->page[0])) if(npg > sizeof(n->page) / sizeof(n->page[0])) {
panic("vmnode too big"); cprintf("vmnode too big: %d\n", npg);
return 0;
}
for(uint i = 0; i < npg; i++) { for(uint i = 0; i < npg; i++) {
if((n->page[i] = kalloc()) == 0) { if((n->page[i] = kalloc()) == 0) {
vmn_free(n); vmn_free(n);
...@@ -429,37 +431,6 @@ freevm(pde_t *pgdir) ...@@ -429,37 +431,6 @@ freevm(pde_t *pgdir)
kfree((char*)pgdir); kfree((char*)pgdir);
} }
// Given a parent process's page table, create a copy
// of it for a child.
pde_t*
copyuvm(pde_t *pgdir, uint sz)
{
pde_t *d;
pte_t *pte;
uint pa, i;
char *mem;
if((d = setupkvm()) == 0)
return 0;
for(i = 0; i < sz; i += PGSIZE){
if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0)
panic("copyuvm: pte should exist");
if(!(*pte & PTE_P))
panic("copyuvm: page not present");
pa = PTE_ADDR(*pte);
if((mem = kalloc()) == 0)
goto bad;
memmove(mem, (char*)pa, PGSIZE);
if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0)
goto bad;
}
return d;
bad:
freevm(d);
return 0;
}
//PAGEBREAK! //PAGEBREAK!
// Map user virtual address to kernel physical address. // Map user virtual address to kernel physical address.
char* char*
...@@ -528,3 +499,28 @@ copyin(struct vmap *vmap, uint va, void *p, uint len) ...@@ -528,3 +499,28 @@ copyin(struct vmap *vmap, uint va, void *p, uint len)
} }
return 0; return 0;
} }
int
pagefault(pde_t *pgdir, struct vmap *vmap, uint va)
{
cprintf("pagefault\n");
pte_t *pte = walkpgdir(pgdir, (const void *)va, 1);
cprintf("pagefault: 0\n");
if((*pte & (PTE_P|PTE_U|PTE_W)) == (PTE_P|PTE_U|PTE_W)) {
cprintf("pagefault: 1\n");
return 0;
}
cprintf("pagefault: 1.1\n");
struct vma *m = vmap_lookup(vmap, va);
if(m == 0) {
cprintf("pagefault: 2\n");
return -1;
}
cprintf("pagefault: 3\n");
uint npg = (PGROUNDDOWN(va) - m->va_start) / PGSIZE;
*pte = PADDR(m->n->page[npg]) | PTE_P | PTE_U | PTE_W;
release(&m->lock);
return 1;
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论