提交 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 *);
int allocuvm(pde_t*, uint, uint);
int deallocuvm(pde_t*, uint, uint);
void freevm(pde_t*);
pde_t* copyuvm(pde_t*, uint);
void switchuvm(struct proc*);
void switchkvm(void);
int copyout(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
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
......@@ -86,7 +86,7 @@ userinit(void)
panic("userinit: out of memory?");
if((p->vmap = vmap_alloc()) == 0)
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)
panic("userinit: vmn_allocpg");
if(vmap_insert(p->vmap, vmn, 0) < 0)
......
......@@ -16,7 +16,7 @@
int
fetchint(struct proc *p, uint addr, int *ip)
{
#if 0 /* XXX */
#if 0 /* XXX use pagefault() */
if(addr >= p->sz || addr+4 > p->sz)
return -1;
#endif
......@@ -32,12 +32,12 @@ fetchstr(struct proc *p, uint addr, char **pp)
{
char *s, *ep;
#if 0 /* XXX */
#if 0 /* XXX use pagefault() */
if(addr >= p->sz)
return -1;
#endif
*pp = (char*)addr;
#if 0 /* XXX */
#if 0 /* XXX use pagefault() */
ep = (char*)p->sz;
#else
ep = (char *) 0xffffffff;
......@@ -65,7 +65,7 @@ argptr(int n, char **pp, int size)
if(argint(n, &i) < 0)
return -1;
#if 0 /* XXX */
#if 0 /* XXX use pagefault() */
if((uint)i >= proc->sz || (uint)i+size > proc->sz)
return -1;
#endif
......
......@@ -45,6 +45,16 @@ trap(struct trapframe *tf)
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){
case T_IRQ0 + IRQ_TIMER:
if(cpu->id == 0){
......
......@@ -210,8 +210,10 @@ struct vmnode *
vmn_allocpg(uint npg)
{
struct vmnode *n = vmn_alloc();
if(npg > sizeof(n->page) / sizeof(n->page[0]))
panic("vmnode too big");
if(npg > sizeof(n->page) / sizeof(n->page[0])) {
cprintf("vmnode too big: %d\n", npg);
return 0;
}
for(uint i = 0; i < npg; i++) {
if((n->page[i] = kalloc()) == 0) {
vmn_free(n);
......@@ -429,37 +431,6 @@ freevm(pde_t *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!
// Map user virtual address to kernel physical address.
char*
......@@ -528,3 +499,28 @@ copyin(struct vmap *vmap, uint va, void *p, uint len)
}
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论