Ejemplo n.º 1
0
static errval_t do_single_map(struct pmap_arm *pmap, genvaddr_t vaddr, genvaddr_t vend,
                              struct capref frame, size_t offset, size_t pte_count,
                              vregion_flags_t 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);
    }
    uintptr_t pmap_flags = vregion_flags_to_kpi_paging_flags(flags);
    // XXX: reassess the following note -SG
    // NOTE: strictly speaking a l2 entry only has 8 bits, but due to the way
    // Barrelfish allocates l1 and l2 tables, we use 10 bits for the tracking
    // index here and in the map syscall
    uintptr_t index = ARM_USER_L2_OFFSET(vaddr);
    // Create user level datastructure for the mapping
    bool has_page = has_vnode(ptable, index, pte_count);
    assert(!has_page);
    struct vnode *page = slab_alloc(&pmap->slab);
    assert(page);
    page->is_vnode = false;
    page->entry = index;
    page->next  = ptable->u.vnode.children;
    ptable->u.vnode.children = page;
    page->u.frame.cap = frame;
    page->u.frame.pte_count = pte_count;

    // Map entry into the page table
    err = vnode_map(ptable->u.vnode.cap, frame, index,
                    pmap_flags, offset, pte_count);
    if (err_is_fail(err)) {
        return err_push(err, LIB_ERR_VNODE_MAP);
    }
    return SYS_ERR_OK;
}
Ejemplo n.º 2
0
// this should work for x86_64 and x86_32.
bool has_vnode(struct vnode *root, uint32_t entry, size_t len,
               bool only_pages)
{
    assert(root != NULL);
    assert(root->is_vnode);
    struct vnode *n;

    uint32_t end_entry = entry + len;

    // region we check [entry .. end_entry)

    for (n = root->u.vnode.children; n; n = n->next) {
        // 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) {
            if (only_pages) {
                return has_vnode(n, 0, PTABLE_SIZE, true);
            }
#ifdef LIBBARRELFISH_DEBUG_PMAP
            debug_printf("1: found page table inside our region\n");
#endif
            return true;
        } else if (n->is_vnode) {
            // all other vnodes do not overlap with us, so go to next
            assert(n->entry < entry || n->entry >= end_entry);
            continue;
        }
        // this remains the same regardless of `only_pages`.
        // 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 (entry < n->entry && end_entry >= end) {
#ifdef LIBBARRELFISH_DEBUG_PMAP
            debug_printf("2: found a strict subset of our region: (%"
                    PRIu32"--%"PRIu32") < (%"PRIu32"--%"PRIu32")\n",
                    n->entry, end, entry, end_entry);
#endif
            return true;
        }
        if (entry >= n->entry && entry < end) {
#ifdef LIBBARRELFISH_DEBUG_PMAP
            debug_printf("3: found a region starting inside our region: (%"
                    PRIu32"--%"PRIu32") <> (%"PRIu32"--%"PRIu32")\n",
                    n->entry, end, entry, end_entry);
#endif
            return true;
        }
        if (end_entry > n->entry && end_entry < end) {
#ifdef LIBBARRELFISH_DEBUG_PMAP
            debug_printf("4: found a region ending inside our region: (%"
                    PRIu32"--%"PRIu32") <> (%"PRIu32"--%"PRIu32")\n",
                    n->entry, end, entry, end_entry);
#endif
            return true;
        }
    }

    return false;
}