x86_32: Implemented missing parts of new kernel memory system.
authorSimon Gerber <simugerber@student.ethz.ch>
Thu, 22 Nov 2012 14:53:25 +0000 (15:53 +0100)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Tue, 29 Jan 2013 10:31:04 +0000 (11:31 +0100)
12 files changed:
include/arch/x86_32/barrelfish/invocations_arch.h
include/arch/x86_32/barrelfish_kpi/paging_arch.h
include/target/x86_32/barrelfish_kpi/paging_target.h
kernel/arch/x86_32/page_mappings_arch.c
kernel/arch/x86_32/syscall.c
kernel/arch/x86_64/page_mappings_arch.c
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_32/pmap_target.c
lib/spawndomain/arch/x86/spawn_arch.c

index d44e3e9..bb75c09 100644 (file)
@@ -220,13 +220,39 @@ static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap,
                     invoke_cptr, cap, bits).error;
 }
 
-static inline errval_t invoke_vnode_unmap(struct capref cap, size_t entry)
+// XXX: workaround for an inlining bug in gcc 4.3.4
+#if defined(__GNUC__) \
+    && __GNUC__ == 4 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 4
+static __attribute__ ((noinline,unused)) errval_t
+invoke_vnode_map(struct capref ptable, capaddr_t slot, capaddr_t from,
+                 int frombits, uintptr_t flags, uintptr_t offset, uintptr_t pte_count)
+#else
+static inline errval_t invoke_vnode_map(struct capref ptable, capaddr_t slot,
+                                        capaddr_t from, int frombits, uintptr_t flags,
+                                        uintptr_t offset, uintptr_t pte_count)
+#endif
+{
+    uint8_t invoke_bits = get_cap_valid_bits(ptable);
+    capaddr_t invoke_cptr = get_cap_addr(ptable) >> (CPTR_BITS - invoke_bits);
+
+    assert(slot <= 0xffff);
+    assert(frombits <= 0xff);
+
+    // XXX: needs check of flags, offset, and pte_count sizes
+    // XXX: flag transfer breaks for PAE (flags are 64 bits for PAE)
+    return syscall7((invoke_bits << 16) | (VNodeCmd_Map << 8) | SYSCALL_INVOKE,
+                    invoke_cptr, from, (slot << 16) | frombits,
+                    flags, offset, pte_count).error;
+}
+
+
+static inline errval_t invoke_vnode_unmap(struct capref cap, size_t entry, size_t pte_count)
 {
     uint8_t invoke_bits = get_cap_valid_bits(cap);
     capaddr_t invoke_cptr = get_cap_addr(cap) >> (CPTR_BITS - invoke_bits);
 
-    return syscall3((invoke_bits << 16) | (VNodeCmd_Unmap << 8) | SYSCALL_INVOKE,
-                    invoke_cptr, entry).error;
+    return syscall4((invoke_bits << 16) | (VNodeCmd_Unmap << 8) | SYSCALL_INVOKE,
+                    invoke_cptr, entry, pte_count).error;
 }
 
 /**
@@ -417,6 +443,20 @@ static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap,
     return sysret.error;
 }
 
+static inline errval_t invoke_kernel_dump_ptables(struct capref kern_cap,
+                                                  struct capref dispcap)
+{
+    uint8_t invoke_bits = get_cap_valid_bits(kern_cap);
+    capaddr_t invoke_cptr = get_cap_addr(kern_cap) >> (CPTR_BITS - invoke_bits);
+
+    capaddr_t dispcaddr = get_cap_addr(dispcap);
+    struct sysret sysret =
+        syscall3((invoke_bits << 16) | (KernelCmd_DumpPTables << 8) | SYSCALL_INVOKE,
+                 invoke_cptr,dispcaddr);
+    return sysret.error;
+}
+
+
 static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
 {
     uint8_t invoke_bits = get_cap_valid_bits(notify_cap);
index 71569eb..d36f857 100644 (file)
@@ -56,4 +56,6 @@
 #define PTABLE_ACCESS_DEFAULT   X86_32_PTABLE_ACCESS_DEFAULT
 #define PTABLE_ACCESS_READONLY  X86_32_PTABLE_ACCESS_READONLY
 
+#define PTABLE_ENTRY_SIZE       X86_32_PTABLE_ENTRY_SIZE
+
 #endif // ARCH_X86_32_BARRELFISH_KPI_PAGING_H
index 55c255b..e511c3a 100644 (file)
@@ -87,6 +87,8 @@ typedef uint32_t paging_x86_32_flags_t;
 
 #endif
 
+#define X86_32_PTABLE_ENTRY_SIZE   sizeof(union x86_32_pdir_entry)
+
 #ifdef CONFIG_PAE
 #define X86_32_PDPTE_BASE(base)        (((uint32_t)(base) >> 30) & X86_32_PDPTE_MASK)
 #define X86_32_PDIR_BASE(base)         (((uint32_t)(base) >> 21) & X86_32_PTABLE_MASK)
index f43dad6..66c0378 100644 (file)
 #include <dispatch.h>
 #include <target/x86_32/paging_kernel_target.h>
 #include <target/x86_32/offsets_target.h>
+#include <paging_kernel_arch.h>
+#include <string.h>
+#include <cap_predicates.h>
+
+static inline struct cte *cte_for_cap(struct capability *cap)
+{
+    return (struct cte *) (cap - offsetof(struct cte, cap));
+}
 
 #ifdef CONFIG_PAE
 /// Map within a x86_32 pdpt
 static errval_t x86_32_pdpt(struct capability *dest, cslot_t slot,
-                            struct capability * src, uintptr_t param1,
-                            uintptr_t param2)
+                            struct capability * src, uintptr_t flags,
+                            uintptr_t offset, uintptr_t pte_count)
 {
     if (slot >= X86_32_PTABLE_SIZE) { // Slot within page table
         return SYS_ERR_VNODE_SLOT_INVALID;
     }
 
+    if (pte_count > 1) { // disallow multiple pdpt mappings at a time
+        return SYS_ERR_VM_MAP_SIZE;
+    }
+
     if (src->type != ObjType_VNode_x86_32_pdir) { // Right mapping
         return SYS_ERR_WRONG_MAPPING;
     }
@@ -42,6 +54,12 @@ static errval_t x86_32_pdpt(struct capability *dest, cslot_t slot,
     union x86_32_pdpte_entry *entry =
         (union x86_32_pdpte_entry *)dest_lv + slot;
 
+    // Set metadata
+    struct cte *src_cte = cte_for_cap(src);
+    src_cte->mapping_info.pte = dest_lp + slot * sizeof(union x86_32_pdpte_entry);
+    src_cte->mapping_info.pte_count = pte_count;
+    src_cte->mapping_info.offset = offset;
+
     // Source
     genpaddr_t src_gp   = src->u.vnode_x86_32_pdir.base;
     lpaddr_t src_lp     = gen_phys_to_local_phys(src_gp);
@@ -54,13 +72,18 @@ static errval_t x86_32_pdpt(struct capability *dest, cslot_t slot,
 
 /// Map within a x86_32 pdir
 static errval_t x86_32_pdir(struct capability *dest, cslot_t slot,
-                            struct capability * src, uintptr_t param1,
-                            uintptr_t param2)
+                            struct capability * src, uintptr_t flags,
+                            uintptr_t offset, uintptr_t pte_count)
 {
     if (slot >= X86_32_PTABLE_SIZE) { // Slot within page table
         return SYS_ERR_VNODE_SLOT_INVALID;
     }
 
+    if (pte_count > 1) { // disallow more than one page at a time
+        // XXX: this prevents mapping multiple superpages at a time
+        return SYS_ERR_VM_MAP_SIZE;
+    }
+
 #ifndef CONFIG_PAE
     if(slot >= X86_32_PDIR_BASE(X86_32_MEMORY_OFFSET)) { // Kernel mapped here
         return SYS_ERR_VNODE_SLOT_RESERVED;
@@ -78,7 +101,15 @@ static errval_t x86_32_pdir(struct capability *dest, cslot_t slot,
     union x86_32_pdir_entry *entry =
         (union x86_32_pdir_entry *)dest_lv + slot;
 
+    // Set metadata
+    struct cte *src_cte = cte_for_cap(src);
+    src_cte->mapping_info.pte = dest_lp + slot * sizeof(union x86_32_pdir_entry);
+    src_cte->mapping_info.pte_count = pte_count;
+    src_cte->mapping_info.offset = offset;
+
+
     // Source
+    // XXX: offset is ignored
     genpaddr_t src_gp   = src->u.vnode_x86_32_pdir.base;
     lpaddr_t src_lp     = gen_phys_to_local_phys(src_gp);
     paging_x86_32_map_table(entry, src_lp);
@@ -88,21 +119,27 @@ static errval_t x86_32_pdir(struct capability *dest, cslot_t slot,
 
 /// Map within a x86_32 ptable
 static errval_t x86_32_ptable(struct capability *dest, cslot_t slot,
-                              struct capability * src, uintptr_t param1,
-                              uintptr_t param2)
+                              struct capability * src, uintptr_t uflags,
+                              uintptr_t offset, uintptr_t pte_count)
 {
     if (slot >= X86_32_PTABLE_SIZE) { // Slot within page table
         return SYS_ERR_VNODE_SLOT_INVALID;
     }
 
+    cslot_t last_slot = slot + pte_count;
+
+    if (last_slot > X86_32_PTABLE_SIZE) {
+        printf("slot = %"PRIuCSLOT", last_slot = %"PRIuCSLOT", PTABLE_SIZE = %d\n", slot, last_slot, X86_32_PTABLE_SIZE);
+        return SYS_ERR_VM_MAP_SIZE;
+    }
+
     if (src->type != ObjType_Frame &&
         src->type != ObjType_DevFrame) { // Right mapping
         return SYS_ERR_WRONG_MAPPING;
     }
 
     // check offset within frame
-    genpaddr_t offset = param2;
-    if (offset + X86_32_BASE_PAGE_SIZE > ((genpaddr_t)1 << src->u.frame.bits)) {
+    if (offset + pte_count * X86_32_BASE_PAGE_SIZE > get_size(src)) {
         return SYS_ERR_FRAME_OFFSET_INVALID;
     }
 
@@ -111,30 +148,40 @@ static errval_t x86_32_ptable(struct capability *dest, cslot_t slot,
     paging_x86_32_flags_t flags =
         paging_x86_32_cap_to_page_flags(src->rights);
     // Mask with provided access rights mask
-    flags = paging_x86_32_mask_attrs(flags, X86_32_PTABLE_ACCESS(param1));
+    flags = paging_x86_32_mask_attrs(flags, X86_32_PTABLE_ACCESS(uflags));
     // Add additional arch-specific flags
-    flags |= X86_32_PTABLE_FLAGS(param1);
+    flags |= X86_32_PTABLE_FLAGS(uflags);
     // Unconditionally mark the page present
     flags |= X86_32_PTABLE_PRESENT;
 
-    // Destination
-    genpaddr_t dest_gp   = dest->u.vnode_x86_32_ptable.base;
+    // Convert destination base address
+    genpaddr_t dest_gp   = get_address(dest);
     lpaddr_t dest_lp     = gen_phys_to_local_phys(dest_gp);
     lvaddr_t dest_lv     = local_phys_to_mem(dest_lp);
-    union x86_32_ptable_entry *entry =
-        (union x86_32_ptable_entry *)dest_lv + slot;
+    // Convert source base address
+    genpaddr_t src_gp   = get_address(src) + offset;
+    lpaddr_t src_lp     = gen_phys_to_local_phys(src_gp);
+    // Set metadata
+    struct cte *src_cte = cte_for_cap(src);
+    src_cte->mapping_info.pte = dest_lp + slot * sizeof(union x86_32_ptable_entry);
+    src_cte->mapping_info.pte_count = pte_count;
+    src_cte->mapping_info.offset = offset;
 
-    /* FIXME: Flush TLB if the page is already present
-     * in the meantime, since we don't do this, we just assert that
-     * we never reuse a VA mapping */
-    if (X86_32_IS_PRESENT(entry)) {
-        panic("Trying to map into an already present page NYI.");
-    }
 
-    // Carry out the page mapping
-    genpaddr_t src_gp   = src->u.frame.base + offset;
-    lpaddr_t src_lp     = gen_phys_to_local_phys(src_gp);
-    paging_x86_32_map(entry, src_lp, flags);
+    for (; slot < last_slot; slot++, offset += X86_32_BASE_PAGE_SIZE) {
+        union x86_32_ptable_entry *entry =
+            (union x86_32_ptable_entry *)dest_lv + slot;
+
+        /* FIXME: Flush TLB if the page is already present
+         * in the meantime, since we don't do this, we just assert that
+         * we never reuse a VA mapping */
+        if (X86_32_IS_PRESENT(entry)) {
+            panic("Trying to map into an already present page NYI.");
+        }
+
+        // Carry out the page mapping
+        paging_x86_32_map(entry, src_lp + offset, flags);
+    }
 
     return SYS_ERR_OK;
 }
@@ -142,7 +189,8 @@ static errval_t x86_32_ptable(struct capability *dest, cslot_t slot,
 typedef errval_t (*mapping_handler_t)(struct capability *dest_cap,
                                       cslot_t dest_slot,
                                       struct capability *src_cap,
-                                      uintptr_t param1, uintptr_t param2);
+                                      uintptr_t flags, uintptr_t offset,
+                                      uintptr_t pte_count);
 
 /// Dispatcher table for the type of mapping to create
 static mapping_handler_t handler[ObjType_Num] = {
@@ -153,10 +201,13 @@ static mapping_handler_t handler[ObjType_Num] = {
     [ObjType_VNode_x86_32_ptable] = x86_32_ptable,
 };
 
+#define DIAGNOSTIC_ON_ERROR 1
+#define RETURN_ON_ERROR 1
+
 /// Create page mappings
 errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
-                            struct cte *src_cte, uintptr_t param1,
-                            uintptr_t param2)
+                            struct cte *src_cte, uintptr_t flags,
+                            uintptr_t offset, uintptr_t pte_count)
 {
     assert(type_is_vnode(dest_vnode_cte->cap.type));
 
@@ -165,13 +216,158 @@ errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
     mapping_handler_t handler_func = handler[dest_cap->type];
 
     assert(handler_func != NULL);
-    return handler_func(dest_cap, dest_slot, src_cap, param1, param2);
+
+    if (src_cte->mapping_info.pte) {
+        // already mapped
+#if DIAGNOSTIC_ON_ERROR
+        printf("caps_copy_to_vnode: this copy is already mapped @0x%lx\n", src_cte->mapping_info.pte);
+#endif
+#if RETURN_ON_ERROR
+        return SYS_ERR_VM_ALREADY_MAPPED;
+#endif
+    }
+
+    cslot_t last_slot = dest_slot + pte_count;
+
+    // TODO: PAE
+    if (last_slot > X86_32_PTABLE_SIZE) {
+        // requested map overlaps leaf page table
+#if DIAGNOSTIC_ON_ERROR
+        printf("caps_copy_to_vnode: requested mapping spans multiple leaf page tables\n");
+#endif
+#if RETURN_ON_ERROR
+        return SYS_ERR_VM_RETRY_SINGLE;
+#endif
+    }
+
+    genvaddr_t vaddr;
+    compile_vaddr(dest_vnode_cte, dest_slot, &vaddr);
+    printf("caps_copy_to_vnode: mapping %lu pages (slots %"PRIuCSLOT" to %"PRIuCSLOT") to 0x%"PRIxGENVADDR"\n",
+            pte_count, dest_slot, last_slot, vaddr);
+
+    errval_t r = handler_func(dest_cap, dest_slot, src_cap, flags, offset, pte_count);
+    if (err_is_fail(r)) {
+        printf("caps_copy_to_vnode: handler func returned %ld\n", r);
+    }
+#if 1
+    else {
+        printf("mapping_info.pte       = 0x%lx\n", src_cte->mapping_info.pte);
+        printf("mapping_info.offset    = 0x%"PRIx64"\n", src_cte->mapping_info.offset);
+        printf("mapping_info.pte_count = %zu\n", src_cte->mapping_info.pte_count);
+    }
+#endif
+    return r;
+}
+
+size_t do_unmap(lvaddr_t pt, cslot_t slot, genvaddr_t vaddr, size_t num_pages)
+{
+    size_t unmapped_pages = 0;
+    union x86_32_ptable_entry *ptentry = (union x86_32_ptable_entry *)pt + slot;
+    for (int i = 0; i < num_pages; i++) {
+        ptentry++->raw = 0;
+        unmapped_pages++;
+    }
+    return unmapped_pages;
 }
 
-errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
+static inline void read_pt_entry(struct capability *pgtable, size_t slot,
+        genpaddr_t *mapped_addr, lpaddr_t *pte,
+        void **entry)
 {
     assert(type_is_vnode(pgtable->type));
 
+    genpaddr_t paddr;
+    lpaddr_t pte_;
+    void *entry_;
+
+    genpaddr_t gp = get_address(pgtable);
+    lpaddr_t lp = gen_phys_to_local_phys(gp);
+    lvaddr_t lv = local_phys_to_mem(lp);
+
+    // get paddr
+    switch (pgtable->type) {
+        case ObjType_VNode_x86_32_pdpt:
+        case ObjType_VNode_x86_32_pdir: {
+                                            union x86_32_pdir_entry *e =
+                                                (union x86_32_pdir_entry *)lv + slot;
+                                            paddr = e->d.base_addr << BASE_PAGE_BITS;
+                                            entry_ = e;
+                                            pte_ = lp + slot * sizeof(union x86_32_pdir_entry);
+                                            break;
+                                        }
+        case ObjType_VNode_x86_32_ptable: {
+                                              union x86_32_ptable_entry *e =
+                                                  (union x86_32_ptable_entry *)lv + slot;
+                                              paddr = e->base.base_addr << BASE_PAGE_BITS;
+                                              entry_ = e;
+                                              pte_ = lp + slot * sizeof(union x86_32_ptable_entry);
+                                              break;
+                                          }
+        default:
+                                          assert(!"Should not get here");
+    }
+
+    if (mapped_addr) {
+        *mapped_addr = paddr;
+    }
+    if (pte) {
+        *pte = pte_;
+    }
+    if (entry) {
+        *entry = entry_;
+    }
+}
+
+errval_t page_mappings_unmap(struct capability *pgtable, size_t slot, size_t num_pages)
+{
+    assert(type_is_vnode(pgtable->type));
+    printf("page_mappings_unmap(%zd pages, slot = %zd)\n", num_pages, slot);
+
+    // get page table entry data
+    genpaddr_t paddr;
+    lvaddr_t pte;
+    read_pt_entry(pgtable, slot, &paddr, &pte, NULL);
+    lvaddr_t pt = local_phys_to_mem(gen_phys_to_local_phys(get_address(pgtable)));
+
+    // get virtual address of first page
+    // TODO: error checking
+    genvaddr_t vaddr;
+    struct cte *leaf_pt = cte_for_cap(pgtable);
+    compile_vaddr(leaf_pt, slot, &vaddr);
+    printf("vaddr = 0x%"PRIxGENVADDR"\n", vaddr);
+    printf("num_pages = %zu\n", num_pages);
+
+    // get cap for mapping
+    struct cte *mem;
+    errval_t err = lookup_cap_for_mapping(paddr, pte, &mem);
+    if (err_is_fail(err)) {
+        printf("page_mappings_unmap: %ld\n", err);
+        return err;
+    }
+    //printf("state before unmap: mapped_pages = %zd\n", mem->mapping_info.mapped_pages);
+    //printf("state before unmap: num_pages    = %zd\n", num_pages);
+
+    if (num_pages != mem->mapping_info.pte_count) {
+        // want to unmap a different amount of pages than was mapped
+        return SYS_ERR_VM_MAP_SIZE;
+    }
+
+    do_unmap(pt, slot, vaddr, num_pages);
+
+    // update mapping info
+    memset(&mem->mapping_info, 0, sizeof(struct mapping_info));
+
+    do_tlb_flush();
+
+    return SYS_ERR_OK;
+}
+
+__attribute__((unused))
+static errval_t old_page_mappings_unmap(struct capability *pgtable, size_t slot, size_t pte_count)
+{
+    printf("page_mappings_unmap(%zd)\n", pte_count);
+    assert(type_is_vnode(pgtable->type));
+
     switch (pgtable->type) {
     case ObjType_VNode_x86_32_pdpt: {
         genpaddr_t gp = pgtable->u.vnode_x86_32_pdpt.base;
@@ -215,3 +411,43 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
 
     return SYS_ERR_OK;
 }
+
+void dump_hw_page_tables(struct dcb *dispatcher)
+{
+    printf("dump_hw_page_tables\n");
+    lvaddr_t root_pt = local_phys_to_mem(dispatcher->vspace);
+
+#ifdef CONFIG_PAE
+    // loop over pdpt entries
+    for (int pdir_index = 0; pdir_index < X86_64_PDPTE_SIZE; pdir_index++) {
+        // get pdir
+        union x86_32_pdpte_entry *pdir = (union x86_64_pdir_entry *)root_pt + pdir_index;
+        if (!pdir->raw) { continue; }
+        genpaddr_t pdir_gp = pdir->d.base_addr << BASE_PAGE_BITS;
+        lvaddr_t pdir_lv = local_phys_to_mem(gen_phys_to_local_phys(pdir_gp));
+#else
+        int pdir_index = 0;
+        lvaddr_t pdir_lv = root_pt;
+#endif
+
+        for (int ptable_index = 0; ptable_index < X86_32_PDIR_SIZE; ptable_index++) {
+            // get ptable
+            union x86_32_pdir_entry *ptable = (union x86_32_pdir_entry *)pdir_lv + ptable_index;
+            if (!ptable->raw) { continue; }
+            genpaddr_t ptable_gp = ptable->d.base_addr << BASE_PAGE_BITS;
+            lvaddr_t ptable_lv = local_phys_to_mem(gen_phys_to_local_phys(ptable_gp));
+
+            for (int entry = 0; entry < X86_32_PTABLE_SIZE; entry++) {
+                union x86_32_ptable_entry *e =
+                    (union x86_32_ptable_entry *)ptable_lv + entry;
+                genpaddr_t paddr = e->base.base_addr << BASE_PAGE_BITS;
+                if (!paddr) {
+                    continue;
+                }
+                printf("%d.%d.%d: 0x%"PRIxGENPADDR"\n", pdir_index, ptable_index, entry, paddr);
+            }
+        }
+#ifdef CONFIG_PAE
+    } // endfor PDPT entries
+#endif
+}
index 0edf4eb..175b2f1 100644 (file)
@@ -212,11 +212,28 @@ static struct sysret handle_revoke(struct capability *root,
     return  handle_revoke_common(root, args, false);
 }
 
+static struct sysret handle_map(struct capability *pgtable,
+                                int cmd, uintptr_t *args)
+{
+    /* Retrive arguments */
+    capaddr_t  source_cptr   = args[0];
+    capaddr_t dest_slot      = args[1] >> 16;
+    int      source_vbits  = args[1] & 0xff;
+    uintptr_t flags, offset,pte_count;
+    flags = args[2];
+    offset = args[3];
+    pte_count = args[4];
+
+    return sys_map(pgtable, dest_slot, source_cptr, source_vbits,
+                   flags, offset, pte_count);
+}
+
 static struct sysret handle_unmap(struct capability *pgtable,
                                   int cmd, uintptr_t *args)
 {
     size_t entry = args[0];
-    errval_t err = page_mappings_unmap(pgtable, entry);
+    size_t pte_count = args[1];
+    errval_t err = page_mappings_unmap(pgtable, entry, pte_count);
     return SYSRET(err);
 }
 
@@ -642,6 +659,35 @@ static struct sysret handle_ipi_notify_send(struct capability *cap,
 }
 #endif
 
+static struct sysret kernel_dump_ptables(struct capability *cap,
+                                         int cmd, uintptr_t *args)
+{
+    assert(cap->type == ObjType_Kernel);
+
+    printf("kernel_dump_ptables\n");
+
+    capaddr_t dispcaddr = args[0];
+
+    struct cte *dispcte;
+    errval_t err = caps_lookup_slot(&dcb_current->cspace.cap, dispcaddr, CPTR_BITS,
+                           &dispcte, CAPRIGHTS_WRITE);
+    if (err_is_fail(err)) {
+        printf("failed to lookup dispatcher cap\n");
+        return SYSRET(err_push(err, SYS_ERR_DISP_FRAME));
+    }
+    struct capability *dispcap = &dispcte->cap;
+    if (dispcap->type != ObjType_Dispatcher) {
+        printf("dispcap is not dispatcher cap\n");
+        return SYSRET(err_push(err, SYS_ERR_DISP_FRAME_INVALID));
+    }
+
+    struct dcb *dispatcher = dispcap->u.dispatcher.dcb;
+
+    dump_hw_page_tables(dispatcher);
+
+    return SYSRET(SYS_ERR_OK);
+}
+
 typedef struct sysret (*invocation_handler_t)(struct capability *to,
                                               int cmd, uintptr_t *args);
 
@@ -672,12 +718,15 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [CNodeCmd_Revoke] = handle_revoke,
     },
     [ObjType_VNode_x86_32_pdpt] = {
+        [VNodeCmd_Map]   = handle_map,
         [VNodeCmd_Unmap] = handle_unmap,
     },
     [ObjType_VNode_x86_32_pdir] = {
+        [VNodeCmd_Map]   = handle_map,
         [VNodeCmd_Unmap] = handle_unmap,
     },
     [ObjType_VNode_x86_32_ptable] = {
+        [VNodeCmd_Map]   = handle_map,
         [VNodeCmd_Unmap] = handle_unmap,
     },
     [ObjType_Kernel] = {
@@ -702,11 +751,12 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
 #ifdef __scc__
         [KernelCmd_Spawn_SCC_Core]   = monitor_spawn_scc_core,
         [KernelCmd_IPI_Register] = kernel_rck_register,
-        [KernelCmd_IPI_Delete]   = kernel_rck_delete
+        [KernelCmd_IPI_Delete]   = kernel_rck_delete,
 #else
         [KernelCmd_IPI_Register] = kernel_ipi_register,
-        [KernelCmd_IPI_Delete]   = kernel_ipi_delete
+        [KernelCmd_IPI_Delete]   = kernel_ipi_delete,
 #endif
+        [KernelCmd_DumpPTables]  = kernel_dump_ptables,
     },
     [ObjType_IRQTable] = {
         [IRQTableCmd_Set] = handle_irq_table_set,
index 358dcab..1893aaa 100644 (file)
@@ -302,72 +302,10 @@ static inline void read_pt_entry(struct capability *pgtable, size_t slot,
     }
 }
 
-static inline errval_t lookup_cap_for_mapping(genpaddr_t paddr, lvaddr_t pte, struct cte **retcte)
-{
-    // lookup matching cap
-    struct cte *mem, *last, *orig;
-    // find a cap for paddr
-    errval_t err = mdb_find_cap_for_address(paddr, &mem);
-    if (err_is_fail(err)) {
-        printf("could not find a cap for 0x%"PRIxGENPADDR" (%ld)\n", paddr, err);
-        return err;
-    }
-#if 0
-    printf("lookup request = 0x%"PRIxGENPADDR"\n", paddr);
-    printf("has_copies(mem) = %d\n", has_copies(mem));
-    printf("pte = 0x%lx\n", pte);
-    printf("0x%lx, %zd\n", get_address(&mem->cap), get_size(&mem->cap));
-    printf("mem->mapping_info.pte          = 0x%lx\n", mem->mapping_info.pte);
-    printf("mem->mapping_info.offset       = %zd\n", mem->mapping_info.offset);
-    printf("mem->mapping_info.pte_count    = %zd\n", mem->mapping_info.pte_count);
-    printf("mem = %p\n", mem);
-#endif
-
-    // look at all copies of mem
-    last = mem;
-    orig = mem;
-    // search backwards in tree
-    while (is_copy(&mem->cap, &last->cap)) {
-        struct capability *cap = &mem->cap;
-        struct mapping_info *map = &mem->mapping_info;
-        genpaddr_t base = get_address(cap);
-        // only match mappings that start where we want to unmap
-        if (base + map->offset == paddr && map->pte == pte)
-        {
-            // found matching cap
-            *retcte = mem;
-            return SYS_ERR_OK;
-        }
-        last = mem;
-        mem = mdb_predecessor(mem);
-    }
-    last = orig;
-    // search forward in tree
-    mem = mdb_successor(orig);
-    while (is_copy(&mem->cap, &last->cap)) {
-        struct capability *cap = &mem->cap;
-        struct mapping_info *map = &mem->mapping_info;
-        genpaddr_t base = get_address(cap);
-        // only match mappings that start where we want to unmap
-        if (base + map->offset == paddr && map->pte == pte)
-        {
-            // found matching cap
-            *retcte = mem;
-            return SYS_ERR_OK;
-        }
-        last = mem;
-        mem = mdb_successor(mem);
-    }
-
-    // if we get here, we have not found a matching cap
-    return SYS_ERR_CAP_NOT_FOUND;
-}
-
 static inline void clear_pt_entry(lvaddr_t pte) {
     ((union x86_64_pdir_entry *)pte)->raw = 0;
 }
 
-
 static inline lvaddr_t get_leaf_ptable_for_vaddr(genvaddr_t vaddr)
 {
     lvaddr_t root_pt = local_phys_to_mem(dcb_current->vspace);
index 63f2761..6af307e 100644 (file)
@@ -96,7 +96,7 @@ static inline size_t get_pte_size(void) {
 
 static inline size_t vnode_entry_bits(enum objtype type) {
 #ifdef CONFIG_PAE
-    else if (type == ObjType_VNode_x86_32_pdpt)
+    if (type == ObjType_VNode_x86_32_pdpt)
     {
         return 2;       // log2(X86_32_PDPTE_SIZE)
     }
@@ -106,8 +106,8 @@ static inline size_t vnode_entry_bits(enum objtype type) {
         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)
+    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)
     }
@@ -117,4 +117,16 @@ static inline size_t vnode_entry_bits(enum objtype type) {
     }
 }
 
+static inline void do_tlb_flush(void)
+{
+    // XXX: FIXME: Going to reload cr3 to flush the entire TLB.
+    // This is inefficient.
+    // The current implementation is also not multicore safe.
+    // We should only invalidate the affected entry using invlpg
+    // and figure out which remote tlbs to flush.
+    uint32_t cr3;
+    __asm__ __volatile__("mov %%cr3,%0" : "=a" (cr3) : );
+    __asm__ __volatile__("mov %0,%%cr3" :  : "a" (cr3));
+}
+
 #endif // KERNEL_ARCH_X86_32_PAGING_H
index 0879322..8e28a1a 100644 (file)
@@ -87,4 +87,16 @@ static inline size_t vnode_entry_bits(enum objtype type) {
     }
 }
 
+static inline void do_tlb_flush(void) {
+    // XXX: FIXME: Going to reload cr3 to flush the entire TLB.
+    // This is inefficient.
+    // The current implementation is also not multicore safe.
+    // We should only invalidate the affected entry using invlpg
+    // and figure out which remote tlbs to flush.
+    uint64_t cr3;
+    __asm__ __volatile__("mov %%cr3,%0" : "=a" (cr3) : );
+    __asm__ __volatile__("mov %0,%%cr3" :  : "a" (cr3));
+}
+
+
 #endif // KERNEL_ARCH_X86_64_PAGING_H
index 4ef2fa6..54a4f62 100644 (file)
@@ -27,5 +27,6 @@ struct mapping_info {
 struct cte;
 errval_t compile_vaddr(struct cte *ptable, size_t entry, genvaddr_t *retvaddr);
 errval_t unmap_capability(struct cte *mem);
+errval_t lookup_cap_for_mapping(genpaddr_t paddr, lvaddr_t pte, struct cte **retcte);
 
 #endif // PAGING_H
index f1146b8..3f87381 100644 (file)
@@ -139,14 +139,68 @@ errval_t unmap_capability(struct cte *mem)
 
     do_unmap(pt, slot, vaddr, mem->mapping_info.pte_count);
 
-    // XXX: FIXME: Going to reload cr3 to flush the entire TLB.
-    // This is inefficient.
-    // The current implementation is also not multicore safe.
-    // We should only invalidate the affected entry using invlpg
-    // and figure out which remote tlbs to flush.
-    uint64_t cr3;
-    __asm__ __volatile__("mov %%cr3,%0" : "=a" (cr3) : );
-    __asm__ __volatile__("mov %0,%%cr3" :  : "a" (cr3));
+    do_tlb_flush();
 
     return SYS_ERR_OK;
 }
+
+errval_t lookup_cap_for_mapping(genpaddr_t paddr, lvaddr_t pte, struct cte **retcte)
+{
+    // lookup matching cap
+    struct cte *mem, *last, *orig;
+    // find a cap for paddr
+    errval_t err = mdb_find_cap_for_address(paddr, &mem);
+    if (err_is_fail(err)) {
+        printf("could not find a cap for 0x%"PRIxGENPADDR" (%ld)\n", paddr, err);
+        return err;
+    }
+#if 0
+    printf("lookup request = 0x%"PRIxGENPADDR"\n", paddr);
+    printf("has_copies(mem) = %d\n", has_copies(mem));
+    printf("pte = 0x%lx\n", pte);
+    printf("0x%lx, %zd\n", get_address(&mem->cap), get_size(&mem->cap));
+    printf("mem->mapping_info.pte          = 0x%lx\n", mem->mapping_info.pte);
+    printf("mem->mapping_info.offset       = %zd\n", mem->mapping_info.offset);
+    printf("mem->mapping_info.pte_count    = %zd\n", mem->mapping_info.pte_count);
+    printf("mem = %p\n", mem);
+#endif
+
+    // look at all copies of mem
+    last = mem;
+    orig = mem;
+    // search backwards in tree
+    while (is_copy(&mem->cap, &last->cap)) {
+        struct capability *cap = &mem->cap;
+        struct mapping_info *map = &mem->mapping_info;
+        genpaddr_t base = get_address(cap);
+        // only match mappings that start where we want to unmap
+        if (base + map->offset == paddr && map->pte == pte)
+        {
+            // found matching cap
+            *retcte = mem;
+            return SYS_ERR_OK;
+        }
+        last = mem;
+        mem = mdb_predecessor(mem);
+    }
+    last = orig;
+    // search forward in tree
+    mem = mdb_successor(orig);
+    while (is_copy(&mem->cap, &last->cap)) {
+        struct capability *cap = &mem->cap;
+        struct mapping_info *map = &mem->mapping_info;
+        genpaddr_t base = get_address(cap);
+        // only match mappings that start where we want to unmap
+        if (base + map->offset == paddr && map->pte == pte)
+        {
+            // found matching cap
+            *retcte = mem;
+            return SYS_ERR_OK;
+        }
+        last = mem;
+        mem = mdb_successor(mem);
+    }
+
+    // if we get here, we have not found a matching cap
+    return SYS_ERR_CAP_NOT_FOUND;
+}
index 4e87da6..a0e21c3 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/dispatch.h>
+#include <stdio.h>
 #include "target/x86/pmap_x86.h"
 
 // Location and size of virtual address space reserved for mapping
@@ -79,6 +80,31 @@ static struct vnode *find_vnode(struct vnode *root, uint16_t entry)
     return NULL;
 }
 
+static bool has_vnode(struct vnode *root, uint32_t entry, size_t len)
+{
+    assert(root != NULL);
+    assert(root->is_vnode);
+    struct vnode *n;
+
+    uint32_t end_entry = entry + len;
+
+    for (n = root->u.vnode.children; n; n = n->next) {
+        if (n->is_vnode && n->entry == entry) {
+            return true;
+        }
+        // n is frame
+        uint32_t end = n->entry + n->u.frame.pte_count;
+        if (n->entry < entry && end > end_entry) {
+            return true;
+        }
+        if (n->entry >= entry && n->entry < end_entry) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 static void remove_vnode(struct vnode *root, struct vnode *item)
 {
     assert(root->is_vnode);
@@ -127,7 +153,7 @@ static errval_t alloc_vnode(struct pmap_x86 *pmap, struct vnode *root,
 
     // Map it
     err = vnode_map(root->u.vnode.cap, newvnode->u.vnode.cap, entry,
-                    X86_32_PTABLE_ACCESS_DEFAULT, 0);
+                    X86_32_PTABLE_ACCESS_DEFAULT, 0, 1);
     if (err_is_fail(err)) {
         return err_push(err, LIB_ERR_VNODE_MAP);
     }
@@ -180,42 +206,138 @@ static errval_t get_ptable(struct pmap_x86 *pmap, genvaddr_t base,
     return SYS_ERR_OK;
 }
 
+static struct vnode *find_ptable(struct pmap_x86 *pmap, genvaddr_t base)
+{
+    struct vnode *root = &pmap->root;
+    struct vnode *pdir;
+    assert(root != NULL);
+
+#ifdef CONFIG_PAE
+    // PDPT mapping
+    if((pdir = find_vnode(root, X86_32_PDPT_BASE(base))) == NULL) {
+        return NULL;
+    }
+#else
+    pdir = root;
+#endif
+
+    // PDIR mapping
+    return find_vnode(pdir, X86_32_PDIR_BASE(base));
+}
+
+static errval_t do_single_map(struct pmap_x86 *pmap, genvaddr_t vaddr, genvaddr_t vend,
+                              struct capref frame, size_t offset, size_t pte_count,
+                              vregion_flags_t flags)
+{
+    // translate flags
+    paging_x86_32_flags_t pmap_flags = vregion_to_pmap_flag(flags);
+
+    // Get the page table
+    struct vnode *ptable;
+    errval_t err = get_ptable(pmap, vaddr, &ptable);
+    if (err_is_fail(err)) {
+        return err_push(err, LIB_ERR_PMAP_GET_PTABLE);
+    }
+
+    // check if there is an overlapping mapping
+    if (has_vnode(ptable, X86_32_PTABLE_BASE(vaddr), pte_count)) {
+        printf("page already exists in 0x%"PRIxGENVADDR"--0x%"PRIxGENVADDR"\n", vaddr, vend);
+        return LIB_ERR_PMAP_EXISTING_MAPPING;
+    }
+
+    // setup userspace mapping
+    struct vnode *page = slab_alloc(&pmap->slab);
+    assert(page);
+    page->is_vnode = false;
+    page->entry = X86_32_PTABLE_BASE(vaddr);
+    page->next  = ptable->u.vnode.children;
+    ptable->u.vnode.children = page;
+    page->u.frame.cap = frame;
+    page->u.frame.offset = offset;
+    page->u.frame.flags = flags;
+    page->u.frame.pte_count = pte_count;
+
+    // do map
+    err = vnode_map(ptable->u.vnode.cap, frame, X86_32_PTABLE_BASE(vaddr),
+                    pmap_flags, offset, pte_count);
+    if (err_is_fail(err)) {
+        return err_push(err, LIB_ERR_VNODE_MAP);
+    }
+
+    return SYS_ERR_OK;
+}
+
 static errval_t do_map(struct pmap_x86 *pmap, genvaddr_t vaddr,
                        struct capref frame, size_t offset, size_t size,
                        vregion_flags_t flags, size_t *retoff, size_t *retsize)
 {
+    printf("[do_map] vaddr = 0x%"PRIxGENVADDR", size = %zd\n", vaddr, size);
     errval_t err;
-    paging_x86_32_flags_t pmap_flags = vregion_to_pmap_flag(flags);
 
-    for (size_t i = offset; i < offset + size; i += X86_32_BASE_PAGE_SIZE) {
-        // Get the page table
-        struct vnode *ptable;
-        err = get_ptable(pmap, vaddr, &ptable);
+    size = ROUND_UP(size, X86_32_BASE_PAGE_SIZE);
+    size_t pte_count = DIVIDE_ROUND_UP(size, X86_32_BASE_PAGE_SIZE);
+    genvaddr_t vend = vaddr + size;
+
+    if (X86_32_PDIR_BASE(vaddr) == X86_32_PDIR_BASE(vend)) {
+        // fast path
+        do_single_map(pmap, vaddr, vend, frame, offset, pte_count, flags);
+    }
+    else { // multiple leaf page tables
+        // first leaf
+        uint32_t c = X86_32_PTABLE_SIZE - X86_32_PTABLE_BASE(vaddr);
+        genvaddr_t temp_end = vaddr + c * X86_32_BASE_PAGE_SIZE;
+        err = do_single_map(pmap, vaddr, temp_end, frame, offset, c, flags);
         if (err_is_fail(err)) {
-            return err_push(err, LIB_ERR_PMAP_GET_PTABLE);
+            return err_push(err, LIB_ERR_PMAP_DO_MAP);
         }
 
-        // Create user level datastructure for the mapping
-        struct vnode *page = find_vnode(ptable, X86_32_PTABLE_BASE(vaddr));
-        assert(!page);
-        page = slab_alloc(&pmap->slab);
-        assert(page);
-        page->is_vnode = false;
-        page->entry = X86_32_PTABLE_BASE(vaddr);
-        page->next  = ptable->u.vnode.children;
-        ptable->u.vnode.children = page;
-        page->u.frame.cap = frame;
-        page->u.frame.offset = i;
-        page->u.frame.flags = flags;
-
-        // Map entry into the page table
-        uint32_t entry = X86_32_PTABLE_BASE(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);
+        // map full leaves
+        while (X86_32_PDIR_BASE(temp_end) < X86_32_PDIR_BASE(vend)) {
+            // update vars
+            vaddr = temp_end;
+            temp_end = vaddr + X86_32_PTABLE_SIZE * X86_32_BASE_PAGE_SIZE;
+            offset += c * X86_32_BASE_PAGE_SIZE;
+            c = X86_32_PTABLE_SIZE;
+            // copy cap
+            struct capref next;
+            err = slot_alloc(&next);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_DO_MAP);
+            }
+            err = cap_copy(next, frame);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_DO_MAP);
+            }
+            frame = next;
+
+            // do mapping
+            err = do_single_map(pmap, vaddr, temp_end, frame, offset, X86_32_PTABLE_SIZE, flags);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_DO_MAP);
+            }
         }
 
-        vaddr += BASE_PAGE_SIZE;
+        // map remaining part
+        offset += c * X86_32_BASE_PAGE_SIZE;
+        c = X86_32_PTABLE_BASE(vend) - X86_32_PTABLE_BASE(temp_end);
+        if (c) {
+            // copy cap
+            struct capref next;
+            err = slot_alloc(&next);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_DO_MAP);
+            }
+            err = cap_copy(next, frame);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_DO_MAP);
+            }
+
+            // do mapping
+            err = do_single_map(pmap, temp_end, vend, next, offset, c, flags);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_DO_MAP);
+            }
+        }
     }
 
     if (retoff) {
@@ -360,6 +482,90 @@ static errval_t map(struct pmap *pmap, genvaddr_t vaddr, struct capref frame,
     return err;
 }
 
+static errval_t do_single_unmap(struct pmap_x86 *pmap, genvaddr_t vaddr, size_t pte_count, bool delete_cap)
+{
+    errval_t err;
+    struct vnode *pt = find_ptable(pmap, vaddr);
+    if (pt) {
+        struct vnode *page = find_vnode(pt, X86_32_PTABLE_BASE(vaddr));
+        if (page && page->u.frame.pte_count == pte_count) {
+            err = vnode_unmap(pt->u.vnode.cap, page->entry, page->u.frame.pte_count);
+            if (err_is_fail(err)) {
+                printf("vnode_unmap returned error: %s (%d)\n", err_getstring(err), err_no(err));
+                return err_push(err, LIB_ERR_VNODE_UNMAP);
+            }
+
+            // Free up the resources
+            if (delete_cap) {
+                err = cap_destroy(page->u.frame.cap);
+                if (err_is_fail(err)) {
+                    return err_push(err, LIB_ERR_PMAP_DO_SINGLE_UNMAP);
+                }
+            }
+            remove_vnode(pt, page);
+            slab_free(&pmap->slab, page);
+        }
+        else {
+            return LIB_ERR_PMAP_FIND_VNODE;
+        }
+    }
+
+    return SYS_ERR_OK;
+}
+
+static errval_t unmap(struct pmap *pmap, genvaddr_t vaddr, size_t size,
+                      size_t *retsize)
+{
+    printf("[unmap] 0x%"PRIxGENVADDR", %zu\n", vaddr, size);
+    errval_t err, ret = SYS_ERR_OK;
+    struct pmap_x86 *x86 = (struct pmap_x86*)pmap;
+    size = ROUND_UP(size, X86_32_BASE_PAGE_SIZE);
+    genvaddr_t vend = vaddr + size;
+
+    if (X86_32_PDIR_BASE(vaddr) == X86_32_PDIR_BASE(vend)) {
+        // fast path
+        err = do_single_unmap(x86, vaddr, size / X86_32_BASE_PAGE_SIZE, false);
+        if (err_is_fail(err)) {
+            return err_push(err, LIB_ERR_PMAP_UNMAP);
+        }
+    }
+    else { // slow path
+        // unmap first leaf
+        uint32_t c = X86_32_PTABLE_SIZE - X86_32_PTABLE_BASE(vaddr);
+        err = do_single_unmap(x86, vaddr, c, false);
+        if (err_is_fail(err)) {
+            return err_push(err, LIB_ERR_PMAP_UNMAP);
+        }
+
+        // unmap full leaves
+        vaddr += c * X86_32_BASE_PAGE_SIZE;
+        while (X86_32_PDIR_BASE(vaddr) < X86_32_PDIR_BASE(vend)) {
+            c = X86_32_PTABLE_SIZE;
+            err = do_single_unmap(x86, vaddr, X86_32_PTABLE_SIZE, true);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_UNMAP);
+            }
+            vaddr += c * X86_32_BASE_PAGE_SIZE;
+        }
+
+        // unmap remaining part
+        c = X86_32_PTABLE_BASE(vend) - X86_32_PTABLE_BASE(vaddr);
+        if (c) {
+            err = do_single_unmap(x86, vaddr, c, true);
+            if (err_is_fail(err)) {
+                return err_push(err, LIB_ERR_PMAP_UNMAP);
+            }
+        }
+    }
+
+    if (retsize) {
+        *retsize = size;
+    }
+
+    //printf("[unmap] exiting\n");
+    return ret;
+}
+
 /**
  * \brief Remove page mappings
  *
@@ -368,7 +574,8 @@ static errval_t map(struct pmap *pmap, genvaddr_t vaddr, struct capref frame,
  * \param size     The size of virtual address to remove
  * \param retsize  If non-NULL, filled in with the actual size removed
  */
-static errval_t unmap(struct pmap *pmap, genvaddr_t vaddr, size_t size,
+__attribute__((unused))
+static errval_t old_unmap(struct pmap *pmap, genvaddr_t vaddr, size_t size,
                       size_t *retsize)
 {
     errval_t err;
@@ -390,7 +597,7 @@ static errval_t unmap(struct pmap *pmap, genvaddr_t vaddr, size_t size,
         }
 
         // Unmap it in the kernel
-        err = vnode_unmap(ptable->u.vnode.cap, page->entry);
+        err = vnode_unmap(ptable->u.vnode.cap, page->entry, 1);
         if (err_is_fail(err)) {
             return err_push(err, LIB_ERR_VNODE_UNMAP);
         }
index 68c302d..b63c85d 100644 (file)
@@ -96,7 +96,7 @@ static errval_t elf_allocate(void *state, genvaddr_t base, size_t size,
         err = cap_copy(spawn_frame, frame);
         if (err_is_fail(err)) {
             // TODO: make debug printf
-            printf("cap_copy failed for src_slot = %d, dest_slot = %d\n", frame.slot, spawn_frame.slot);
+            printf("cap_copy failed for src_slot = %"PRIuCSLOT", dest_slot = %"PRIuCSLOT"\n", frame.slot, spawn_frame.slot);
             return err_push(err, LIB_ERR_CAP_COPY);
         }
     }