x86_64: fixed unmap last leaf, added code to allow users to easily map large/huge...
authorSimon Gerber <simon.gerber@hp.com>
Tue, 17 Jun 2014 00:19:33 +0000 (17:19 -0700)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Thu, 30 Apr 2015 19:19:27 +0000 (21:19 +0200)
Signed-off-by: Simon Gerber <simon.gerber@hp.com>

include/barrelfish/vspace_common.h
kernel/arch/x86_64/page_mappings_arch.c
lib/barrelfish/target/x86_64/pmap_target.c
lib/barrelfish/vspace/utils.c
lib/barrelfish/vspace/vregion.c

index 804838b..6b6b899 100644 (file)
@@ -5,6 +5,7 @@
 
 /*
  * Copyright (c) 2009, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2014, HP Labs.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -54,6 +55,11 @@ errval_t vspace_map_one_frame_attr(void **retaddr, size_t size,
                                    struct capref frame, vregion_flags_t flags,
                                    struct memobj **retmemobj,
                                    struct vregion **retvregion);
+errval_t vspace_map_one_frame_attr_aligned(void **retaddr, size_t size,
+                                   struct capref frame, vregion_flags_t flags,
+                                   size_t alignment,
+                                   struct memobj **retmemobj,
+                                   struct vregion **retvregion);
 errval_t vspace_map_one_frame(void **retaddr, size_t size, struct capref frame,
                               struct memobj **retmemobj,
                               struct vregion **retvregion);
index d8ead39..aaaafd2 100644 (file)
@@ -5,6 +5,7 @@
 
 /*
  * Copyright (c) 2010-2013 ETH Zurich.
+ * Copyright (c) 2014, HP Labs.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -483,8 +484,8 @@ void paging_dump_tables(struct dcb *dispatcher)
 {
     lvaddr_t root_pt = local_phys_to_mem(dispatcher->vspace);
 
-    // loop over pdpts
-    for (int pdpt_index = 0; pdpt_index < X86_64_PTABLE_SIZE-1; pdpt_index++) {
+    // loop over pdpts (ignore kernel space 508--511)
+    for (int pdpt_index = 0; pdpt_index < X86_64_PTABLE_SIZE-4; pdpt_index++) {
 
         union x86_64_pdir_entry *pdpt = (union x86_64_pdir_entry *)root_pt + pdpt_index;
         if (!pdpt->raw) { continue; }
index 75108c2..e8eb30a 100644 (file)
@@ -92,16 +92,29 @@ static bool has_vnode(struct vnode *root, uint32_t entry, size_t len)
 
     uint32_t end_entry = entry + len;
 
+    // region we check [entry .. end_entry)
+
     for (n = root->u.vnode.children; n; n = n->next) {
-        if (n->is_vnode && n->entry == entry) {
+        // n is page table, we need to check if it's anywhere inside the
+        // region to check [entry .. end_entry)
+        // this amounts to n->entry == entry for len = 1
+        if (n->is_vnode && n->entry >= entry && n->entry < end_entry) {
             return true;
         }
-        // n is frame
+        // n is frame [n->entry .. end)
+        // 3 cases:
+        // 1) entry < n->entry && end_entry >= end --> n is a strict subset of
+        // our region
+        // 2) entry inside n (entry >= n->entry && entry < end)
+        // 3) end_entry inside n (end_entry >= n->entry && end_entry < end)
         uint32_t end = n->entry + n->u.frame.pte_count;
-        if (n->entry < entry && end > end_entry) {
+        if (entry < n->entry && end_entry >= end) {
+            return true;
+        }
+        if (entry >= n->entry && entry < end) {
             return true;
         }
-        if (n->entry >= entry && n->entry < end_entry) {
+        if (end_entry > n->entry && end_entry < end) {
             return true;
         }
     }
@@ -391,7 +404,8 @@ static errval_t do_single_map(struct pmap_x86 *pmap, genvaddr_t vaddr,
         err = get_ptable(pmap, vaddr, &ptable);
         table_base = X86_64_PTABLE_BASE(vaddr);
     }
-    
+    assert(ptable->is_vnode);
+
     if (err_is_fail(err)) {
         return err_push(err, LIB_ERR_PMAP_GET_PTABLE);
     }
@@ -888,7 +902,9 @@ static errval_t unmap(struct pmap *pmap, genvaddr_t vaddr, size_t size,
         }
 
         // unmap remaining part
-        c = get_addr_prefix(vend, map_bits) - get_addr_prefix(vaddr, map_bits);
+        // subtracting 9 from map_bits to get #ptes in last-level table
+        // instead of 2nd-to-last.
+        c = get_addr_prefix(vend, map_bits-9) - get_addr_prefix(vaddr, map_bits-9);
         assert(c < X86_64_PTABLE_SIZE);
         if (c) {
             err = do_single_unmap(x86, vaddr, c, true);
index 0e47370..7bfcf98 100644 (file)
@@ -326,6 +326,20 @@ errval_t vspace_map_one_frame_attr(void **retaddr, size_t size,
                                    struct memobj **retmemobj,
                                    struct vregion **retvregion)
 {
+    return vspace_map_one_frame_attr_aligned(retaddr, size,
+            frame, flags, 0, retmemobj, retvregion);
+}
+
+/**
+ * \brief Wrapper for creating and mapping a memory object
+ * of type one frame with specific flags and a specific alignment
+ */
+errval_t vspace_map_one_frame_attr_aligned(void **retaddr, size_t size,
+                                   struct capref frame, vregion_flags_t flags,
+                                   size_t alignment,
+                                   struct memobj **retmemobj,
+                                   struct vregion **retvregion)
+{
     errval_t err1, err2;
     struct memobj *memobj   = NULL;
     struct vregion *vregion = NULL;
@@ -357,7 +371,8 @@ errval_t vspace_map_one_frame_attr(void **retaddr, size_t size,
         goto error;
     }
 
-    err1 = vregion_map(vregion, get_current_vspace(), memobj, 0, size, flags);
+    err1 = vregion_map_aligned(vregion, get_current_vspace(), memobj, 0, size,
+            flags, alignment);
     if (err_is_fail(err1)) {
         err1 = err_push(err1, LIB_ERR_VREGION_MAP);
         goto error;
index 2227943..1171333 100644 (file)
@@ -8,6 +8,7 @@
 
 /*
  * Copyright (c) 2009, 2010, ETH Zurich.
+ * Copyright (c) 2014, HP Labs.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -60,6 +61,10 @@ errval_t vregion_map_aligned(struct vregion *vregion, struct vspace* vspace,
     // Add to memobj
     err = memobj->f.map_region(memobj, vregion);
     if (err_is_fail(err)) {
+        // remove memobj from region if map fails, otherwise we'll get a
+        // follow up error if client code call vregion_destroy() on the
+        // region.
+        vregion->memobj = NULL;
         return err_push(err, LIB_ERR_MEMOBJ_MAP_REGION);
     }