void wait_for_timer_interrupt(env_t env) { seL4_Word sender_badge; seL4_Wait(env->timer_aep.cptr, &sender_badge); sel4_timer_handle_single_irq(env->timer); }
/* IRQ handler thread. Wait on a notification object for IRQs. When one arrives, send a * synchronous message to the registered endpoint. If no synchronous endpoint was * registered, call the appropriate handler function directly (must be thread safe) */ static void _irq_thread_entry(struct irq_server_thread* st) { seL4_CPtr sep; seL4_CPtr notification; uintptr_t node_ptr; seL4_Word label; sep = st->delivery_sep; notification = st->node->notification; node_ptr = (uintptr_t)st->node; label = st->label; DIRQSERVER("thread started. Waiting on endpoint %d\n", notification); while (1) { seL4_Word badge; seL4_Wait(notification, &badge); assert(badge != 0); if (sep != seL4_CapNull) { /* Synchronous endpoint registered. Send IPC */ seL4_MessageInfo_t info = seL4_MessageInfo_new(label, 0, 0, 2); seL4_SetMR(0, badge); seL4_SetMR(1, node_ptr); seL4_Send(sep, info); } else { /* No synchronous endpoint. Call the handler directly */ irq_server_node_handle_irq(st->node, badge); } } }
void run_benchmark(void *faulter_fn, void *handler_fn, seL4_CPtr done_ep) { int error = sel4utils_start_thread(&fault_handler, (sel4utils_thread_entry_fn) handler_fn, (void *) N_HANDLER_ARGS, (void *) handler_argv, true); ZF_LOGF_IF(error, "Failed to start handler"); if (config_set(CONFIG_KERNEL_RT)) { /* convert the fault handler to passive */ ZF_LOGD("Waiting to convert handler to passive"); seL4_Wait(done_ep, NULL); ZF_LOGD("unbound sc\n"); error = api_sc_unbind(fault_handler.sched_context.cptr); ZF_LOGF_IF(error, "Failed to convert to passive"); } error = sel4utils_start_thread(&faulter, (sel4utils_thread_entry_fn) faulter_fn, (void *) N_FAULTER_ARGS, (void *) faulter_argv, true); ZF_LOGF_IF(error, "Failed to start faulter"); /* benchmark runs */ benchmark_wait_children(done_ep, "faulter", 1); if (config_set(CONFIG_KERNEL_RT)) { /* convert the fault handler to active */ ZF_LOGD("Rebound sc\n"); error = api_sc_bind(fault_handler.sched_context.cptr, fault_handler.tcb.cptr); ZF_LOGF_IF(error, "Failed to convert to active"); } benchmark_wait_children(done_ep, "fault handler", 1); error = seL4_TCB_Suspend(faulter.tcb.cptr); ZF_LOGF_IF(error, "Failed to suspend faulter"); error = seL4_TCB_Suspend(fault_handler.tcb.cptr); ZF_LOGF_IF(error, "Failed to suspend fault handler"); }
int run(void) { seL4_CPtr aep = timeout_aep(); while(1) { seL4_Wait(aep, NULL); timer_callback(NULL); } return 0; }
int wait_for_helper(helper_thread_t *thread) { seL4_Word badge; seL4_Wait(thread->local_endpoint.cptr, &badge); return seL4_GetMR(0); }
// Wait on an seL4 notification or endpoint void ffiseL4_Wait(unsigned char *c, long clen, unsigned char *a, long alen) { seL4_CPtr src; memcpy(&src, a + 1, sizeof(src)); seL4_Word badge; seL4_Wait(src, &badge); memcpy(a + 1, &badge, sizeof(badge)); a[0] = FFI_SUCCESS; }
/* * We have to loop a couple of time because we exceed hardware limit. */ static void wait_for_timer() { for (int i = 0; i < 100 / speed; i++) { //wait for timer interrupt to occur seL4_Wait(timer_aep.cptr, NULL); //Ack IRQ sel4_timer_handle_single_irq(timer); } }
static inline void fault_handler_done(seL4_CPtr ep, seL4_Word ip, seL4_CPtr done_ep, seL4_CPtr reply) { /* handle last fault */ ip += UD_INSTRUCTION_SIZE; seL4_ReplyWith1MR(ip, reply); /* tell benchmark we are done */ seL4_Signal(done_ep); /* block */ seL4_Wait(ep, NULL); }
void testEP(env_t env) { UNUSED int error; cspacepath_t epb1; //badged endpoint (derived from env->aep) seL4_CapData_t badge1 = seL4_CapData_Badge_new (1); //mint a badged endpoint with badge value 1 error = vka_mint_object(&env->vka, &env->aep, &epb1, seL4_CanWrite, badge1); assert(error == 0); cspacepath_t epb2; //badged endpoint (derived from env->aep) seL4_CapData_t badge2 = seL4_CapData_Badge_new (2); //mint a badged endpoint with badge value 2 error = vka_mint_object(&env->vka, &env->aep, &epb2, seL4_CanWrite, badge2); assert(error == 0); seL4_Notify(epb1.capPtr, 0); seL4_Notify(epb2.capPtr, 0); seL4_Word senderBadge; seL4_Wait(env->aep.cptr, &senderBadge); printf("senderBadge= %d\n", senderBadge); //prints 3; the two badges 1|2 //======================================= // uint32_t label = 0xF; // uint32_t capsUnwrapped = 0; // uint32_t extraCaps = 0; // uint32_t length = 3; // seL4_MessageInfo_t tag = seL4_MessageInfo_new( // label, capsUnwrapped, extraCaps, length); // seL4_SetMR(0, 0); //0xAFF); // seL4_SetMR(1, 0); //0xBFF); // seL4_SetMR(2, 0xCFF); // seL4_SetMR(3, 0xDFF); // seL4_SetMR(4, 0xEFF); // seL4_SetMR(5, 0xFFF); // seL4_NBSend(epb1.capPtr, tag); // tag = seL4_Wait(env->aep.cptr, &senderBadge); // printf("senderBadge %d\n", senderBadge); // // // in build/x86/pc99/libsel4/include/sel4/types_gen.h // label = seL4_MessageInfo_get_label(tag); // length = seL4_MessageInfo_get_length(tag); // // printf("** label=%x \n", label); // printf("** length=%x \n", length); // printf("** seL4_GetMR0=%x \n", seL4_GetMR(0)); // printf("** seL4_GetMR1=%x \n", seL4_GetMR(1)); // printf("** seL4_GetMR2=%x \n", seL4_GetMR(2)); // printf("** seL4_GetMR3=%x \n", seL4_GetMR(3)); // printf("** seL4_GetMR4=%x \n", seL4_GetMR(4)); // printf("** seL4_GetMR4=%x \n", seL4_GetMR(5)); }
/*! @brief Main CPIO file server message loop. Simply loops through recieving and dispatching messages repeatedly. */ static void fileserv_mainloop(void) { struct fs_state *s = &fileServ; srv_msg_t msg; while (1) { dvprintf("Fileserver blocking for message...\n"); msg.message = seL4_Wait(fileServCommon->anonEP, &msg.badge); fileserv_handle_message(s, &msg); client_table_postaction(&fileServCommon->clientTable); } }
/*! @brief Main timer server message loop. Simply loops through recieving and dispatching messages repeatedly. */ static void timer_server_mainloop(void) { struct timeserv_state *s = &timeServ; srv_msg_t msg; seL4_DebugPrintf("timer1 will go EP\n"); while (1) { seL4_DebugPrintf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<start to receive on EP<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); msg.message = seL4_Wait(s->commonState.anonEP, &msg.badge); seL4_DebugPrintf("<<<<<<<<<<<<<<<<<<<<<<<<<<<timeserver resume on EP>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); timer_server_handle_message(s, &msg); client_table_postaction(&s->commonState.clientTable); } }
static int test_thread(void * arg) { struct timeserv_state *s = &timeServ; srv_msg_t msg; seL4_DebugPrintf("timer2 will go AEP\n"); while(1) { seL4_DebugPrintf("\n################# Blocked on AEP #################\n"); msg.message = seL4_Wait(s->commonState.notifyAsyncEP, &msg.badge); seL4_DebugPrintf("\n@@@@@@@@@@@@@@@@@ Resumed on AEP @@@@@@@@@@@@@@@@@\n"); timer_server_handle_message(s, &msg); client_table_postaction(&s->commonState.clientTable); } return 0; }
void reply_to_parent(seL4_Word result) { seL4_MessageInfo_t info = seL4_MessageInfo_new(result, 0, 0, 0); seL4_Word badge = 0; /* ignored */ seL4_Word empty = 0; /* ignored */ #if defined(CONFIG_ARCH_IA32) #if defined(CONFIG_KERNEL_RT) seL4_SendWithMRs(shared_endpoint, info, &empty); #else seL4_SendWithMRs(shared_endpoint, info, &empty, &empty); #endif /* CONFIG_KERNEL_RT */ #else seL4_SendWithMRs(shared_endpoint, info, &empty, &empty, &empty, &empty); #endif /* CONFIG_ARCH_IA32 */ /* Block to avoid returning and assume our parent will kill us. */ seL4_Wait(shared_endpoint, &badge); }
void ticker_fn(ccnt_t *results, volatile ccnt_t *current_time) { seL4_Word start, end_low; ccnt_t end; seL4_Word badge; for (int i = 0; i < N_RUNS; i++) { /* wait for irq */ seL4_Wait(timer_signal, &badge); /* record result */ SEL4BENCH_READ_CCNT(end); sel4platsupport_handle_timer_irq(timer, badge); end_low = (seL4_Word) end; start = (seL4_Word) *current_time; results[i] = end_low - start; } seL4_Signal(done_ep); }
int run(void) { printf("%s instance starting up, going to be listening on %s:%d\n", get_instance_name(), ip_addr, ECHO_PORT); int socket_in = echo_control_open(false); if (socket_in == -1) { assert(!"Failed to open a socket for listening!"); } listener_socket = echo_control_open(false); if (listener_socket == -1) { assert(!"Failed to open a socket for echoing!"); } int ret = echo_control_bind(socket_in, PICOSERVER_ANY_ADDR_IPV4, ECHO_PORT); if (ret) { assert(!"Failed to bind a socket for listening!"); } ret = echo_control_listen(socket_in, 1); if (ret) { assert(!"Failed to listen for incoming connections!"); } uint32_t ip = 0; pico_string_to_ipv4(ip_addr, &ip); ret = echo_control_connect(listener_socket, ip, LISTENER_PORT); if (ret) { assert(!"Failed to connect to the listener!"); } /* Now poll for events and handle them */ seL4_Word badge; while (1) { seL4_Wait(echo_control_notification(), &badge); handle_picoserver_notification(); } }
void syscall_loop(seL4_CPtr ep) { while (1) { //dprintf(3, "looping\n"); seL4_Word badge; seL4_Word label; seL4_MessageInfo_t message; message = seL4_Wait(ep, &badge); //dprintf(3, "badge=0x%x\n", badge); label = seL4_MessageInfo_get_label(message); if(badge & IRQ_EP_BADGE){ /* Interrupt */ if (badge & IRQ_BADGE_NETWORK) { network_irq(); } if (badge & IRQ_BADGE_TIMER) { int ret = timer_interrupt(); if (ret != CLOCK_R_OK) { //What now? } } }else if(label == seL4_VMFault){ /* Page fault */ dprintf(3, "user with pid = %d, 0x%08x is having a vmfault\n", badge & ~USER_EP_BADGE, badge); set_cur_proc(badge & ~USER_EP_BADGE); handle_pagefault(); }else if(label == seL4_NoFault) { /* System call */ dprintf(3, "user with pid = %d, 0x%08x is making a syscall\n", badge & ~USER_EP_BADGE, badge); set_cur_proc(badge & ~USER_EP_BADGE); handle_syscall(badge, seL4_MessageInfo_get_length(message) - 1); }else{ dprintf(3, "Rootserver got an unknown message\n"); } } }
/* function to run in the new thread */ void thread_2(void) { seL4_Word sender_badge; seL4_MessageInfo_t tag; seL4_Word msg; printf("thread_2: hallo wereld\n"); /* wait for a message to come in over the endpoint */ tag = seL4_Wait(ep_cap, &sender_badge); /* make sure it is what we expected */ assert(sender_badge == EP_BADGE); assert(seL4_MessageInfo_get_length(tag) == 1); /* get the message stored in the first message register */ msg = seL4_GetMR(0); printf("thread_2: got a message %#x from %#x\n", msg, sender_badge); /* modify the message and send it back */ seL4_SetMR(0, ~msg); seL4_ReplyWait(ep_cap, tag, &sender_badge); }
int main() { UNUSED int err; setup_system(); /* enable serial driver */ platsupport_serial_setup_simple(NULL, &simple, &vka); printf("\n\n>>>>>>>>>> multi-irqs <<<<<<<<<< \n\n"); simple_print(&simple); /* TODO: lots of duplicate code here ... */ chardev_t serial1; chardev_t serial2; chardev_t keyboard; struct ps_io_ops opsIO; sel4platsupport_get_io_port_ops(&opsIO.io_port_ops, &simple); ps_chardevice_t *ret; ret = ps_cdev_init(PS_SERIAL0, &opsIO, &serial1.dev); assert(ret != NULL); ret = ps_cdev_init(PS_SERIAL1, &opsIO, &serial2.dev); assert(ret != NULL); ret = ps_cdev_init(PC99_KEYBOARD_PS2, &opsIO, &keyboard.dev); assert(ret != NULL); /////////////////// /* async endpoint*/ vka_object_t aep; // create endpoint err = vka_alloc_async_endpoint(&vka, &aep); assert(err == 0); seL4_CapData_t badge1 = seL4_CapData_Badge_new (1); //mint a badged endpoint with badge value 1 err = vka_mint_object(&vka, &aep, &serial1.ep, seL4_AllRights, badge1); assert(err == 0); seL4_CapData_t badge2 = seL4_CapData_Badge_new (2); //mint a badged endpoint with badge value 2 err = vka_mint_object(&vka, &aep, &serial2.ep, seL4_AllRights, badge2); assert(err == 0); seL4_CapData_t badge3 = seL4_CapData_Badge_new (4); //mint a badged endpoint with badge value 4 err = vka_mint_object(&vka, &aep, &keyboard.ep, seL4_AllRights, badge3); assert(err == 0); /////////////////// set_devEp(&serial1); set_devEp(&serial2); set_devEp(&keyboard); for (;;) { seL4_Word sender_badge; printf("waiting:\n"); UNUSED seL4_MessageInfo_t msg = seL4_Wait(aep.cptr, &sender_badge); printf("seL4_Wait returned with badge: %d\n", sender_badge); if (sender_badge & 1) { handle_cdev_event("serial1", &serial1); } if (sender_badge & 2) { handle_cdev_event("serial2", &serial2); } if (sender_badge & 4) { handle_cdev_event("keyboard", &keyboard); } } return 0; }
/* Entry point of of VMM main host module. */ void vmm_run(vmm_t *vmm) { int error; DPRINTF(2, "VMM MAIN HOST MODULE STARTED\n"); for (int i = 0; i < vmm->num_vcpus; i++) { vmm_vcpu_t *vcpu = &vmm->vcpus[i]; vcpu->guest_state.virt.interrupt_halt = 0; vcpu->guest_state.exit.in_exit = 0; /* sync the existing guest state */ vmm_sync_guest_state(vcpu); vmm_sync_guest_context(vcpu); /* now invalidate everything */ assert(vmm_guest_state_no_modified(&vcpu->guest_state)); vmm_guest_state_invalidate_all(&vcpu->guest_state); } /* Start the boot vcpu guest thread running */ vmm->vcpus[BOOT_VCPU].online = 1; /* Get our interrupt pending callback happening */ seL4_CPtr notification = vmm->plat_callbacks.get_async_event_notification(); error = seL4_TCB_BindNotification(simple_get_init_cap(&vmm->host_simple, seL4_CapInitThreadTCB), vmm->plat_callbacks.get_async_event_notification()); assert(error == seL4_NoError); while (1) { /* Block and wait for incoming msg or VM exits. */ seL4_Word badge; int fault; vmm_vcpu_t *vcpu = &vmm->vcpus[BOOT_VCPU]; if (vcpu->online && !vcpu->guest_state.virt.interrupt_halt && !vcpu->guest_state.exit.in_exit) { seL4_SetMR(0, vmm_guest_state_get_eip(&vcpu->guest_state)); seL4_SetMR(1, vmm_guest_state_get_control_ppc(&vcpu->guest_state)); seL4_SetMR(2, vmm_guest_state_get_control_entry(&vcpu->guest_state)); fault = seL4_VMEnter(vcpu->guest_vcpu, &badge); if (fault == SEL4_VMENTER_RESULT_FAULT) { /* We in a fault */ vcpu->guest_state.exit.in_exit = 1; /* Update the guest state from a fault */ seL4_Word fault_message[SEL4_VMENTER_RESULT_FAULT_LEN]; for (int i = 0 ; i < SEL4_VMENTER_RESULT_FAULT_LEN; i++) { fault_message[i] = seL4_GetMR(i); } vmm_guest_state_invalidate_all(&vcpu->guest_state); vmm_update_guest_state_from_fault(vcpu, fault_message); } else { /* update the guest state from a non fault */ seL4_Word int_message[SEL4_VMENTER_RESULT_NOTIF_LEN]; for (int i = 0 ; i < SEL4_VMENTER_RESULT_NOTIF_LEN; i++) { int_message[i] = seL4_GetMR(i); } vmm_guest_state_invalidate_all(&vcpu->guest_state); vmm_update_guest_state_from_interrupt(vcpu, int_message); } } else { seL4_Wait(notification, &badge); fault = SEL4_VMENTER_RESULT_NOTIF; } if (fault == SEL4_VMENTER_RESULT_NOTIF) { assert(badge >= vmm->num_vcpus); /* assume interrupt */ int raise = vmm->plat_callbacks.do_async(badge); if (raise == 0) { /* Check if this caused PIC to generate interrupt */ vmm_check_external_interrupt(vmm); } continue; } /* Handle the vm exit */ vmm_handle_vm_exit(vcpu); vmm_check_external_interrupt(vmm); DPRINTF(5, "VMM main host blocking for another message...\n"); } }
/* * mmap service */ int mmap_main (void) { while (1) { seL4_Word badge = 0; seL4_Wait (_mmap_ep, &badge); int do_reply = false; if (badge == 0) { seL4_Word method = seL4_GetMR (0); if (method == MMAP_REQUEST) { /* queue request from root server */ do_reply = mmap_queue_schedule ( seL4_GetMR (1), seL4_GetMR (2), (struct frameinfo*)seL4_GetMR (3), (void*)seL4_GetMR (4), (struct pawpaw_event*)seL4_GetMR (5)); if (do_reply) { seL4_Notify (rootserver_async_cap, MMAP_IRQ); } } else if (method == MMAP_RESULT) { /* root server wanted to read some data out of our queue */ seL4_MessageInfo_t reply = seL4_MessageInfo_new (0, 0, 0, 3); if (!done_queue) { seL4_SetMR (0, 0); seL4_SetMR (1, 0); seL4_SetMR (2, 0); } else { seL4_SetMR (0, (seL4_Word)done_queue->cb); seL4_SetMR (1, (seL4_Word)done_queue->evt); seL4_SetMR (2, (seL4_Word)done_queue->frame); struct mmap_queue_item* cur = done_queue; done_queue = done_queue->next; free (cur); } seL4_Reply (reply); } else { panic ("unknown request from rootsvr\n"); } } else { /* response from filesystem */ struct frameinfo* evt_id = (struct frameinfo*)seL4_GetMR (1); /* find the matching mmap request */ struct mmap_queue_item* q = mmap_queue; while (q) { /* FIXME: ensure amount (MR0) == PAGE_SIZE or needed amount */ if (q->frame == evt_id) { q = mmap_move_done (q); break; } q = q->next; } /* read finished, notify server if we found one */ if (q) { seL4_Notify (rootserver_async_cap, MMAP_IRQ); } } } return 0; }
int main_continued(void) { vm_t vm; int err; /* setup for restart with a setjmp */ while (setjmp(restart_jmp_buf) != 0) { reset_resources(); } restart_tcb = camkes_get_tls()->tcb_cap; restart_event_reg_callback(restart_event, NULL); err = vmm_init(); assert(!err); print_cpio_info(); /* Create the VM */ err = vm_create(VM_NAME, VM_PRIO, _fault_endpoint, VM_BADGE, &_vka, &_simple, &_vspace, &_io_ops, &vm); if (err) { printf("Failed to create VM\n"); seL4_DebugHalt(); return -1; } /* HACK: See if we have a "RAM device" for 1-1 mappings */ map_unity_ram(&vm); /* Load system images */ printf("Loading Linux: \'%s\' dtb: \'%s\'\n", VM_LINUX_NAME, VM_LINUX_DTB_NAME); err = load_linux(&vm, VM_LINUX_NAME, VM_LINUX_DTB_NAME); if (err) { printf("Failed to load VM image\n"); seL4_DebugHalt(); return -1; } vm_vchan_setup(&vm); /* Power on */ printf("Starting VM\n\n"); err = vm_start(&vm); if (err) { printf("Failed to start VM\n"); seL4_DebugHalt(); return -1; } /* Loop forever, handling events */ while (1) { seL4_MessageInfo_t tag; seL4_Word sender_badge; tag = seL4_Wait(_fault_endpoint, &sender_badge); if (sender_badge == 0) { seL4_Word label; label = seL4_MessageInfo_get_label(tag); if (label == IRQ_MESSAGE_LABEL) { irq_server_handle_irq_ipc(_irq_server); } else { printf("Unknown label (%d) for IPC badge %d\n", label, sender_badge); } } else if (sender_badge == VUSB_NBADGE) { vusb_notify(); } else { assert(sender_badge == VM_BADGE); err = vm_event(&vm, tag); if (err) { /* Shutdown */ vm_stop(&vm); seL4_DebugHalt(); while (1); } } } return 0; }
int sync_mutex_lock(sync_mutex_t *mutex) { assert(mutex != NULL); (void)seL4_Wait(mutex->aep, NULL); __sync_synchronize(); return 0; }
/* function to run in the new thread */ void thread_2(void) { seL4_Word sender_badge; seL4_MessageInfo_t tag; seL4_Word msg; printf("thread_2: hallo wereld\n"); /* TODO 11: wait for a message to come in over the endpoint */ /* hint 1: seL4_Wait() * seL4_MessageInfo_t seL4_Wait(seL4_CPtr src, seL4_Word* sender) * @param src The capability to be invoked. * @param sender The badge of the endpoint capability that was invoked by the sender is written to this address. * @return A seL4_MessageInfo_t structure * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/sel4/arch/syscalls.h#L165 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf * * hint 2: seL4_MessageInfo_t is generated during build. * The type definition and generated field access functions are defined in a generated file: * build/x86/pc99/libsel4/include/sel4/types_gen.h * It is generated from the following definition: * https://github.com/seL4/seL4/blob/master/libsel4/include/sel4/types.bf#L35 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf */ tag = seL4_Wait(ep_object.cptr, &sender_badge); /* TODO 12: make sure it is what we expected */ /* hint 1: check the badge. is it EP_BADGE? * hint 2: we are expecting only 1 message register * hint 3: seL4_MessageInfo_get_length() * seL4_Uint32 CONST seL4_MessageInfo_get_length(seL4_MessageInfo_t seL4_MessageInfo) * @param seL4_MessageInfo the seL4_MessageInfo_t to extract a field from * @return the number of message registers delivered * seL4_MessageInfo_get_length() is generated during build. It can be found in: * build/x86/pc99/libsel4/include/sel4/types_gen.h * It is generated from the following definition: * https://github.com/seL4/seL4/blob/master/libsel4/include/sel4/types.bf#L35 * */ assert(sender_badge == EP_BADGE); assert(seL4_MessageInfo_get_length(tag) == 1); /* TODO 13: get the message stored in the first message register */ /* hint: seL4_GetMR() * seL4_Word seL4_GetMR(int i) * @param i The message register to retreive * @return The message register value * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/sel4/arch/functions.h#L33 * You can find out more about message registers in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf */ msg = seL4_GetMR(0); printf("thread_2: got a message %#x from %#x\n", msg, sender_badge); /* modify the message */ msg = ~msg; /* TODO 14: copy the modified message back into the message register */ /* hint: seL4_SetMR() * void seL4_SetMR(int i, seL4_Word mr) * @param i The message register to write * @param mr The value of the message register * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/sel4/arch/functions.h#L41 * You can find out more about message registers in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf */ seL4_SetMR(0, msg); /* TODO 15: send the message back */ /* hint 1: seL4_ReplyWait() * seL4_MessageInfo_t seL4_ReplyWait(seL4_CPtr dest, seL4_MessageInfo_t msgInfo, seL4_Word *sender) * @param dest The capability to be invoked. * @param msgInfo The messageinfo structure for the IPC. This specifies information about the message to send (such as the number of message registers to send) as the Reply part. * @param sender The badge of the endpoint capability that was invoked by the sender is written to this address. This is a result of the Wait part. * @return A seL4_MessageInfo_t structure. This is a result of the Wait part. * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/sel4/arch/syscalls.h#L324 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf * * hint 2: seL4_MessageInfo_t is generated during build. * The type definition and generated field access functions are defined in a generated file: * build/x86/pc99/libsel4/include/sel4/types_gen.h * It is generated from the following definition: * https://github.com/seL4/seL4/blob/master/libsel4/include/sel4/types.bf#L35 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf */ seL4_ReplyWait(ep_object.cptr, tag, &sender_badge); }
/* Run a single test. * Each test is launched as its own process. */ int run_test(struct testcase *test) { UNUSED int error; sel4utils_process_t test_process; /* Test intro banner. */ printf(" %s\n", test->name); error = sel4utils_configure_process(&test_process, &env.vka, &env.vspace, env.init->priority, TESTS_APP); assert(error == 0); /* set up caps about the process */ env.init->page_directory = copy_cap_to_process(&test_process, test_process.pd.cptr); env.init->root_cnode = SEL4UTILS_CNODE_SLOT; env.init->tcb = copy_cap_to_process(&test_process, test_process.thread.tcb.cptr); env.init->domain = copy_cap_to_process(&test_process, simple_get_init_cap(&env.simple, seL4_CapDomain)); #ifndef CONFIG_KERNEL_STABLE env.init->asid_pool = copy_cap_to_process(&test_process, simple_get_init_cap(&env.simple, seL4_CapInitThreadASIDPool)); #endif /* CONFIG_KERNEL_STABLE */ #ifdef CONFIG_IOMMU env.init->io_space = copy_cap_to_process(&test_process, simple_get_init_cap(&env.simple, seL4_CapIOSpace)); #endif /* CONFIG_IOMMU */ /* setup data about untypeds */ env.init->untypeds = copy_untypeds_to_process(&test_process, untypeds, num_untypeds); copy_timer_caps(env.init, &env, &test_process); /* copy the fault endpoint - we wait on the endpoint for a message * or a fault to see when the test finishes */ seL4_CPtr endpoint = copy_cap_to_process(&test_process, test_process.fault_endpoint.cptr); /* WARNING: DO NOT COPY MORE CAPS TO THE PROCESS BEYOND THIS POINT, * AS THE SLOTS WILL BE CONSIDERED FREE AND OVERRIDDEN BY THE TEST PROCESS. */ /* set up free slot range */ env.init->cspace_size_bits = CONFIG_SEL4UTILS_CSPACE_SIZE_BITS; env.init->free_slots.start = endpoint + 1; env.init->free_slots.end = (1u << CONFIG_SEL4UTILS_CSPACE_SIZE_BITS); assert(env.init->free_slots.start < env.init->free_slots.end); /* copy test name */ strncpy(env.init->name, test->name + strlen("TEST_"), TEST_NAME_MAX); #ifdef SEL4_DEBUG_KERNEL seL4_DebugNameThread(test_process.thread.tcb.cptr, env.init->name); #endif /* set up args for the test process */ char endpoint_string[10]; char sel4test_name[] = { TESTS_APP }; char zero_string[] = {"0"}; char *argv[] = {sel4test_name, zero_string, endpoint_string}; argv[0] = endpoint_string; snprintf(endpoint_string, 10, "%d", endpoint); /* spawn the process */ error = sel4utils_spawn_process_v(&test_process, &env.vka, &env.vspace, ARRAY_SIZE(argv), argv, 1); assert(error == 0); /* send env.init_data to the new process */ void *remote_vaddr = send_init_data(&env, test_process.fault_endpoint.cptr, &test_process); /* wait on it to finish or fault, report result */ seL4_Word badge; seL4_MessageInfo_t info = seL4_Wait(test_process.fault_endpoint.cptr, &badge); int result = seL4_GetMR(0); if (seL4_MessageInfo_get_label(info) != seL4_NoFault) { sel4utils_print_fault_message(info, test->name); result = FAILURE; } /* unmap the env.init data frame */ vspace_unmap_pages(&test_process.vspace, remote_vaddr, 1, PAGE_BITS_4K, NULL); /* reset all the untypeds for the next test */ for (int i = 0; i < num_untypeds; i++) { cspacepath_t path; vka_cspace_make_path(&env.vka, untypeds[i].cptr, &path); vka_cnode_revoke(&path); } /* destroy the process */ sel4utils_destroy_process(&test_process, &env.vka); test_assert(result == SUCCESS); return result; }