Fixed compile_vaddr(). Cleaned up new code.
authorSimon Gerber <simon.gerber@inf.ethz.ch>
Thu, 22 Nov 2012 14:52:19 +0000 (15:52 +0100)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Tue, 29 Jan 2013 10:30:59 +0000 (11:30 +0100)
errors/errno.fugu
kernel/arch/x86_64/page_mappings_arch.c
kernel/include/arch/armv5/paging_kernel_arch.h
kernel/include/arch/armv7/paging_kernel_arch.h
kernel/include/arch/x86_32/paging_kernel_arch.h
kernel/include/arch/x86_64/paging_kernel_arch.h
kernel/include/paging_generic.h
kernel/paging_generic.c
lib/barrelfish/target/x86_64/pmap_target.c

index 3fafa9c..58dc4de 100644 (file)
@@ -70,7 +70,8 @@ errors kernel SYS_ERR_ {
     failure FRAME_OFFSET_INVALID "Specified offset exceeds size of frame",
     failure VNODE_SLOT_RESERVED        "Destination slot is reserved",
     failure VNODE_SLOT_INUSE   "Destination slot in use: unmap first",
-    failure VNODE_TYPE          "Encountered non-VNoe capability when manipulating page tables",
+    failure VNODE_TYPE          "Encountered non-VNode capability when manipulating page tables",
+    failure VNODE_LOOKUP_NEXT   "Could not find next level page table",
 
     // errors related to IRQ table
     failure IRQ_LOOKUP          "Specified capability was not found while inserting in IRQ table",
index b91294a..1f0b709 100644 (file)
@@ -38,9 +38,9 @@ static errval_t x86_64_pml4(struct capability *dest, cslot_t slot,
     genpaddr_t dest_gp   = dest->u.vnode_x86_64_pml4.base;
     lpaddr_t dest_lp     = gen_phys_to_local_phys(dest_gp);
     lvaddr_t dest_lv     = local_phys_to_mem(dest_lp);
-    // assign output param
-    *pte = dest_lv + slot;
     union x86_64_pdir_entry *entry = (union x86_64_pdir_entry *)dest_lv + slot;
+    // assign output param
+    *pte = dest_lp + slot * sizeof(union x86_64_ptable_entry);
 
     if (X86_64_IS_PRESENT(entry)) {
         return SYS_ERR_VNODE_SLOT_INUSE;
@@ -71,9 +71,9 @@ static errval_t x86_64_pdpt(struct capability *dest, cslot_t slot,
     genpaddr_t dest_gp   = dest->u.vnode_x86_64_pdpt.base;
     lpaddr_t dest_lp     = gen_phys_to_local_phys(dest_gp);
     lvaddr_t dest_lv     = local_phys_to_mem(dest_lp);
-    // assign output param
-    *pte = dest_lv + slot;
     union x86_64_pdir_entry *entry = (union x86_64_pdir_entry *)dest_lv + slot;
+    // assign output param
+    *pte = dest_lp + slot * sizeof(union x86_64_ptable_entry);
 
     if (X86_64_IS_PRESENT(entry)) {
         return SYS_ERR_VNODE_SLOT_INUSE;
@@ -104,9 +104,9 @@ static errval_t x86_64_pdir(struct capability *dest, cslot_t slot,
     genpaddr_t dest_gp   = dest->u.vnode_x86_64_pdir.base;
     lpaddr_t dest_lp     = gen_phys_to_local_phys(dest_gp);
     lvaddr_t dest_lv     = local_phys_to_mem(dest_lp);
-    // assign output param
-    *pte = dest_lv + slot;
     union x86_64_pdir_entry *entry = (union x86_64_pdir_entry *)dest_lv + slot;
+    // assign output param
+    *pte = dest_lp + slot * sizeof(union x86_64_ptable_entry);
 
     if (X86_64_IS_PRESENT(entry)) {
         return SYS_ERR_VNODE_SLOT_INUSE;
@@ -156,10 +156,10 @@ static errval_t x86_64_ptable(struct capability *dest, cslot_t slot,
     genpaddr_t dest_gp   = dest->u.vnode_x86_64_ptable.base;
     lpaddr_t dest_lp     = gen_phys_to_local_phys(dest_gp);
     lvaddr_t dest_lv     = local_phys_to_mem(dest_lp);
-    // assign output param
-    *pte = dest_lv + slot;
     union x86_64_ptable_entry *entry =
         (union x86_64_ptable_entry *)dest_lv + slot;
+    // assign output param
+    *pte = dest_lp + slot * sizeof(union x86_64_ptable_entry);
 
     /* FIXME: Flush TLB if the page is already present
      * in the meantime, since we don't do this, we just fail to avoid
@@ -207,11 +207,22 @@ errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
     errval_t r = handler_func(dest_cap, dest_slot, src_cap, param1, param2, &pte);
     if (err_is_ok(r)) {
         // update mapping
-        src_cte->mapping_info.pte = pte;
+        // XXX: hacky, should either have a real indicator if mapping in progress
+        // or do the base page loop here
+        if (src_cte->mapping_info.pte == 0) {
+            src_cte->mapping_info.pte = pte;
+            src_cte->mapping_info.mapped_offset = param2;
+        }
         src_cte->mapping_info.mapped_pages += 1;
-        src_cte->mapping_info.mapped_offset = 0;
+        genvaddr_t vaddr = 0;
+        errval_t r2 = compile_vaddr(dest_vnode_cte, dest_slot, &vaddr);
+        if (err_is_fail(r2)) {
+            printf("src_cte->cap.type = %d\n", src_cte->cap.type);
+            printf("error in compile_vaddr: 0x%"PRIxERRV"\n", r2);
+        }
+        //printf("src_cte->pte = %"PRIxLVADDR"\n", src_cte->mapping_info.pte);
         printf("full vaddr of new mapping (entry = %"PRIuCSLOT"): 0x%"PRIxGENVADDR"\n",
-               dest_slot, compile_vaddr(src_cte, dest_slot));
+               dest_slot, vaddr);
     }
     return r;
 }
index 0b2f92d..2933eaf 100644 (file)
@@ -73,4 +73,23 @@ static inline bool is_root_pt(enum objtype type) {
     return type == ObjType_VNode_ARM_l2;
 }
 
+static inline size_t get_pte_size(void) {
+    // both l1_entry and l2_entry are 4 bytes
+    return sizeof(union l1_entry);
+}
+
+static inline size_t vnode_entry_bits(enum objtype type) {
+    if (type == ObjType_VNode_ARM_l2)
+    {
+        return 9;       // log2(ARM_L2_MAX_ENTRIES)
+    }
+    else if (type == ObjType_VNode_ARM_l1)
+    {
+        return 12;      // log2(ARM_L1_MAX_ENTRIES)
+    }
+    else {
+        assert(!"unknown page table type");
+    }
+}
+
 #endif // KERNEL_ARCH_ARM_PAGING_H
index 4084047..aa9c783 100644 (file)
@@ -71,4 +71,23 @@ static inline bool is_root_pt(enum objtype type) {
     return type == ObjType_VNode_ARM_l2;
 }
 
+static inline size_t get_pte_size(void) {
+    // both l1_entry and l2_entry are 4 bytes
+    return sizeof(union l1_entry);
+}
+
+static inline size_t vnode_entry_bits(enum objtype type) {
+    if (type == ObjType_VNode_ARM_l2)
+    {
+        return 9;       // log2(ARM_L2_MAX_ENTRIES)
+    }
+    else if (type == ObjType_VNode_ARM_l1)
+    {
+        return 12;      // log2(ARM_L1_MAX_ENTRIES)
+    }
+    else {
+        assert(!"unknown page table type");
+    }
+}
+
 #endif // KERNEL_ARCH_ARM_PAGING_H
index 2a3fadd..63f2761 100644 (file)
@@ -81,11 +81,40 @@ static lvaddr_t inline paging_map_device(lpaddr_t base, size_t size)
 }
 
 static inline bool is_root_pt(enum objtype type) {
-#if PAE
+#ifdef CONFIG_PAE
     return type == ObjType_VNode_x86_32_pdpt;
 #else
     return type == ObjType_VNode_x86_32_pdir;
 #endif
 }
 
+static inline size_t get_pte_size(void) {
+    // the definition of x86_32_ptable entry is wrapped in an #ifdef CONFIG_PAE
+    // block and will thus have the correct size for both PAE and non-PAE x86_32.
+    return sizeof(union x86_32_ptable_entry);
+}
+
+static inline size_t vnode_entry_bits(enum objtype type) {
+#ifdef CONFIG_PAE
+    else if (type == ObjType_VNode_x86_32_pdpt)
+    {
+        return 2;       // log2(X86_32_PDPTE_SIZE)
+    }
+    else if (type == ObjType_VNode_x86_32_pdir ||
+             type == ObjType_VNode_x86_32_ptable)
+    {
+        return 9;       // log2(X86_32_PTABLE_SIZE) == log2(X86_32_PDIR_SIZE)
+    }
+#else
+    else if (type == ObjType_VNode_x86_32_pdir ||
+             type == ObjType_VNode_x86_32_ptable)
+    {
+        return 10;      // log2(X86_32_PTABLE_SIZE) == log2(X86_32_PDIR_SIZE)
+    }
+#endif
+    else {
+        assert(!"unknown page table type");
+    }
+}
+
 #endif // KERNEL_ARCH_X86_32_PAGING_H
index fb73614..0879322 100644 (file)
@@ -65,4 +65,26 @@ static inline bool is_root_pt(enum objtype type) {
     return type == ObjType_VNode_x86_64_pml4;
 }
 
+static inline size_t get_pte_size(void) {
+    return sizeof(union x86_64_ptable_entry);
+}
+
+/**
+ * Return number of page table entries for vnode in bits.
+ * @param type Object type.
+ * @return Number of page table entries in bits
+ */
+static inline size_t vnode_entry_bits(enum objtype type) {
+    if (type == ObjType_VNode_x86_64_pml4 ||
+        type == ObjType_VNode_x86_64_pdpt ||
+        type == ObjType_VNode_x86_64_pdir ||
+        type == ObjType_VNode_x86_64_ptable)
+    {
+        return 9;      // log2(X86_64_PTABLE_SIZE)
+    }
+    else {
+        assert(!"unknown page table type");
+    }
+}
+
 #endif // KERNEL_ARCH_X86_64_PAGING_H
index 6d0d7d8..159bdbb 100644 (file)
@@ -25,6 +25,6 @@ struct mapping_info {
 };
 
 struct cte;
-genvaddr_t compile_vaddr(struct cte *ptable, size_t entry);
+errval_t compile_vaddr(struct cte *ptable, size_t entry, genvaddr_t *retvaddr);
 
 #endif // PAGING_H
index 3992d1f..54fbe7a 100644 (file)
 #include <mdb/mdb_tree.h>
 #include <stdio.h>
 
-__attribute__((unused))
-static size_t get_next_size(enum objtype type)
+static inline errval_t find_next_ptable(struct cte *old, struct cte **next)
 {
-    if (!type_is_vnode(type)) {
-        assert(!"makes no sense on non-vnode type");
+    int result;
+    errval_t err;
+    err = mdb_find_range(get_type_root(ObjType_RAM),
+            local_phys_to_gen_phys((lpaddr_t)old->mapping_info.pte),
+            0, MDB_RANGE_FOUND_INNER, next,
+            &result);
+    if (err_is_fail(err)) {
+        printf("error in compile_vaddr: mdb_find_range: 0x%"PRIxERRV"\n", err);
+        return err;
     }
-
-    size_t size;
-    switch (type) {
-        case ObjType_VNode_x86_64_pdpt:
-            size = 1ULL<<vnode_objbits(ObjType_VNode_x86_64_pml4);
-            break;
-        case ObjType_VNode_x86_64_pdir:
-            size = 1ULL<<vnode_objbits(ObjType_VNode_x86_64_pdpt);
-            break;
-        case ObjType_VNode_x86_64_ptable:
-            size = 1ULL<<vnode_objbits(ObjType_VNode_x86_64_pdir);
-            break;
-#ifdef PAE
-        case ObjType_VNode_x86_32_pdir:
-            size = 1ULL<<vnode_objbits(ObjType_VNode_x86_32_pdpt);
-            break;
-#endif
-        case ObjType_VNode_x86_32_ptable:
-            size = 1ULL<<vnode_objbits(ObjType_VNode_x86_32_pdir);
-            break;
-        case ObjType_VNode_ARM_l1:
-            size = 1ULL<<vnode_objbits(ObjType_VNode_ARM_l2);
-            break;
-        default:
-            assert(!"makes no sense on top level vnode type");
+    if (result != MDB_RANGE_FOUND_SURROUNDING) {
+        printf("(%d) could not find cap associated with 0x%"PRIxLVADDR"\n", result, old->mapping_info.pte);
+        return SYS_ERR_VNODE_LOOKUP_NEXT;
     }
+    return SYS_ERR_OK;
+}
 
-    return size;
+static inline size_t get_offset(struct cte *old, struct cte *next)
+{
+    return (old->mapping_info.pte - get_address(&next->cap)) / get_pte_size();
 }
 
 /*
  * compile_vaddr returns the lowest address that is addressed by entry 'entry'
  * in page table 'ptable'
  */
-genvaddr_t compile_vaddr(struct cte *ptable, size_t entry)
+errval_t compile_vaddr(struct cte *ptable, size_t entry, genvaddr_t *retvaddr)
 {
     if (!type_is_vnode(ptable->cap.type)) {
         return SYS_ERR_VNODE_TYPE;
     }
 
     genvaddr_t vaddr = 0;
-    size_t sw = BASE_PAGE_BITS;
+    // shift at least by BASE_PAGE_BITS for first vaddr part
+    size_t shift = BASE_PAGE_BITS;
+
     // figure out how much we need to shift (assuming that
     // compile_vaddr can be used on arbitrary page table types)
     // A couple of cases have fallthroughs in order to avoid having
     // multiple calls to vnode_objbits with the same type argument.
     switch (ptable->cap.type) {
         case ObjType_VNode_x86_64_pml4:
-            sw += vnode_objbits(ObjType_VNode_x86_64_pdpt);
+            shift += vnode_objbits(ObjType_VNode_x86_64_pdpt);
         case ObjType_VNode_x86_64_pdpt:
-            sw += vnode_objbits(ObjType_VNode_x86_64_pdir);
+            shift += vnode_objbits(ObjType_VNode_x86_64_pdir);
         case ObjType_VNode_x86_64_pdir:
-            sw += vnode_objbits(ObjType_VNode_x86_64_ptable);
+            shift += vnode_objbits(ObjType_VNode_x86_64_ptable);
         case ObjType_VNode_x86_64_ptable:
             break;
+
         case ObjType_VNode_x86_32_pdpt:
-            sw += vnode_objbits(ObjType_VNode_x86_32_pdir);
+            shift += vnode_objbits(ObjType_VNode_x86_32_pdir);
         case ObjType_VNode_x86_32_pdir:
-            sw += vnode_objbits(ObjType_VNode_x86_32_ptable);
+            shift += vnode_objbits(ObjType_VNode_x86_32_ptable);
         case ObjType_VNode_x86_32_ptable:
             break;
+
         case ObjType_VNode_ARM_l2:
-            sw += vnode_objbits(ObjType_VNode_ARM_l1);
+            shift += vnode_objbits(ObjType_VNode_ARM_l1);
         case ObjType_VNode_ARM_l1:
             break;
+
         default:
-            assert(0);
+            return SYS_ERR_VNODE_TYPE;
     }
+
     size_t mask = (1ULL<<vnode_objbits(ptable->cap.type))-1;
-    printf("entry = %zd\nmask = %zd\nsw = %zd\nentry & mask = %zd\n", entry, mask, sw, entry & mask);
-    vaddr = ((genvaddr_t)(entry & mask)) << sw;
+    vaddr = ((genvaddr_t)(entry & mask)) << shift;
 
     // add next piece of virtual address until we are at root page table
     struct cte *old = ptable;
     struct cte *next;
     errval_t err;
-    printf("vaddr = 0x%"PRIxGENVADDR", sw = %zd, entry = %zd\n", vaddr, sw, entry);
-    while (!is_root_pt(ptable->cap.type))
+    while (!is_root_pt(old->cap.type))
     {
-        int result;
-        err = mdb_find_range(0,
-                local_phys_to_gen_phys((lpaddr_t)old->mapping_info.pte),
-                1, MDB_RANGE_FOUND_SURROUNDING, &next,
-                &result);
+        err = find_next_ptable(old, &next);
         if (err_is_fail(err)) {
-            printf("error in compile_vaddr: mdb_find_range: 0x%"PRIxERRV"\n", err);
-            return 0;
-        }
-        if (result != MDB_RANGE_FOUND_SURROUNDING) {
-            printf("could not find cap associated with 0x%"PRIxLVADDR"\n", old->mapping_info.pte);
-            return 0;
+            return err;
         }
-        sw += vnode_objbits(old->cap.type);
-        size_t offset = old->mapping_info.pte - get_address(&next->cap);
-        printf("vaddr = 0x%"PRIxGENVADDR", sw = %zd, offset = %zd\n", vaddr, sw, offset);
+        // calculate offset into next level ptable
+        size_t offset = get_offset(old, next);
+        // shift new part of vaddr by old shiftwidth + #entries of old ptable
+        shift += vnode_entry_bits(old->cap.type);
+
         mask = (1ULL<<vnode_objbits(next->cap.type))-1;
-        vaddr |= ((offset & mask) << sw);
+        vaddr |= ((offset & mask) << shift);
         old = next;
     }
 
-    return vaddr;
+    *retvaddr = vaddr;
+    return SYS_ERR_OK;
 }
index 233a58c..23140af 100644 (file)
@@ -123,6 +123,8 @@ static errval_t alloc_vnode(struct pmap_x86 *pmap, struct vnode *root,
         return err_push(err, LIB_ERR_VNODE_CREATE);
     }
 
+    // TODO: setup mapping size
+
     // Map it
     err = vnode_map(root->u.vnode.cap, newvnode->u.vnode.cap, entry,
                     PTABLE_ACCESS_DEFAULT, 0);
@@ -217,6 +219,8 @@ static errval_t do_map(struct pmap_x86 *pmap, genvaddr_t vaddr,
     errval_t err;
     paging_x86_64_flags_t pmap_flags = vregion_to_pmap_flag(flags);
 
+    // TODO: setup mapping info
+
     for (size_t i = offset; i < offset + size; i += X86_64_BASE_PAGE_SIZE) {
 
         // Get the page table
@@ -243,6 +247,7 @@ static errval_t do_map(struct pmap_x86 *pmap, genvaddr_t vaddr,
 
         // Map entry into the page table in the kernel
         uint32_t entry = X86_64_PTABLE_BASE(vaddr);
+        printf("mapping vaddr = 0x%"PRIxGENVADDR"\n", vaddr);
         err = vnode_map(ptable->u.vnode.cap, frame, entry, pmap_flags, i);
         if (err_is_fail(err)) {
             return err_push(err, LIB_ERR_VNODE_MAP);
@@ -452,6 +457,9 @@ static errval_t modify_flags(struct pmap *pmap, genvaddr_t vaddr, size_t size,
     struct pmap_x86 *x86 = (struct pmap_x86 *)pmap;
     size = ROUND_UP(size, X86_64_BASE_PAGE_SIZE);
 
+    // TODO: reset mapping info
+    // XXX: need new copy of cap?
+
     for (size_t i = 0; i < size; i += X86_64_BASE_PAGE_SIZE) {
         // Find the page table
         struct vnode *ptable = find_ptable(x86, vaddr + i);