Пример #1
0
/* Some more generic routines for helping with mapping */
void *
sel4utils_dup_and_map(vka_t *vka, vspace_t *vspace, seL4_CPtr page, size_t size_bits)
{
    int error;
    cspacepath_t page_path;
    cspacepath_t copy_path;
    void *mapping;
    /* First need to copy the cap */
    error = vka_cspace_alloc_path(vka, &copy_path);
    if (error != seL4_NoError) {
        return NULL;
    }
    vka_cspace_make_path(vka, page, &page_path);
    error = vka_cnode_copy(&copy_path, &page_path, seL4_AllRights);
    if (error != seL4_NoError) {
        vka_cspace_free(vka, copy_path.capPtr);
        return NULL;
    }
    /* Now map it in */
    mapping = vspace_map_pages(vspace, &copy_path.capPtr, NULL,  seL4_AllRights, 1, size_bits, 1);
    if (!mapping) {
        vka_cnode_delete(&copy_path);
        vka_cspace_free(vka, copy_path.capPtr);
        return NULL;
    }
    return mapping;
}
Пример #2
0
static void
delete_iospace(env_t env, seL4_CPtr iospace)
{
    cspacepath_t path;
    vka_cspace_make_path(&env->vka, iospace, &path);
    vka_cnode_delete(&path);
}
Пример #3
0
int
cnode_delete(env_t env, seL4_CPtr slot)
{
    cspacepath_t path;
    vka_cspace_make_path(&env->vka, slot, &path);
    return vka_cnode_delete(&path);
}
Пример #4
0
void
sel4utils_unmap_dup(vka_t *vka, vspace_t *vspace, void *mapping, size_t size_bits)
{
    /* Grap a copy of the cap */
    seL4_CPtr copy = vspace_get_cap(vspace, mapping);
    cspacepath_t copy_path;
    assert(copy);
    /* now free the mapping */
    vspace_unmap_pages(vspace, mapping, 1, size_bits, VSPACE_PRESERVE);
    /* delete and free the cap */
    vka_cspace_make_path(vka, copy, &copy_path);
    vka_cnode_delete(&copy_path);
    vka_cspace_free(vka, copy);
}
Пример #5
0
void
sel4utils_unmap_pages(vspace_t *vspace, void *vaddr, size_t num_pages, size_t size_bits, vka_t *vka)
{
    uintptr_t v = (uintptr_t) vaddr;
    sel4utils_alloc_data_t *data = get_alloc_data(vspace);
    sel4utils_res_t *reserve = find_reserve(data, v);

    if (!sel4_valid_size_bits(size_bits)) {
        ZF_LOGE("Invalid size_bits %zu", size_bits);
        return;
    }

    if (vka == VSPACE_FREE) {
        vka = data->vka;
    }

    for (int i = 0; i < num_pages; i++) {
        seL4_CPtr cap = get_cap(data->top_level, v);

        /* unmap */
        if (cap != 0) {
            int error = seL4_ARCH_Page_Unmap(cap);
            if (error != seL4_NoError) {
                ZF_LOGE("Failed to unmap page at vaddr %p", vaddr);
            }
        }

        if (vka) {
            cspacepath_t path;
            vka_cspace_make_path(vka, cap, &path);
            vka_cnode_delete(&path);
            vka_cspace_free(vka, cap);
            if (sel4utils_get_cookie(vspace, vaddr)) {
                vka_utspace_free(vka, kobject_get_type(KOBJECT_FRAME, size_bits),
                                     size_bits, sel4utils_get_cookie(vspace, vaddr));
            }
        }

        if (reserve == NULL) {
            clear_entries(vspace, v, size_bits);
        } else {
            reserve_entries(vspace, v, size_bits);
        }
        assert(get_cap(data->top_level, v) != cap);
        assert(get_cookie(data->top_level, v) == 0);

        v += (1 << size_bits);
        vaddr = (void *) v;
    }
}
Пример #6
0
static void _delete_node(allocman_t *alloc, struct utspace_split_node *node) {
    vka_cnode_delete(&node->ut);
    allocman_cspace_free(alloc, &node->ut);
    allocman_mspace_free(alloc, node, sizeof(*node));
}
Пример #7
0
static int _refill_pool(allocman_t *alloc, utspace_split_t *split, struct utspace_split_node **heads, size_t size_bits, uintptr_t paddr) {
    struct utspace_split_node *node;
    struct utspace_split_node *left, *right;
    int sel4_error;
    if (paddr == ALLOCMAN_NO_PADDR) {
        /* see if pool is actually empty */
        if (heads[size_bits]) {
            return 0;
        }
    } else {
        /* see if the pool has the paddr we want */
        for (node = heads[size_bits]; node; node = node->next) {
            if (node->paddr <= paddr && paddr < node->paddr + BIT(size_bits)) {
                return 0;
            }
        }
    }
    /* ensure we are not the highest pool */
    if (size_bits >= sizeof(seL4_Word) * 8 - 2) {
        /* bugger, no untypeds bigger than us */
        ZF_LOGV("Failed to refill pool of size %zu, no larger pools", size_bits);
        return 1;
    }
    /* get something from the highest pool */
    if (_refill_pool(alloc, split, heads, size_bits + 1, paddr)) {
        /* could not fill higher pool */
        ZF_LOGV("Failed to refill pool of size %zu", size_bits);
        return 1;
    }
    if (paddr == ALLOCMAN_NO_PADDR) {
        /* use the first node for lack of a better one */
        node = heads[size_bits + 1];
    } else {
        for (node = heads[size_bits + 1]; node && !(node->paddr <= paddr && paddr < node->paddr + BIT(size_bits + 1)); node = node->next);
        /* _refill_pool should not have returned if this wasn't possible */
        assert(node);
    }
    /* allocate two new nodes */
    left = _new_node(alloc);
    if (!left) {
        ZF_LOGV("Failed to allocate left node");
        return 1;
    }
    right = _new_node(alloc);
    if (!right) {
        ZF_LOGV("Failed to allocate right node");
        _delete_node(alloc, left);
        return 1;
    }
    /* perform the first retype */
    sel4_error = seL4_Untyped_Retype(node->ut.capPtr, seL4_UntypedObject, size_bits, left->ut.root, left->ut.dest, left->ut.destDepth, left->ut.offset, 1);
    if (sel4_error != seL4_NoError) {
        _delete_node(alloc, left);
        _delete_node(alloc, right);
        /* Well this shouldn't happen */
        ZF_LOGE("Failed to retype untyped, error %d\n", sel4_error);
        return 1;
    }
    /* perform the second retype */
    sel4_error = seL4_Untyped_Retype(node->ut.capPtr, seL4_UntypedObject, size_bits, right->ut.root, right->ut.dest, right->ut.destDepth, right->ut.offset, 1);
    if (sel4_error != seL4_NoError) {
        vka_cnode_delete(&left->ut);
        _delete_node(alloc, left);
        _delete_node(alloc, right);
        /* Well this shouldn't happen */
        ZF_LOGE("Failed to retype untyped, error %d\n", sel4_error);
        return 1;
    }
    /* all is done. remove the parent and insert the children */
    _remove_node(&heads[size_bits + 1], node);
    left->parent = right->parent = node;
    left->sibling = right;
    left->origin_head = &heads[size_bits];
    right->origin_head = &heads[size_bits];
    right->sibling = left;
    if (node->paddr != ALLOCMAN_NO_PADDR) {
        left->paddr = node->paddr;
        right->paddr = node->paddr + BIT(size_bits);
    } else {
        left->paddr = right->paddr = ALLOCMAN_NO_PADDR;
    }
    /* insert in this order so that we end up pulling the untypeds off in order of contiugous
     * physical address. This makes various allocation problems slightly less likely to happen */
    _insert_node(&heads[size_bits], right);
    _insert_node(&heads[size_bits], left);
    return 0;
}
Пример #8
0
static int _refill_pool(allocman_t *alloc, utspace_split_t *split, uint32_t size_bits) {
    struct utspace_split_node *node;
    struct utspace_split_node *left, *right;
    int sel4_error;
    /* see if pool is actually empty */
    if (split->heads[size_bits]) {
        return 0;
    }
    /* ensure we are not the highest pool */
    if (size_bits >= 30) {
        /* bugger, no untypeds bigger than us */
        return 1;
    }
    /* get something from the highest pool */
    if (_refill_pool(alloc, split, size_bits + 1)) {
        /* could not fill higher pool */
        return 1;
    }
    /* use the first node for lack of a better one */
    node = split->heads[size_bits + 1];
    /* allocate two new nodes */
    left = _new_node(alloc);
    if (!left) {
        return 1;
    }
    right = _new_node(alloc);
    if (!right) {
        _delete_node(alloc, left);
        return 1;
    }
    /* perform the first retype */
#if defined(CONFIG_KERNEL_STABLE)
    sel4_error = seL4_Untyped_RetypeAtOffset(node->ut.capPtr, seL4_UntypedObject, 0, size_bits, left->ut.root, left->ut.dest, left->ut.destDepth, left->ut.offset, 1);
#else
    sel4_error = seL4_Untyped_Retype(node->ut.capPtr, seL4_UntypedObject, size_bits, left->ut.root, left->ut.dest, left->ut.destDepth, left->ut.offset, 1);
#endif
    if (sel4_error != seL4_NoError) {
        _delete_node(alloc, left);
        _delete_node(alloc, right);
        /* Well this shouldn't happen */
        return 1;
    }
    /* perform the second retype */
#if defined(CONFIG_KERNEL_STABLE)
    sel4_error = seL4_Untyped_RetypeAtOffset(node->ut.capPtr, seL4_UntypedObject, BIT(size_bits), size_bits, right->ut.root, right->ut.dest, right->ut.destDepth, right->ut.offset, 1);
#else
    sel4_error = seL4_Untyped_Retype(node->ut.capPtr, seL4_UntypedObject, size_bits, right->ut.root, right->ut.dest, right->ut.destDepth, right->ut.offset, 1);
#endif
    if (sel4_error != seL4_NoError) {
        vka_cnode_delete(&left->ut);
        _delete_node(alloc, left);
        _delete_node(alloc, right);
        /* Well this shouldn't happen */
        return 1;
    }
    /* all is done. remove the parent and insert the children */
    _remove_node(&split->heads[size_bits + 1], node);
    left->parent = right->parent = node;
    left->sibling = right;
    right->sibling = left;
    if (node->paddr) {
        left->paddr = node->paddr;
        right->paddr = node->paddr + BIT(size_bits);
    } else {
        left->paddr = right->paddr = 0;
    }
    /* insert in this order so that we end up pulling the untypeds off in order of contiugous
     * physical address. This makes various allocation problems slightly less likely to happen */
    _insert_node(&split->heads[size_bits], right);
    _insert_node(&split->heads[size_bits], left);
    return 0;
}