pagelookup returns the kernel addr for a user addr

上级 63692bb2
......@@ -235,7 +235,8 @@ void uartintr(void);
// vm.c
void switchvm(struct proc*);
int pagefault(struct vmap *, uptr, u32);
int pagefault(struct vmap*, uptr, u32);
void* pagelookup(struct vmap*, uptr);
// zalloc.cc
char* zalloc(const char* name);
......
......@@ -96,6 +96,7 @@ struct vmap {
int remove(uptr start, uptr len);
int pagefault(uptr va, u32 err);
void* pagelookup(uptr va);
int copyout(uptr va, void *p, u64 len);
int sbrk(ssize_t n, uptr *addr);
......
......@@ -633,7 +633,7 @@ vmap::pagefault(uptr va, u32 err)
}
int
pagefault(struct vmap *vmap, uptr va, u32 err)
pagefault(vmap *vmap, uptr va, u32 err)
{
#if MTRACE
mt_ascope ascope("%s(%p)", __func__, va);
......@@ -656,6 +656,57 @@ pagefault(struct vmap *vmap, uptr va, u32 err)
}
}
void*
vmap::pagelookup(uptr va)
{
if (va >= USERTOP)
return nullptr;
scoped_gc_epoch gc;
vma *m = lookup(va, 1);
if (m == 0 || m->n == nullptr)
return nullptr;
u64 npg = (PGROUNDDOWN(va)-m->vma_start) / PGSIZE;
if (!m->n->page[npg])
// XXX(sbw) you might think we don't need to zero if ONDEMAND;
// however, our vmnode might include not backed by a file
// (e.g. the bss section of an ELF segment)
// XXX(austin) Why is this still necessary now that we map zeroed
// parts of segments separately?
if (m->n->allocpg(npg, true) < 0)
throw_bad_alloc();
char* kptr = (char*)(m->n->page[npg]);
mtreadavar("vmnode:%016x", m->n);
return &kptr[va & (PGSIZE-1)];
}
void*
pagelookup(vmap* vmap, uptr va)
{
#if MTRACE
mt_ascope ascope("%s(%p)", __func__, va);
mtwriteavar("thread:%x", myproc()->pid);
mtwriteavar("page:%p.%016x", vmap, PGROUNDDOWN(va));
#endif
for (;;) {
#if EXCEPTIONS
try {
#endif
return vmap->pagelookup(va);
#if EXCEPTIONS
} catch (retryable& e) {
cprintf("%d: pagelookup retry\n", myproc()->pid);
gc_wakeup();
yield();
}
#endif
}
}
// Copy len bytes from p to user address va in vmap.
// Most useful when vmap is not the current page table.
int
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论