Esempio n. 1
0
static struct utspace_split_node *_new_node(allocman_t *alloc) {
    int error;
    struct utspace_split_node *node;
    node = (struct utspace_split_node*) allocman_mspace_alloc(alloc, sizeof(*node), &error);
    if (error) {
        ZF_LOGV("Failed to allocate node of size %zu", sizeof(*node));
        return NULL;
    }
    error = allocman_cspace_alloc(alloc, &node->ut);
    if (error) {
        allocman_mspace_free(alloc, node, sizeof(*node));
        ZF_LOGV("Failed to allocate slot");
        return NULL;
    }
    return node;
}
Esempio n. 2
0
int main(int argc, char *argv[])
{
    (void)argc;
    (void)argv;

    /* Current log level is set to ZF_LOG_INFO by defining ZF_LOG_LEVEL
     * before zf_log.h include. All log messages below INFO level will be
     * compiled out.
     */
    ZF_LOGV("Argument of this VERBOSE message will not be evaluated: %i",
            call_exit());
    ZF_LOGI("So you will see that INFO message");

    /* Output log level is set to WARN and then to INFO. Argument of INFO log
     * statement will be evaluated only once (after setting output log level to
     * INFO).
     */
    zf_log_set_output_level(ZF_LOG_WARN);
    int count = 0;
    for (int i = 2; 0 < i--;)
    {
        ZF_LOGI("Argument of this INFO message will be evaluated only once: %i",
                ++count);
        zf_log_set_output_level(ZF_LOG_INFO);
    }
    if (1 != count)
    {
        abort();
    }
    ZF_LOGI("And you will see that INFO message");
    return 0;
}
Esempio n. 3
0
static int _insert_new_node(allocman_t *alloc, struct utspace_split_node **head, cspacepath_t ut, uintptr_t paddr) {
    int error;
    struct utspace_split_node *node;
    node = (struct utspace_split_node*) allocman_mspace_alloc(alloc, sizeof(*node), &error);
    if (error) {
        ZF_LOGV("Failed to allocate node of size %zu", sizeof(*node));
        return 1;
    }
    node->parent = NULL;
    node->ut = ut;
    node->paddr = paddr;
    node->origin_head = head;
    _insert_node(head, node);
    return 0;
}
Esempio n. 4
0
int
test_timer(driver_env_t env)
{
    int error = ltimer_set_timeout(&env->timer.ltimer, 1 * NS_IN_S, TIMEOUT_PERIODIC);
    test_assert_fatal(!error);

    for (int i = 0; i < 3; i++) {
        wait_for_timer_interrupt(env);
        ZF_LOGV("Tick\n");
    }

    error = ltimer_reset(&env->timer.ltimer);
    test_assert_fatal(!error);

    return sel4test_get_result();
}
Esempio n. 5
0
int
test_gettime_timeout(driver_env_t env)
{
    int error = 0;
    uint64_t start, end;

    start = timestamp(env);
    error = ltimer_set_timeout(&env->timer.ltimer, 1 * NS_IN_MS, TIMEOUT_PERIODIC);
    test_assert_fatal(!error);

    for (int i = 0; i < 3; i++) {
        wait_for_timer_interrupt(env);
        ZF_LOGV("Tick\n");
    }

    end = timestamp(env);

    test_gt(end, start);

    error = ltimer_reset(&env->timer.ltimer);
    test_assert_fatal(!error);

    return sel4test_get_result();
}
Esempio n. 6
0
seL4_Word _utspace_split_alloc(allocman_t *alloc, void *_split, size_t size_bits, seL4_Word type, const cspacepath_t *slot, uintptr_t paddr, bool canBeDev, int *error)
{
    utspace_split_t *split = (utspace_split_t*)_split;
    size_t sel4_size_bits;
    int sel4_error;
    struct utspace_split_node *node;
    /* get size of untyped call */
    sel4_size_bits = get_sel4_object_size(type, size_bits);
    if (size_bits != vka_get_object_size(type, sel4_size_bits) || size_bits == 0) {
        SET_ERROR(error, 1);
        return 0;
    }
    struct utspace_split_node **head = NULL;
    /* if we're allocating at a particular paddr then we will just trawl through every pool
     * and see if we can find out which one has what we want */
    if (paddr != ALLOCMAN_NO_PADDR) {
        if (canBeDev) {
            head = find_head_for_paddr(split->dev_heads, paddr, size_bits);
            if (!head) {
                head = find_head_for_paddr(split->dev_mem_heads, paddr, size_bits);
            }
        }
        if (!head) {
            head = find_head_for_paddr(split->heads, paddr, size_bits);
        }
        if (!head) {
            SET_ERROR(error, 1);
            ZF_LOGE("Failed to find any untyped capable of creating an object at address %p", (void*)paddr);
            return 0;
        }
        if (_refill_pool(alloc, split, head, size_bits, paddr)) {
            /* out of memory? */
            SET_ERROR(error, 1);
            ZF_LOGV("Failed to refill pool to allocate object of size %zu", size_bits);
            return 0;
        }
        /* search for the node we want to use. We have the advantage of knowing that
         * due to objects being size aligned that the base paddr of the untyped will
         * be exactly the paddr we want */
        for (node = head[size_bits]; node && node->paddr != paddr; node = node->next);
        /* _refill_pool should not have returned if this wasn't possible */
        assert(node);
    } else {
        /* if we can use device memory then preference allocating from there */
        if (canBeDev) {
            if (_refill_pool(alloc, split, split->dev_mem_heads, size_bits, ALLOCMAN_NO_PADDR)) {
                /* out of memory? */
                SET_ERROR(error, 1);
                ZF_LOGV("Failed to refill pool to allocate object of size %zu", size_bits);
                return 0;
            }
            head = split->dev_mem_heads;
        }
        if (!head) {
            head = split->heads;
            if (_refill_pool(alloc, split, head, size_bits, ALLOCMAN_NO_PADDR)) {
                /* out of memory? */
                SET_ERROR(error, 1);
                ZF_LOGV("Failed to refill pool to allocate object of size %zu", size_bits);
                return 0;
            }
        }
        /* use the first node for lack of a better one */
        node = head[size_bits];
    }
    /* Perform the untyped retype */
    sel4_error = seL4_Untyped_Retype(node->ut.capPtr, type, sel4_size_bits, slot->root, slot->dest, slot->destDepth, slot->offset, 1);
    if (sel4_error != seL4_NoError) {
        /* Well this shouldn't happen */
        ZF_LOGE("Failed to retype untyped, error %d\n", sel4_error);
        SET_ERROR(error, 1);
        return 0;
    }
    /* remove the node */
    _remove_node(&head[size_bits], node);
    SET_ERROR(error, 0);
    /* return the node as a cookie */
    return (seL4_Word)node;
}
Esempio n. 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;
}