void * create_level(vspace_t *vspace, size_t size) { sel4utils_alloc_data_t *data = get_alloc_data(vspace); /* We need a level in the bootstrapper vspace */ if (data->bootstrap == NULL) { return bootstrap_create_level(vspace, size); } /* Otherwise we allocate our level out of the bootstrapper vspace - * which is where bookkeeping is mapped */ void *level = vspace_new_pages(data->bootstrap, seL4_AllRights, size / PAGE_SIZE_4K, seL4_PageBits); if (level == NULL) { return NULL; } memset(level, 0, size); return level; }
int serial_server_client_connect(seL4_CPtr badged_server_ep_cap, vka_t *client_vka, vspace_t *client_vspace, serial_client_context_t *conn) { seL4_Error error; int shmem_n_pages; uintptr_t shmem_tmp_vaddr; seL4_MessageInfo_t tag; cspacepath_t frame_cspath; if (badged_server_ep_cap == 0 || client_vka == NULL || client_vspace == NULL || conn == NULL) { return seL4_InvalidArgument; } memset(conn, 0, sizeof(serial_client_context_t)); shmem_n_pages = BYTES_TO_4K_PAGES(SERIAL_SERVER_SHMEM_MAX_SIZE); if (shmem_n_pages > seL4_MsgMaxExtraCaps) { ZF_LOGE(SERSERVC"connect: Currently unsupported shared memory size: " "IPC cap transfer capability is inadequate."); return seL4_RangeError; } conn->shmem = vspace_new_pages(client_vspace, seL4_AllRights, shmem_n_pages, seL4_PageBits); if (conn->shmem == NULL) { ZF_LOGE(SERSERVC"connect: Failed to alloc shmem."); return seL4_NotEnoughMemory; } assert(IS_ALIGNED((uintptr_t)conn->shmem, seL4_PageBits)); /* Look up the Frame cap behind each page in the shmem range, and marshal * all of those Frame caps to the parent. The parent will then map those * Frames into its VSpace and establish a shmem link. */ shmem_tmp_vaddr = (uintptr_t)conn->shmem; for (int i = 0; i < shmem_n_pages; i++) { vka_cspace_make_path(client_vka, vspace_get_cap(client_vspace, (void *)shmem_tmp_vaddr), &frame_cspath); seL4_SetCap(i, frame_cspath.capPtr); shmem_tmp_vaddr += BIT(seL4_PageBits); } /* Call the server asking it to establish the shmem mapping with us, and * get us connected up. */ seL4_SetMR(SSMSGREG_FUNC, FUNC_CONNECT_REQ); seL4_SetMR(SSMSGREG_CONNECT_REQ_SHMEM_SIZE, SERIAL_SERVER_SHMEM_MAX_SIZE); /* extraCaps doubles up as the number of shmem pages. */ tag = seL4_MessageInfo_new(0, 0, shmem_n_pages, SSMSGREG_CONNECT_REQ_END); tag = seL4_Call(badged_server_ep_cap, tag); /* It makes sense to verify that the message we're getting back is an * ACK response to our request message. */ if (seL4_GetMR(SSMSGREG_FUNC) != FUNC_CONNECT_ACK) { error = seL4_IllegalOperation; ZF_LOGE(SERSERVC"connect: Reply message was not a CONNECT_ACK as " "expected."); goto out; } /* When the parent replies, we check to see if it was successful, etc. */ error = seL4_MessageInfo_get_label(tag); if (error != (int)SERIAL_SERVER_NOERROR) { ZF_LOGE(SERSERVC"connect ERR %d: Failed to connect to the server.", error); if (error == (int)SERIAL_SERVER_ERROR_SHMEM_TOO_LARGE) { ZF_LOGE(SERSERVC"connect: Your requested shmem mapping size is too " "large.\n\tServer's max shmem size is %luB.", (long)seL4_GetMR(SSMSGREG_CONNECT_ACK_MAX_SHMEM_SIZE)); } goto out; } conn->shmem_size = SERIAL_SERVER_SHMEM_MAX_SIZE; vka_cspace_make_path(client_vka, badged_server_ep_cap, &conn->badged_server_ep_cspath); return seL4_NoError; out: if (conn->shmem != NULL) { vspace_unmap_pages(client_vspace, (void *)conn->shmem, shmem_n_pages, seL4_PageBits, VSPACE_FREE); } return error; }
/* elf region data */ int num_elf_regions; sel4utils_elf_region_t elf_regions[MAX_REGIONS]; /* Print welcome banner. */ printf("\n"); printf("seL4 Test\n"); printf("=========\n"); printf("\n"); /* allocate lots of untyped memory for tests to use */ num_untypeds = populate_untypeds(untypeds); /* create a frame that will act as the init data, we can then map that * in to target processes */ env.init = (test_init_data_t *) vspace_new_pages(&env.vspace, seL4_AllRights, 1, PAGE_BITS_4K); assert(env.init != NULL); /* copy the cap to map into the remote process */ cspacepath_t src, dest; vka_cspace_make_path(&env.vka, vspace_get_cap(&env.vspace, env.init), &src); UNUSED int error = vka_cspace_alloc(&env.vka, &env.init_frame_cap_copy); assert(error == 0); vka_cspace_make_path(&env.vka, env.init_frame_cap_copy, &dest); error = vka_cnode_copy(&dest, &src, seL4_AllRights); assert(error == 0); /* copy the untyped size bits list across to the init frame */ memcpy(env.init->untyped_size_bits_list, untyped_size_bits_list, sizeof(uint8_t) * num_untypeds);
int main(int argc, char **argv) { env_t *env; irquser_results_t *results; vka_object_t endpoint = {0}; static size_t object_freq[seL4_ObjectTypeCount] = { [seL4_TCBObject] = 2, [seL4_EndpointObject] = 1, #ifdef CONFIG_KERNEL_RT [seL4_SchedContextObject] = 2, [seL4_ReplyObject] = 2 #endif }; env = benchmark_get_env(argc, argv, sizeof(irquser_results_t), object_freq); benchmark_init_timer(env); results = (irquser_results_t *) env->results; if (vka_alloc_endpoint(&env->slab_vka, &endpoint) != 0) { ZF_LOGF("Failed to allocate endpoint\n"); } /* set up globals */ done_ep = endpoint.cptr; timer = &env->timer; timer_signal = env->ntfn.cptr; int error = ltimer_reset(&env->timer.ltimer); ZF_LOGF_IF(error, "Failed to start timer"); error = ltimer_set_timeout(&env->timer.ltimer, INTERRUPT_PERIOD_NS, TIMEOUT_PERIODIC); ZF_LOGF_IF(error, "Failed to configure timer"); sel4bench_init(); sel4utils_thread_t ticker, spinner; /* measurement overhead */ ccnt_t start, end; for (int i = 0; i < N_RUNS; i++) { SEL4BENCH_READ_CCNT(start); SEL4BENCH_READ_CCNT(end); results->overheads[i] = end - start; } /* create a frame for the shared time variable so we can share it between processes */ ccnt_t *local_current_time = (ccnt_t *) vspace_new_pages(&env->vspace, seL4_AllRights, 1, seL4_PageBits); if (local_current_time == NULL) { ZF_LOGF("Failed to allocate page"); } /* first run the benchmark between two threads in the current address space */ benchmark_configure_thread(env, endpoint.cptr, seL4_MaxPrio - 1, "ticker", &ticker); benchmark_configure_thread(env, endpoint.cptr, seL4_MaxPrio - 2, "spinner", &spinner); error = sel4utils_start_thread(&ticker, (sel4utils_thread_entry_fn) ticker_fn, (void *) results->thread_results, (void *) local_current_time, true); if (error) { ZF_LOGF("Failed to start ticker"); } char strings[1][WORD_STRING_SIZE]; char *spinner_argv[1]; sel4utils_create_word_args(strings, spinner_argv, 1, (seL4_Word) local_current_time); error = sel4utils_start_thread(&spinner, (sel4utils_thread_entry_fn) spinner_fn, (void *) 1, (void *) spinner_argv, true); assert(!error); benchmark_wait_children(endpoint.cptr, "child of irq-user", 1); /* stop spinner thread */ error = seL4_TCB_Suspend(spinner.tcb.cptr); assert(error == seL4_NoError); error = seL4_TCB_Suspend(ticker.tcb.cptr); assert(error == seL4_NoError); /* now run the benchmark again, but run the spinner in another address space */ /* restart ticker */ error = sel4utils_start_thread(&ticker, (sel4utils_thread_entry_fn) ticker_fn, (void *) results->process_results, (void *) local_current_time, true); assert(!error); sel4utils_process_t spinner_process; benchmark_shallow_clone_process(env, &spinner_process, seL4_MaxPrio - 2, spinner_fn, "spinner"); /* share the current time variable with the spinner process */ void *current_time_remote = vspace_share_mem(&env->vspace, &spinner_process.vspace, (void *) local_current_time, 1, seL4_PageBits, seL4_AllRights, true); assert(current_time_remote != NULL); /* start the spinner process */ sel4utils_create_word_args(strings, spinner_argv, 1, (seL4_Word) current_time_remote); error = sel4utils_spawn_process(&spinner_process, &env->slab_vka, &env->vspace, 1, spinner_argv, 1); if (error) { ZF_LOGF("Failed to start spinner process"); } benchmark_wait_children(endpoint.cptr, "child of irq-user", 1); /* done -> results are stored in shared memory so we can now return */ benchmark_finished(EXIT_SUCCESS); return 0; }