Пример #1
0
int sel4utils_reserve_range_no_alloc_aligned(vspace_t *vspace, sel4utils_res_t *reservation,
                                             size_t size, size_t size_bits, seL4_CapRights rights, int cacheable, void **result)
{
    sel4utils_alloc_data_t *data = get_alloc_data(vspace);
    void *vaddr = find_range(data, BYTES_TO_SIZE_BITS_PAGES(size, size_bits), size_bits);

    if (vaddr == NULL) {
        return -1;
    }

    *result = vaddr;
    reservation->malloced = 0;
    perform_reservation(vspace, reservation, (uintptr_t) vaddr, size, rights, cacheable);
    return 0;
}
Пример #2
0
static json_t *
hardware_process(void *results) {
    hardware_results_t *raw_results = results;

    result_desc_t desc = {
        .stable = false,
        .name = "Nop syscall overhead",
        .ignored = N_IGNORED
    };

    result_t nopnulsyscall_result = process_result(N_RUNS, raw_results->nullSyscall_overhead, desc);

    /* Execlude ccnt, user-level and loop overheads */
    desc.overhead = nopnulsyscall_result.min;

    result_t result = process_result(N_RUNS, raw_results->nullSyscall_results, desc);

    result_set_t set = {
        .name = "Hardware null_syscall thread",
        .n_results = 1,
        .n_extra_cols = 0,
        .results = &result
    };

    json_t *array = json_array();
    json_array_append_new(array, result_set_to_json(set));

    set.name = "Nop syscall overhead";
    set.results = &nopnulsyscall_result;
    json_array_append_new(array, result_set_to_json(set));

    return array;
}

static benchmark_t hardware_benchmark = {
    .name = "hardware",
    .enabled = config_set(CONFIG_APP_HARDWAREBENCH),
    .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(hardware_results_t), seL4_PageBits),
    .process = hardware_process,
    .init = blank_init
};

benchmark_t *
hardware_benchmark_new(void)
{
    return &hardware_benchmark;
}
Пример #3
0
static json_t *
process(void *results) {
     irq_results_t *irq_results = (irq_results_t *) results;

    /* Sort and group data by tracepoints. A stable sort is used so the first N_IGNORED
     * results of each tracepoint can be ignored, as this keeps the data in chronological
     * order.
     */
    logging_stable_sort_log(irq_results->kernel_log, irq_results->n);
    logging_group_log_by_key(irq_results->kernel_log, irq_results->n, sizes, offsets, CONFIG_MAX_NUM_TRACE_POINTS);

    /* Copy the cycle counts into a separate array to simplify further processing */
    for (int i = 0; i < irq_results->n; ++i) {
        kernel_log_data[i] = kernel_logging_entry_get_data(&irq_results->kernel_log[i]);
    }

    /* Process log entries generated by an "empty" tracepoint, which recorded
     * the number of cycles between starting a tracepoint and stopping it
     * immediately afterwards. This will determine the overhead introduced by
     * using tracepoints.
     */
    int n_overhead_data = sizes[TRACE_POINT_OVERHEAD] - N_IGNORED;
    if (n_overhead_data <= 0) {
        ZF_LOGF("Insufficient data recorded. Was the kernel built with the relevant tracepoints?\n");
    }

    ccnt_t *overhead_data = &kernel_log_data[offsets[TRACE_POINT_OVERHEAD] + N_IGNORED];

    /* The results of the IRQ path benchmark are split over multiple tracepoints.
     * A new buffer is allocated to store the amalgamated results. */
    int n_data = sizes[TRACE_POINT_IRQ_PATH_START] - N_IGNORED;
    if (n_data <= 0) {
        ZF_LOGF("Insufficient data recorded. Was the kernel built with the relevant tracepoints?\n");
    }

    ccnt_t *data = (ccnt_t*)malloc(sizeof(ccnt_t) * n_data);
    if (data == NULL) {
        ZF_LOGF("Failed to allocate memory\n");
    }

    json_t *array = json_array();
    result_desc_t desc = {0};
    result_t result = process_result(n_overhead_data, overhead_data, desc);

    result_set_t set = {
        .name = "Tracepoint overhead",
        .n_results = 1,
        .results = &result,
    };

    json_array_append_new(array, result_set_to_json(set));

    /* Add the results from the IRQ path tracepoints to get the total IRQ path cycle counts.
     * The average overhead is subtracted from each cycle count (doubled as there are 2
     * tracepoints) to account for overhead added to the cycle counts by use of tracepoints.
     */
    ccnt_t *starts = &kernel_log_data[offsets[TRACE_POINT_IRQ_PATH_START] + N_IGNORED];
    ccnt_t *ends = &kernel_log_data[offsets[TRACE_POINT_IRQ_PATH_END] + N_IGNORED];
    for (int i = 0; i < n_data; ++i) {
        data[i] = starts[i] + ends[i] - (result.mean * 2);
    }

    set.name = "IRQ Path Cycle Count (accounting for overhead)";

    result = process_result(n_data, data, desc);
    json_array_append_new(array, result_set_to_json(set));

    free(data);

    return array;
}

static benchmark_t irq_benchmark = {
    .name = "irq",
    .enabled = config_set(CONFIG_APP_IRQBENCH) && CONFIG_MAX_NUM_TRACE_POINTS == 3,
    .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(irq_results_t), seL4_PageBits),
    .process = process,
    .init = blank_init
};

benchmark_t *
irq_benchmark_new(void)
{
    return &irq_benchmark;
}

static json_t *
irquser_process(void *r) {
    irquser_results_t *raw_results = r;

    result_desc_t desc = {
        .ignored = N_IGNORED,
        .name = "IRQ user measurement overhead"
    };

    result_t results[3];

    results[0] = process_result(N_RUNS, raw_results->overheads, desc);

    desc.overhead = results[0].min;

    results[1] = process_result(N_RUNS, raw_results->thread_results, desc);
    results[2] = process_result(N_RUNS, raw_results->process_results, desc);

    char *types[] = {"Measurement overhead", "Without context switch", "With context switch"};

    column_t col = {
        .header = "Type",
        .type = JSON_STRING,
        .string_array = types
    };

    result_set_t set = {
        .name = "IRQ path cycle count (measured from user level)",
        .n_results = 3,
        .results = results,
        .n_extra_cols = 1,
        .extra_cols = &col
    };

    json_t *json = json_array();
    json_array_append_new(json, result_set_to_json(set));
    return json;
}

static benchmark_t irquser_benchmark = {
    .name = "irquser",
    .enabled = config_set(CONFIG_APP_IRQUSERBENCH),
    .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(irquser_results_t), seL4_PageBits),
    .process = irquser_process,
    .init = blank_init
};

benchmark_t *
irquser_benchmark_new(void)
{
   return &irquser_benchmark;
}