uva2kva() - Does a page table walk to convert
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 9 May 2011 20:12:52 +0000 (13:12 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:02 +0000 (17:36 -0700)
Useful for debugging.  Also added a brief, unrelated note in blockdev
(no issue there, AFAIK).

kern/include/umem.h
kern/src/blockdev.c
kern/src/umem.c

index f6b4265..416a3c3 100644 (file)
@@ -43,6 +43,7 @@ char *user_strdup(struct proc *p, const char *u_string, size_t strlen);
 char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen);
 void *kmalloc_errno(int len);
 bool uva_is_kva(struct proc *p, void *uva, void *kva);
+uintptr_t uva2kva(struct proc *p, void *uva);
 
 /* UTOP is defined as virtual address below which a process can write */
 static inline bool is_user_rwaddr(void *addr)
index 1e9b1ca..77ff867 100644 (file)
@@ -237,6 +237,9 @@ retry:
        /* Try to insert the new one in place.  If it fails, retry the whole "find
         * the bh" process.  This should be rare, so no sense optimizing it. */
        next_loc = prev ? &prev->bh_next : (struct buffer_head**)&page->pg_private;
+       /* Normally, there'd be an ABA problem here, but we never actually remove
+        * bhs from the chain until the whole page gets cleaned up, which can't
+        * happen while we hold a reference to the page. */
        if (!atomic_comp_swap((uint32_t*)next_loc, (uint32_t)bh, (uint32_t)new)) {
                kmem_cache_free(bh_kcache, new);
                goto retry;
index e186235..5fa4bac 100644 (file)
@@ -344,3 +344,19 @@ bool uva_is_kva(struct proc *p, void *uva, void *kva)
                return FALSE;
        return (kva2page(kva) == u_page) ? TRUE : FALSE;
 }
+
+/* Given a proc and a user virtual address, gives us the KVA.  Useful for
+ * debugging.  Returns 0 if the page is unmapped (page lookup fails).  If you
+ * give it a kva, it'll give you that same KVA, but this doesn't play nice with
+ * Jumbo pages. */
+uintptr_t uva2kva(struct proc *p, void *uva)
+{
+       struct page *u_page;
+       uintptr_t offset = PGOFF(uva);
+       if (!p)
+               return 0;
+       u_page = page_lookup(p->env_pgdir, uva, 0);
+       if (!u_page)
+               return 0;
+       return (uintptr_t)page2kva(u_page) + offset;
+}