/* * Create an object allocator managing the root CNode's free slots */ static void create_bootstrap_allocator(struct allocator *allocator) { /* Fetch seL4 bootinfo. */ seL4_BootInfo *bootinfo = seL4_GetBootInfo(); /* Create the allocator. */ allocator_create( allocator, seL4_CapInitThreadCNode, seL4_WordBits, 0, bootinfo->empty.start, bootinfo->empty.end - bootinfo->empty.start, NULL, 0 ); /* Give the allocator all of our free memory. */ fill_allocator_with_resources(allocator, bootinfo); #ifdef CONFIG_DEBUG_BUILD /* Test out everything. */ allocator_self_test(allocator); #endif }
// Test BootInfo if it gets initialized, currently it isn't seL4_Bool test_bootinfo() { seL4_Bool failure = seL4_False; seL4_BootInfo *bi = seL4_GetBootInfo(); failure |= TEST(bi != seL4_Null); failure |= TEST(bi->nodeID == 0); return failure; }
/* * Initialize all main data structures. * * The code to initialize simple, allocman, vka, and vspace is modeled * after the "sel4test-driver" app: * https://github.com/seL4/sel4test/blob/master/apps/sel4test-driver/src/main.c */ static void setup_system() { /* initialize boot information */ bootinfo = seL4_GetBootInfo(); /* initialize simple interface */ simple_stable_init_bootinfo(&simple, bootinfo); //simple_default_init_bootinfo(simple, bootinfo); /* create an allocator */ allocman_t *allocman; allocman = bootstrap_use_current_simple(&simple, POOL_SIZE, memPool); assert(allocman); /* create a VKA */ allocman_make_vka(&vka, allocman); /* create a vspace */ UNUSED int err; err = sel4utils_bootstrap_vspace_with_bootinfo_leaky(&vspace, &allocData, seL4_CapInitThreadPD, &vka, bootinfo); assert(err == 0); /* fill allocator with virtual memory */ void *vaddr; UNUSED reservation_t vres; vres = vspace_reserve_range(&vspace, VIRT_POOL_SIZE, seL4_AllRights, 1, &vaddr); assert(vres.res); bootstrap_configure_virtual_pool(allocman, vaddr, VIRT_POOL_SIZE, seL4_CapInitThreadPD); }
/*! @brief Process server main entry point. */ int main(void) { SET_MUSLC_SYSCALL_TABLE; initialise(seL4_GetBootInfo(), &procServ); dprintf("======== RefOS Process Server ========\n"); // -----> Run Root Task Testing. #ifdef CONFIG_REFOS_RUN_TESTS test_run_all(); #endif // -----> Start RefOS system processes. int error; error = proc_load_direct("console_server", 252, "", PID_NULL, PROCESS_PERMISSION_DEVICE_IRQ | PROCESS_PERMISSION_DEVICE_MAP | PROCESS_PERMISSION_DEVICE_IOPORT); if (error) { ROS_WARNING("Procserv could not start console_server."); assert(!"RefOS system startup error."); } error = proc_load_direct("file_server", 250, "", PID_NULL, 0x0); if (error) { ROS_WARNING("Procserv could not start file_server."); assert(!"RefOS system startup error."); } // -----> Start OS level tests. #ifdef CONFIG_REFOS_RUN_TESTS error = proc_load_direct("test_os", 245, "", PID_NULL, 0x0); if (error) { ROS_WARNING("Procserv could not start test_os."); assert(!"RefOS system startup error."); } #endif // -----> Start RefOS timer server. error = proc_load_direct("selfloader", 245, "fileserv/timer_server", PID_NULL, PROCESS_PERMISSION_DEVICE_IRQ | PROCESS_PERMISSION_DEVICE_MAP | PROCESS_PERMISSION_DEVICE_IOPORT); if (error) { ROS_WARNING("Procserv could not start timer_server."); assert(!"RefOS system startup error."); } // -----> Start initial task. if (strlen(CONFIG_REFOS_INIT_TASK) > 0) { error = proc_load_direct("selfloader", CONFIG_REFOS_INIT_TASK_PRIO, CONFIG_REFOS_INIT_TASK, PID_NULL, 0x0); if (error) { ROS_WARNING("Procserv could not start initial task."); assert(!"RefOS system startup error."); } } return proc_server_loop(); }
allocman_t *test_use_current_cspace_bootinfo() { int error; allocman_t *allocman; vspace_alloc_t vspace; vka_t *vka; allocman = bootstrap_use_bootinfo(seL4_GetBootInfo(), sizeof(initial_mem_pool), initial_mem_pool); assert(allocman); vka = allocman_mspace_alloc(allocman, sizeof(*vka), &error); assert(!error); allocman_make_vka(vka, allocman); sel4util_get_vspace_alloc_leaky(&vspace, seL4_CapInitThreadPD, vka, seL4_GetBootInfo()); reservation_t *reservation = vspace_reserve_range_at(&vspace, VIRTUAL_START, MEM_POOL_SIZE, seL4_AllRights, 1); assert(reservation); bootstrap_configure_virtual_pool(allocman, VIRTUAL_START, MEM_POOL_SIZE, seL4_CapInitThreadPD); error = allocman_fill_reserves(allocman); assert(!error); return allocman; }
//============================================================================= int main(int argc, char *argv[]) { seL4_BootInfo *info = seL4_GetBootInfo(); /* initialize libsel4simple, which abstracts away which kernel version * we are running on */ #ifdef CONFIG_KERNEL_STABLE //experimental kernel simple_stable_init_bootinfo(&env.simple, info); #else //master kernel (currently) simple_default_init_bootinfo(&env.simple, info); #endif /* initialize the test environment - allocator, cspace manager, vspace manager, timer */ init_env(&env); /* enable serial driver */ platsupport_serial_setup_simple(NULL, &env.simple, &env.vka); simple_print(&env.simple); printf("\n\n>>>>>>>>>> keyboard - keyboard test <<<<<<<<<< \n\n"); printf("%d %s\n", argc, argv[0]); //from libsel4platsupport /* Set up keyboard device. */ printf("ps_cdev_init keyboard...\n"); struct ps_io_ops opsIO; sel4platsupport_get_io_port_ops(&opsIO.io_port_ops, &env.simple); ps_chardevice_t *devKeyboardRet; devKeyboardRet = ps_cdev_init(PC99_KEYBOARD_PS2, &opsIO, &conServ.devKeyboard); if (!devKeyboardRet) { printf("ERROR: could not initialize keyboard device.\n"); assert(!"ps_cdev_init failed."); exit(1); } //read from keyboard for(;;) { int c = ps_cdev_getchar(&conServ.devKeyboard); if (c != EOF) { printf("You typed [%c]\n", c); } fflush(stdout); } }
void test_use_current_1level_cspace() { int error; seL4_CPtr i; allocman_t *allocman; seL4_BootInfo *bi = seL4_GetBootInfo(); allocman = bootstrap_use_current_1level(seL4_CapInitThreadCNode, bi->initThreadCNodeSizeBits, bi->empty.start, bi->empty.end, sizeof(initial_mem_pool), initial_mem_pool); assert(allocman); /* have to add all our resources manually */ for (i = bi->untyped.start; i < bi->untyped.end; i++) { cspacepath_t slot = allocman_cspace_make_path(allocman, i); uint32_t size_bits = bi->untypedSizeBitsList[i - bi->untyped.start]; uint32_t paddr = bi->untypedPaddrList[i - bi->untyped.start]; error = allocman_utspace_add_uts(allocman, 1, &slot, &size_bits, &paddr); assert(!error); } error = allocman_fill_reserves(allocman); assert(!error); }
void test_use_current_cspace() { int error; seL4_CPtr i; allocman_t *allocman; cspace_single_level_t *cspace; utspace_trickle_t *utspace; seL4_BootInfo *bi = seL4_GetBootInfo(); allocman = bootstrap_create_allocman(sizeof(initial_mem_pool), initial_mem_pool); assert(allocman); /* construct a description of our current cspace */ cspace = allocman_mspace_alloc(allocman, sizeof(*cspace), &error); assert(!error); error = cspace_single_level_create(allocman, cspace, (struct cspace_single_level_config) { .cnode = seL4_CapInitThreadCNode, .cnode_size_bits = bi->initThreadCNodeSizeBits, .cnode_guard_bits = seL4_WordBits - bi->initThreadCNodeSizeBits, .first_slot = bi->empty.start, .end_slot = bi->empty.end });
static void _sos_init(seL4_CPtr* ipc_ep, seL4_CPtr* async_ep){ seL4_Word dma_addr; seL4_Word low, high; int err; /* Retrieve boot info from seL4 */ _boot_info = seL4_GetBootInfo(); conditional_panic(!_boot_info, "Failed to retrieve boot info\n"); if(verbose > 0){ print_bootinfo(_boot_info); } /* Initialise the untyped sub system and reserve memory for DMA */ err = ut_table_init(_boot_info); conditional_panic(err, "Failed to initialise Untyped Table\n"); /* DMA uses a large amount of memory that will never be freed */ dma_addr = ut_steal_mem(DMA_SIZE_BITS); conditional_panic(dma_addr == 0, "Failed to reserve DMA memory\n"); /* find available memory */ ut_find_memory(&low, &high); /* Initialise the untyped memory allocator */ ut_allocator_init(low, high); /* Initialise the cspace manager */ err = cspace_root_task_bootstrap(ut_alloc, ut_free, ut_translate, malloc, free); conditional_panic(err, "Failed to initialise the c space\n"); /* Initialise DMA memory */ err = dma_init(dma_addr, DMA_SIZE_BITS); conditional_panic(err, "Failed to intiialise DMA memory\n"); /* Initialise IPC */ _sos_ipc_init(ipc_ep, async_ep); /* Initialise frame table */ err = frame_init(); conditional_panic(err, "Failed to initialise frame table\n"); }
int main(void) { seL4_BootInfo *info = seL4_GetBootInfo(); /* initialize libsel4simple*/ #ifdef CONFIG_KERNEL_STABLE simple_stable_init_bootinfo(&env.simple, info); #else simple_default_init_bootinfo(&env.simple, info); #endif /* initialize the environment */ init_env(&env); /* enable serial driver */ platsupport_serial_setup_simple(NULL, &env.simple, &env.vka); printf("\n\n>>>>>>>>>> badges - test badged endpoints <<<<<<<<<< \n\n"); simple_print(&env.simple); testEP(&env); return 0; }
/** * No parameters are passed to main, the return * value is ignored and the program hangs. */ int main(void) { seL4_BootInfo *bi = seL4_GetBootInfo(); libsel4_printf("bi=%p\n", bi); libsel4_printf("bi->nodeId=%d\n", bi->nodeID); libsel4_printf("bi->numNodes=%d\n", bi->numNodes); libsel4_printf("bi->numIOPTLevels=%d\n", bi->numIOPTLevels); libsel4_printf("bi->ipcBuffer=%p\n", bi->ipcBuffer); libsel4_printf("bi->empty=%p ", &bi->empty); println_SlotRegion(&bi->empty); libsel4_printf("bi->sharedFrames=%p ", &bi->sharedFrames); println_SlotRegion(&bi->sharedFrames); libsel4_printf("bi->userImageFrames=%p ", &bi->userImageFrames); println_SlotRegion(&bi->userImageFrames); libsel4_printf("bi->userImagePDs=%p ", &bi->userImagePDs); println_SlotRegion(&bi->userImagePDs); libsel4_printf("bi->userImagePTs=%p ", &bi->userImagePTs); println_SlotRegion(&bi->userImagePTs); libsel4_printf("bi->untyped=%p ", &bi->untyped); println_SlotRegion(&bi->untyped); libsel4_printf("bi->untypedPaddrList=%p\n", bi->untypedPaddrList); for(int i=0; i < CONFIG_MAX_NUM_BOOTINFO_UNTYPED_CAPS; i++) { libsel4_printf("bi->untypedPaddrList[%d] 0x%x\n", i, bi->untypedPaddrList[i]); } libsel4_printf("bi->untypedSizeBitsList=%p\n", bi->untypedSizeBitsList); for(int i=0; i < CONFIG_MAX_NUM_BOOTINFO_UNTYPED_CAPS; i++) { libsel4_printf("bi->untypedSizeBitsList[%d] 0x%x\n", i, bi->untypedSizeBitsList[i]); } libsel4_printf("bi->initThreadCNodeSizeBits=%d\n", bi->initThreadCNodeSizeBits); libsel4_printf("bi->numDeviceRegions=%d\n", bi->numDeviceRegions); for(int i=0; i < CONFIG_MAX_NUM_BOOTINFO_DEVICE_REGIONS; i++) { libsel4_printf("bi->deviceRegions[%d] ", i); println_DeviceRegion(&bi->deviceRegions[i]); } libsel4_printf("bi->initThreadDomain=%d\n", bi->initThreadDomain); return 0; }
int main(void) { UNUSED int error; /* Set up logging and give us a name: useful for debugging if the thread faults */ zf_log_set_tag_prefix("hello-3:"); name_thread(seL4_CapInitThreadTCB, "hello-3"); /* get boot info */ info = seL4_GetBootInfo(); /* init simple */ simple_default_init_bootinfo(&simple, info); /* print out bootinfo and other info about simple */ simple_print(&simple); /* create an allocator */ allocman = bootstrap_use_current_simple(&simple, ALLOCATOR_STATIC_POOL_SIZE, allocator_mem_pool); ZF_LOGF_IF(allocman == NULL, "Failed to initialize alloc manager.\n" "\tMemory pool sufficiently sized?\n" "\tMemory pool pointer valid?\n"); /* create a vka (interface for interacting with the underlying allocator) */ allocman_make_vka(&vka, allocman); /* get our cspace root cnode */ seL4_CPtr cspace_cap; cspace_cap = simple_get_cnode(&simple); /* get our vspace root page directory */ seL4_CPtr pd_cap; pd_cap = simple_get_pd(&simple); /* create a new TCB */ vka_object_t tcb_object = {0}; error = vka_alloc_tcb(&vka, &tcb_object); ZF_LOGF_IFERR(error, "Failed to allocate new TCB.\n" "\tVKA given sufficient bootstrap memory?"); /* * create and map an ipc buffer: */ /* TODO 1: get a frame cap for the ipc buffer */ /* hint: vka_alloc_frame() * int vka_alloc_frame(vka_t *vka, uint32_t size_bits, vka_object_t *result) * @param vka Pointer to vka interface. * @param size_bits Frame size: 2^size_bits * @param result Structure for the Frame object. This gets initialised. * @return 0 on success * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_1: */ vka_object_t ipc_frame_object; error = vka_alloc_frame(&vka, IPCBUF_FRAME_SIZE_BITS, &ipc_frame_object); ZF_LOGF_IFERR(error, "Failed to alloc a frame for the IPC buffer.\n" "\tThe frame size is not the number of bytes, but an exponent.\n" "\tNB: This frame is not an immediately usable, virtually mapped page.\n") /* * map the frame into the vspace at ipc_buffer_vaddr. * To do this we first try to map it in to the root page directory. * If there is already a page table mapped in the appropriate slot in the * page diretory where we can insert this frame, then this will succeed. * Otherwise we first need to create a page table, and map it in to * the page directory, before we can map the frame in. */ seL4_Word ipc_buffer_vaddr = IPCBUF_VADDR; /* TODO 2: try to map the frame the first time */ /* hint 1: seL4_ARCH_Page_Map() * The *ARCH* versions of seL4 sys calls are abstractions over the architecture provided by libsel4utils * this one is defined as: * #define seL4_ARCH_Page_Map seL4_X86_Page_Map * in: Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_2: * The signature for the underlying function is: * int seL4_X86_Page_Map(seL4_X86_Page service, seL4_X86_PageDirectory pd, seL4_Word vaddr, seL4_CapRights rights, seL4_X86_VMAttributes attr) * @param service Capability to the page to map. * @param pd Capability to the VSpace which will contain the mapping. * @param vaddr Virtual address to map the page into. * @param rights Rights for the mapping. * @param attr VM Attributes for the mapping. * @return 0 on success. * * Note: this function is generated during build. It is generated from the following definition: * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_2: * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.pdf * * hint 2: for the rights, use seL4_AllRights * hint 3: for VM attributes use seL4_ARCH_Default_VMAttributes * Hint 4: It is normal for this function call to fail. That means there are * no page tables with free slots -- proceed to the next step where you'll * be led to allocate a new empty page table and map it into the VSpace, * before trying again. */ error = seL4_ARCH_Page_Map(ipc_frame_object.cptr, pd_cap, ipc_buffer_vaddr, seL4_AllRights, seL4_ARCH_Default_VMAttributes); if (error != 0) { /* TODO 3: create a page table */ /* hint: vka_alloc_page_table() * int vka_alloc_page_table(vka_t *vka, vka_object_t *result) * @param vka Pointer to vka interface. * @param result Structure for the PageTable object. This gets initialised. * @return 0 on success * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_3: */ vka_object_t pt_object; error = vka_alloc_page_table(&vka, &pt_object); ZF_LOGF_IFERR(error, "Failed to allocate new page table.\n"); /* TODO 4: map the page table */ /* hint 1: seL4_ARCH_PageTable_Map() * The *ARCH* versions of seL4 sys calls are abstractions over the architecture provided by libsel4utils * this one is defined as: * #define seL4_ARCH_PageTable_Map seL4_X86_PageTable_Map * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_4: * The signature for the underlying function is: * int seL4_X86_PageTable_Map(seL4_X86_PageTable service, seL4_X86_PageDirectory pd, seL4_Word vaddr, seL4_X86_VMAttributes attr) * @param service Capability to the page table to map. * @param pd Capability to the VSpace which will contain the mapping. * @param vaddr Virtual address to map the page table into. * @param rights Rights for the mapping. * @param attr VM Attributes for the mapping. * @return 0 on success. * * Note: this function is generated during build. It is generated from the following definition: * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_4: * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.pdf * * hint 2: for VM attributes use seL4_ARCH_Default_VMAttributes */ error = seL4_ARCH_PageTable_Map(pt_object.cptr, pd_cap, ipc_buffer_vaddr, seL4_ARCH_Default_VMAttributes); ZF_LOGF_IFERR(error, "Failed to map page table into VSpace.\n" "\tWe are inserting a new page table into the top-level table.\n" "\tPass a capability to the new page table, and not for example, the IPC buffer frame vaddr.\n") /* TODO 5: then map the frame in */ /* hint 1: use seL4_ARCH_Page_Map() as above * hint 2: for the rights, use seL4_AllRights * hint 3: for VM attributes use seL4_ARCH_Default_VMAttributes */ error = seL4_ARCH_Page_Map(ipc_frame_object.cptr, pd_cap, ipc_buffer_vaddr, seL4_AllRights, seL4_ARCH_Default_VMAttributes); ZF_LOGF_IFERR(error, "Failed again to map the IPC buffer frame into the VSpace.\n" "\t(It's not supposed to fail.)\n" "\tPass a capability to the IPC buffer's physical frame.\n" "\tRevisit the first seL4_ARCH_Page_Map call above and double-check your arguments.\n"); } /* set the IPC buffer's virtual address in a field of the IPC buffer */ seL4_IPCBuffer *ipcbuf = (seL4_IPCBuffer*)ipc_buffer_vaddr; ipcbuf->userData = ipc_buffer_vaddr; /* TODO 6: create an endpoint */ /* hint: vka_alloc_endpoint() * int vka_alloc_endpoint(vka_t *vka, vka_object_t *result) * @param vka Pointer to vka interface. * @param result Structure for the Endpoint object. This gets initialised. * @return 0 on success * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_6: */ error = vka_alloc_endpoint(&vka, &ep_object); ZF_LOGF_IFERR(error, "Failed to allocate new endpoint object.\n"); /* TODO 7: make a badged copy of it in our cspace. This copy will be used to send * an IPC message to the original cap */ /* hint 1: vka_mint_object() * int vka_mint_object(vka_t *vka, vka_object_t *object, cspacepath_t *result, seL4_CapRights rights, seL4_CapData_t badge) * @param[in] vka The allocator for the cspace. * @param[in] object Target object for cap minting. * @param[out] result Allocated cspacepath. * @param[in] rights The rights for the minted cap. * @param[in] badge The badge for the minted cap. * @return 0 on success * * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_7: * * hint 2: for the rights, use seL4_AllRights * hint 3: for the badge use seL4_CapData_Badge_new() * seL4_CapData_t CONST seL4_CapData_Badge_new(seL4_Uint32 Badge) * @param[in] Badge The badge number to use * @return A CapData structure containing the desired badge info * * seL4_CapData_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: * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_7: * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.pdf * * hint 4: for the badge use EP_BADGE */ error = vka_mint_object(&vka, &ep_object, &ep_cap_path, seL4_AllRights, seL4_CapData_Badge_new(EP_BADGE)); ZF_LOGF_IFERR(error, "Failed to mint new badged copy of IPC endpoint.\n" "\tseL4_Mint is the backend for vka_mint_object.\n" "\tseL4_Mint is simply being used here to create a badged copy of the same IPC endpoint.\n" "\tThink of a badge in this case as an IPC context cookie.\n"); /* initialise the new TCB */ error = seL4_TCB_Configure(tcb_object.cptr, seL4_CapNull, seL4_PrioProps_new(seL4_MaxPrio, seL4_MaxPrio), cspace_cap, seL4_NilData, pd_cap, seL4_NilData, ipc_buffer_vaddr, ipc_frame_object.cptr); ZF_LOGF_IFERR(error, "Failed to configure the new TCB object.\n" "\tWe're running the new thread with the root thread's CSpace.\n" "\tWe're running the new thread in the root thread's VSpace.\n"); /* give the new thread a name */ name_thread(tcb_object.cptr, "hello-3: thread_2"); /* set start up registers for the new thread */ seL4_UserContext regs = {0}; size_t regs_size = sizeof(seL4_UserContext) / sizeof(seL4_Word); /* set instruction pointer where the thread shoud start running */ sel4utils_set_instruction_pointer(®s, (seL4_Word)thread_2); /* check that stack is aligned correctly */ const int stack_alignment_requirement = sizeof(seL4_Word) * 2; uintptr_t thread_2_stack_top = (uintptr_t)thread_2_stack + sizeof(thread_2_stack); ZF_LOGF_IF(thread_2_stack_top % (stack_alignment_requirement) != 0, "Stack top isn't aligned correctly to a %dB boundary.\n" "\tDouble check to ensure you're not trampling.", stack_alignment_requirement); /* set stack pointer for the new thread. remember the stack grows down */ sel4utils_set_stack_pointer(®s, thread_2_stack_top); /* set the fs register for IPC buffer */ regs.fs = IPCBUF_GDT_SELECTOR; /* actually write the TCB registers. */ error = seL4_TCB_WriteRegisters(tcb_object.cptr, 0, 0, regs_size, ®s); ZF_LOGF_IFERR(error, "Failed to write the new thread's register set.\n" "\tDid you write the correct number of registers? See arg4.\n"); /* start the new thread running */ error = seL4_TCB_Resume(tcb_object.cptr); ZF_LOGF_IFERR(error, "Failed to start new thread.\n"); /* we are done, say hello */ printf("main: hello world\n"); /* * now send a message to the new thread, and wait for a reply */ seL4_Word msg; seL4_MessageInfo_t tag; /* TODO 8: set the data to send. We send it in the first message register */ /* hint 1: seL4_MessageInfo_new() * seL4_MessageInfo_t CONST seL4_MessageInfo_new(seL4_Uint32 label, seL4_Uint32 capsUnwrapped, seL4_Uint32 extraCaps, seL4_Uint32 length) * @param label The value of the label field * @param capsUnwrapped The value of the capsUnwrapped field * @param extraCaps The value of the extraCaps field * @param length The number of message registers to send * @return The seL4_MessageInfo_t containing the given values. * * seL4_MessageInfo_new() 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: * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_8: * * hint 2: use 0 for the first 3 fields. * hint 3: send only 1 message register of data * * hint 4: 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 * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_8: * You can find out more about message registers in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.pdf * * hint 5: send MSG_DATA */ tag = seL4_MessageInfo_new(0, 0, 0, 1); seL4_SetMR(0, MSG_DATA); /* TODO 9: send and wait for a reply. */ /* hint: seL4_Call() * seL4_MessageInfo_t seL4_Call(seL4_CPtr dest, seL4_MessageInfo_t msgInfo) * @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). * @return A seL4_MessageInfo_t structure. This is information about the repy message. * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_9: * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.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: * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_9: * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.pdf */ tag = seL4_Call(ep_cap_path.capPtr, tag); /* TODO 10: get the reply message */ /* hint: seL4_GetMR() * seL4_Word seL4_GetMR(int i) * @param i The message register to retreive * @return The message register value * Link to source: https://wiki.sel4.systems/seL4%20Tutorial%203#TODO_10: * You can find out more about message registers in the API manual: http://sel4.systems/Info/Docs/seL4-manual-3.0.0.pdf */ msg = seL4_GetMR(0); /* check that we got the expected repy */ ZF_LOGF_IF(seL4_MessageInfo_get_length(tag) != 1, "Response data from thread_2 was not the length expected.\n" "\tHow many registers did you set with seL4_SetMR within thread_2?\n"); ZF_LOGF_IF(msg != ~MSG_DATA, "Response data from thread_2's content was not what was expected.\n"); printf("main: got a reply: %#x\n", msg); return 0; }
/* initialise our runtime environment */ static void init_env(env_t env) { allocman_t *allocman; UNUSED reservation_t virtual_reservation; UNUSED int error; /* create an allocator */ allocman = bootstrap_use_current_simple(&env->simple, ALLOCATOR_STATIC_POOL_SIZE, allocator_mem_pool); assert(allocman); /* create a vka (interface for interacting with the underlying allocator) */ allocman_make_vka(&env->vka, allocman); /* create a vspace (virtual memory management interface). We pass * boot info not because it will use capabilities from it, but so * it knows the address and will add it as a reserved region */ error = sel4utils_bootstrap_vspace_with_bootinfo_leaky(&env->vspace, &data, simple_get_pd(&env->simple), &env->vka, seL4_GetBootInfo()); /* fill the allocator with virtual memory */ void *vaddr; virtual_reservation = vspace_reserve_range(&env->vspace, ALLOCATOR_VIRTUAL_POOL_SIZE, seL4_AllRights, 1, &vaddr); assert(virtual_reservation.res); bootstrap_configure_virtual_pool(allocman, vaddr, ALLOCATOR_VIRTUAL_POOL_SIZE, simple_get_pd(&env->simple)); }
int main(void) { UNUSED int error; /* give us a name: useful for debugging if the thread faults */ name_thread(seL4_CapInitThreadTCB, "hello-2"); /* get boot info */ info = seL4_GetBootInfo(); /* init simple */ simple_default_init_bootinfo(&simple, info); /* print out bootinfo and other info about simple */ simple_print(&simple); /* create an allocator */ allocman = bootstrap_use_current_simple(&simple, ALLOCATOR_STATIC_POOL_SIZE, allocator_mem_pool); assert(allocman); /* create a vka (interface for interacting with the underlying allocator) */ allocman_make_vka(&vka, allocman); /* get our cspace root cnode */ seL4_CPtr cspace_cap; cspace_cap = simple_get_cnode(&simple); /* get our vspace root page diretory */ seL4_CPtr pd_cap; pd_cap = simple_get_pd(&simple); /* create a new TCB */ vka_object_t tcb_object = {0}; error = vka_alloc_tcb(&vka, &tcb_object); assert(error == 0); /* initialise the new TCB */ error = seL4_TCB_Configure(tcb_object.cptr, seL4_CapNull, seL4_MaxPrio, cspace_cap, seL4_NilData, pd_cap, seL4_NilData, 0, 0); assert(error == 0); /* give the new thread a name */ name_thread(tcb_object.cptr, "hello-2: thread_2"); /* set start up registers for the new thread: */ seL4_UserContext regs = {0}; /* set instruction pointer where the thread shoud start running */ sel4utils_set_instruction_pointer(®s, (seL4_Word)thread_2); /* check that stack is aligned correctly */ uintptr_t thread_2_stack_top = (uintptr_t)thread_2_stack + sizeof(thread_2_stack); assert(thread_2_stack_top % (sizeof(seL4_Word) * 2) == 0); /* set stack pointer for the new thread. remember the stack grows down */ sel4utils_set_stack_pointer(®s, thread_2_stack_top); /* actually write the TCB registers. we write 2 registers: * instruction pointer is first, stack pointer is second. */ error = seL4_TCB_WriteRegisters(tcb_object.cptr, 0, 0, 2, ®s); assert(error == 0); /* start the new thread running */ error = seL4_TCB_Resume(tcb_object.cptr); assert(error == 0); /* we are done, say hello */ printf("main: hello world\n"); return 0; }
int main(void) { int error; /* give us a name: useful for debugging if the thread faults */ name_thread(seL4_CapInitThreadTCB, "hello-3"); /* get boot info */ info = seL4_GetBootInfo(); /* print out bootinfo */ print_bootinfo(info); /* get our cspace root cnode */ seL4_CPtr cspace_cap; cspace_cap = seL4_CapInitThreadCNode; /* get our vspace root page directory */ seL4_CPtr pd_cap; pd_cap = seL4_CapInitThreadPD; /* TODO 1: Find free cap slots for the caps to the: * - tcb * - ipc frame * - endpoint * - badged endpoint * - page table * hint: The bootinfo struct contains a range of free cap slot indices. */ /* decide on slots to use based on what is free */ seL4_CPtr tcb_cap = ???; seL4_CPtr ipc_frame_cap = ???; ep_cap = ???; badged_ep_cap = ???; seL4_CPtr page_table_cap = ???; /* get an untyped to retype into all the objects we will need */ seL4_CPtr untyped; /* TODO 2: Obtain a cap to an untyped which is large enough to contain: * - tcb * - ipc frame * - endpoint * - badged endpoint * - page table * * hint 1: determine the size of each object * (look in libs/libsel4/arch_include/x86/sel4/arch/types.h) * hint 2: an array of untyped caps, and a corresponding array of untyped sizes * can be found in the bootinfo struct * hint 3: a single untyped cap can be retyped multiple times. Each time, an appropriately sized chunk * of the object is "chipped off". For simplicity, find a cap to an untyped which is large enough * to contain all required objects. */ /* TODO 3: Using the untyped, create the required objects, storing their caps in the roottask's root cnode. * * hint 1: int seL4_Untyped_Retype(seL4_Untyped service, int type, int size_bits, seL4_CNode root, int node_index, int node_depth, int node_offset, int num_objects) * hint 2: use a depth of 32 * hint 3: use cspace_cap for the root cnode AND the cnode_index */ /* * map the frame into the vspace at ipc_buffer_vaddr. * To do this we first try to map it in to the root page directory. * If there is already a page table mapped in the appropriate slot in the * page diretory where we can insert this frame, then this will succeed. * Otherwise we first need to create a page table, and map it in to * the page`directory, before we can map the frame in. */ seL4_Word ipc_buffer_vaddr; ipc_buffer_vaddr = IPCBUF_VADDR; error = seL4_IA32_Page_Map(ipc_frame_cap, pd_cap, ipc_buffer_vaddr, seL4_AllRights, seL4_IA32_Default_VMAttributes); if (error != 0) { /* TODO 4: Retype the untyped into page table (if this was done in TODO 3, ignore this). */ error = seL4_IA32_PageTable_Map(page_table_cap, pd_cap, ipc_buffer_vaddr, seL4_IA32_Default_VMAttributes); assert(error == 0); /* then map the frame in */ error = seL4_IA32_Page_Map(ipc_frame_cap, pd_cap, ipc_buffer_vaddr, seL4_AllRights, seL4_IA32_Default_VMAttributes); assert(error == 0); } /* set the IPC buffer's virtual address in a field of the IPC buffer */ seL4_IPCBuffer *ipcbuf = (seL4_IPCBuffer*)ipc_buffer_vaddr; ipcbuf->userData = ipc_buffer_vaddr; /* TODO 5: Mint a copy of the endpoint cap into our cspace, using the badge EP_BADGE * hint: int seL4_CNode_Mint(seL4_CNode service, seL4_Word dest_index, seL4_Uint8 dest_depth, seL4_CNode src_root, seL4_Word src_index, seL4_Uint8 src_depth, seL4_CapRights rights, seL4_CapData_t badge); */ /* initialise the new TCB */ error = seL4_TCB_Configure(tcb_cap, seL4_CapNull, seL4_MaxPrio, cspace_cap, seL4_NilData, pd_cap, seL4_NilData, ipc_buffer_vaddr, ipc_frame_cap); assert(error == 0); /* give the new thread a name */ name_thread(tcb_cap, "hello-3: thread_2"); /* set start up registers for the new thread */ size_t regs_size = sizeof(seL4_UserContext) / sizeof(seL4_Word); /* check that stack is aligned correctly */ uintptr_t thread_2_stack_top = (uintptr_t)thread_2_stack + sizeof(thread_2_stack); assert(thread_2_stack_top % (sizeof(seL4_Word) * 2) == 0); /* set instruction pointer, stack pointer and gs register (used for thread local storage) */ seL4_UserContext regs = { .eip = (seL4_Word)thread_2, .esp = (seL4_Word)thread_2_stack_top, .gs = IPCBUF_GDT_SELECTOR }; /* actually write the TCB registers. */ error = seL4_TCB_WriteRegisters(tcb_cap, 0, 0, regs_size, ®s); assert(error == 0); /* start the new thread running */ error = seL4_TCB_Resume(tcb_cap); assert(error == 0); /* we are done, say hello */ printf("main: hello world\n"); /* * now send a message to the new thread, and wait for a reply */ seL4_Word msg; seL4_MessageInfo_t tag; /* set the data to send. We send it in the first message register */ tag = seL4_MessageInfo_new(0, 0, 0, 1); seL4_SetMR(0, MSG_DATA); /* send and wait for a reply */ tag = seL4_Call(badged_ep_cap, tag); /* check that we got the expected repy */ assert(seL4_MessageInfo_get_length(tag) == 1); msg = seL4_GetMR(0); assert(msg == ~MSG_DATA); printf("main: got a reply: %#x\n", msg); return 0; }
int main(void) { int error; /* give us a name: useful for debugging if the thread faults */ name_thread(seL4_CapInitThreadTCB, "hello-2"); /* get boot info */ info = seL4_GetBootInfo(); /* print out bootinfo */ print_bootinfo(info); /* get our cspace root cnode */ seL4_CPtr cspace_cap; //cspace_cap = simple_get_cnode(&simple); cspace_cap = seL4_CapInitThreadCNode; /* get our vspace root page diretory */ seL4_CPtr pd_cap; pd_cap = seL4_CapInitThreadPD; seL4_CPtr tcb_cap; /* TODO 1: Set tcb_cap to a free cap slot index. * hint: The bootinfo struct contains a range of free cap slot indices. */ seL4_CPtr untyped; /* TODO 2: Obtain a cap to an untyped which is large enough to contain a tcb. * * hint 1: determine the size of a tcb object. * (look in libs/libsel4/arch_include/x86/sel4/arch/types.h) * hint 2: an array of untyped caps, and a corresponding array of untyped sizes * can be found in the bootinfo struct */ /* TODO 3: Retype the untyped into a tcb, storing a cap in tcb_cap * * hint 1: int seL4_Untyped_Retype(seL4_Untyped service, int type, int size_bits, seL4_CNode root, int node_index, int node_depth, int node_offset, int num_objects) * hint 2: use a depth of 32 * hint 3: use cspace_cap for the root cnode AND the cnode_index * (bonus question: What property of the calling thread's cspace must hold for this to be ok?) */ /* initialise the new TCB */ error = seL4_TCB_Configure(tcb_cap, seL4_CapNull, seL4_MaxPrio, cspace_cap, seL4_NilData, pd_cap, seL4_NilData, 0, 0); assert(error == 0); /* give the new thread a name */ name_thread(tcb_cap, "hello-2: thread_2"); uintptr_t thread_2_stack_top = (uintptr_t)thread_2_stack + sizeof(thread_2_stack); assert(thread_2_stack_top % (sizeof(seL4_Word) * 2) == 0); seL4_UserContext regs; /* TODO 4: Set up regs to contain the desired stack pointer and instruction pointer * hint 1: libsel4/arch_include/x86/sel4/arch/types.h: * ... typedef struct seL4_UserContext_ { seL4_Word eip, esp, eflags, eax, ebx, ecx, edx, esi, edi, ebp; seL4_Word tls_base, fs, gs; } seL4_UserContext; */ /* TODO 5: Write the registers in regs to the new thread * * hint 1: int seL4_TCB_WriteRegisters(seL4_TCB service, seL4_Bool resume_target, seL4_Uint8 arch_flags, seL4_Word count, seL4_UserContext *regs); * hint 2: the value of arch_flags is ignored on x86 and arm */ /* start the new thread running */ error = seL4_TCB_Resume(tcb_cap); assert(error == 0); /* we are done, say hello */ printf("main: hello world\n"); return 0; }
int main(void) { UNUSED int error; /* give us a name: useful for debugging if the thread faults */ name_thread(seL4_CapInitThreadTCB, "hello-3"); /* get boot info */ info = seL4_GetBootInfo(); /* init simple */ simple_default_init_bootinfo(&simple, info); /* print out bootinfo and other info about simple */ simple_print(&simple); /* create an allocator */ allocman = bootstrap_use_current_simple(&simple, ALLOCATOR_STATIC_POOL_SIZE, allocator_mem_pool); assert(allocman); /* create a vka (interface for interacting with the underlying allocator) */ allocman_make_vka(&vka, allocman); /* get our cspace root cnode */ seL4_CPtr cspace_cap; cspace_cap = simple_get_cnode(&simple); /* get our vspace root page directory */ seL4_CPtr pd_cap; pd_cap = simple_get_pd(&simple); /* create a new TCB */ vka_object_t tcb_object = {0}; error = vka_alloc_tcb(&vka, &tcb_object); assert(error == 0); /* * create and map an ipc buffer: */ /* TODO 1: get a frame cap for the ipc buffer */ /* hint: vka_alloc_frame() * int vka_alloc_frame(vka_t *vka, uint32_t size_bits, vka_object_t *result) * @param vka Pointer to vka interface. * @param size_bits Frame size: 2^size_bits * @param result Structure for the Frame object. This gets initialised. * @return 0 on success * https://github.com/seL4/libsel4vka/blob/master/include/vka/object.h#L147 */ vka_object_t ipc_frame_object; error = vka_alloc_frame(&vka, IPCBUF_FRAME_SIZE_BITS, &ipc_frame_object); assert(error == 0); /* * map the frame into the vspace at ipc_buffer_vaddr. * To do this we first try to map it in to the root page directory. * If there is already a page table mapped in the appropriate slot in the * page diretory where we can insert this frame, then this will succeed. * Otherwise we first need to create a page table, and map it in to * the page directory, before we can map the frame in. */ seL4_Word ipc_buffer_vaddr = IPCBUF_VADDR; /* TODO 2: try to map the frame the first time */ /* hint 1: seL4_ARCH_Page_Map() * The *ARCH* versions of seL4 sys calls are abstractions over the architecture provided by libsel4utils * this one is defined as: * #define seL4_ARCH_Page_Map seL4_IA32_Page_Map * in: https://github.com/seL4/libsel4utils/blob/master/include/sel4utils/mapping.h#L69 * The signature for the underlying function is: * int seL4_IA32_Page_Map(seL4_IA32_Page service, seL4_IA32_PageDirectory pd, seL4_Word vaddr, seL4_CapRights rights, seL4_IA32_VMAttributes attr) * @param service Capability to the page to map. * @param pd Capability to the VSpace which will contain the mapping. * @param vaddr Virtual address to map the page into. * @param rights Rights for the mapping. * @param attr VM Attributes for the mapping. * @return 0 on success. * * Note: this function is generated during build. It is generated from the following definition: * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/interfaces/sel4arch.xml#L52 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf * * hint 2: for the rights, use seL4_AllRights * hint 3: for VM attributes use seL4_ARCH_Default_VMAttributes */ error = seL4_ARCH_Page_Map(ipc_frame_object.cptr, pd_cap, ipc_buffer_vaddr, seL4_AllRights, seL4_ARCH_Default_VMAttributes); if (error != 0) { /* TODO 3: create a page table */ /* hint: vka_alloc_page_table() * int vka_alloc_page_table(vka_t *vka, vka_object_t *result) * @param vka Pointer to vka interface. * @param result Structure for the PageTable object. This gets initialised. * @return 0 on success * https://github.com/seL4/libsel4vka/blob/master/include/vka/object.h#L178 */ vka_object_t pt_object; error = vka_alloc_page_table(&vka, &pt_object); assert(error == 0); /* TODO 4: map the page table */ /* hint 1: seL4_ARCH_PageTable_Map() * The *ARCH* versions of seL4 sys calls are abstractions over the architecture provided by libsel4utils * this one is defined as: * #define seL4_ARCH_PageTable_Map seL4_IA32_PageTable_Map * in: https://github.com/seL4/libsel4utils/blob/master/include/sel4utils/mapping.h#L73 * The signature for the underlying function is: * int seL4_IA32_PageTable_Map(seL4_IA32_PageTable service, seL4_IA32_PageDirectory pd, seL4_Word vaddr, seL4_IA32_VMAttributes attr) * @param service Capability to the page table to map. * @param pd Capability to the VSpace which will contain the mapping. * @param vaddr Virtual address to map the page table into. * @param rights Rights for the mapping. * @param attr VM Attributes for the mapping. * @return 0 on success. * * Note: this function is generated during build. It is generated from the following definition: * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/interfaces/sel4arch.xml#L37 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf * * hint 2: for VM attributes use seL4_ARCH_Default_VMAttributes */ error = seL4_ARCH_PageTable_Map(pt_object.cptr, pd_cap, ipc_buffer_vaddr, seL4_ARCH_Default_VMAttributes); assert(error == 0); /* TODO 5: then map the frame in */ /* hint 1: use seL4_ARCH_Page_Map() as above * hint 2: for the rights, use seL4_AllRights * hint 3: for VM attributes use seL4_ARCH_Default_VMAttributes */ error = seL4_ARCH_Page_Map(ipc_frame_object.cptr, pd_cap, ipc_buffer_vaddr, seL4_AllRights, seL4_ARCH_Default_VMAttributes); assert(error == 0); } /* set the IPC buffer's virtual address in a field of the IPC buffer */ seL4_IPCBuffer *ipcbuf = (seL4_IPCBuffer*)ipc_buffer_vaddr; ipcbuf->userData = ipc_buffer_vaddr; /* TODO 6: create an endpoint */ /* hint: vka_alloc_endpoint() * int vka_alloc_endpoint(vka_t *vka, vka_object_t *result) * @param vka Pointer to vka interface. * @param result Structure for the Endpoint object. This gets initialised. * @return 0 on success * https://github.com/seL4/libsel4vka/blob/master/include/vka/object.h#L94 */ error = vka_alloc_endpoint(&vka, &ep_object); assert(error == 0); /* TODO 7: make a badged copy of it in our cspace. This copy will be used to send * an IPC message to the original cap */ /* hint 1: vka_mint_object() * int vka_mint_object(vka_t *vka, vka_object_t *object, cspacepath_t *result, seL4_CapRights rights, seL4_CapData_t badge) * @param[in] vka The allocator for the cspace. * @param[in] object Target object for cap minting. * @param[out] result Allocated cspacepath. * @param[in] rights The rights for the minted cap. * @param[in] badge The badge for the minted cap. * @return 0 on success * * https://github.com/seL4/libsel4vka/blob/master/include/vka/object_capops.h#L41 * * hint 2: for the rights, use seL4_AllRights * hint 3: for the badge use seL4_CapData_Badge_new() * seL4_CapData_t CONST seL4_CapData_Badge_new(seL4_Uint32 Badge) * @param[in] Badge The badge number to use * @return A CapData structure containing the desired badge info * * seL4_CapData_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#L30 * You can find out more about it in the API manual: http://sel4.systems/Info/Docs/seL4-manual.pdf * * hint 4: for the badge use EP_BADGE */ error = vka_mint_object(&vka, &ep_object, &ep_cap_path, seL4_AllRights, seL4_CapData_Badge_new(EP_BADGE)); assert(error == 0); /* initialise the new TCB */ error = seL4_TCB_Configure(tcb_object.cptr, seL4_CapNull, seL4_MaxPrio, cspace_cap, seL4_NilData, pd_cap, seL4_NilData, ipc_buffer_vaddr, ipc_frame_object.cptr); assert(error == 0); /* give the new thread a name */ name_thread(tcb_object.cptr, "hello-3: thread_2"); /* set start up registers for the new thread */ seL4_UserContext regs = {0}; size_t regs_size = sizeof(seL4_UserContext) / sizeof(seL4_Word); /* set instruction pointer where the thread shoud start running */ sel4utils_set_instruction_pointer(®s, (seL4_Word)thread_2); /* check that stack is aligned correctly */ uintptr_t thread_2_stack_top = (uintptr_t)thread_2_stack + sizeof(thread_2_stack); assert(thread_2_stack_top % (sizeof(seL4_Word) * 2) == 0); /* set stack pointer for the new thread. remember the stack grows down */ sel4utils_set_stack_pointer(®s, thread_2_stack_top); /* set the gs register for thread local storage */ regs.gs = IPCBUF_GDT_SELECTOR; /* actually write the TCB registers. */ error = seL4_TCB_WriteRegisters(tcb_object.cptr, 0, 0, regs_size, ®s); assert(error == 0); /* start the new thread running */ error = seL4_TCB_Resume(tcb_object.cptr); assert(error == 0); /* we are done, say hello */ printf("main: hello world\n"); /* * now send a message to the new thread, and wait for a reply */ seL4_Word msg; seL4_MessageInfo_t tag; /* TODO 8: set the data to send. We send it in the first message register */ /* hint 1: seL4_MessageInfo_new() * seL4_MessageInfo_t CONST seL4_MessageInfo_new(seL4_Uint32 label, seL4_Uint32 capsUnwrapped, seL4_Uint32 extraCaps, seL4_Uint32 length) * @param label The value of the label field * @param capsUnwrapped The value of the capsUnwrapped field * @param extraCaps The value of the extraCaps field * @param length The number of message registers to send * @return The seL4_MessageInfo_t containing the given values. * * seL4_MessageInfo_new() 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 * * hint 2: use 0 for the first 3 fields. * hint 3: send only 1 message register of data * * hint 4: 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 * * hint 5: send MSG_DATA */ tag = seL4_MessageInfo_new(0, 0, 0, 1); seL4_SetMR(0, MSG_DATA); /* TODO 9: send and wait for a reply. */ /* hint: seL4_Call() * seL4_MessageInfo_t seL4_Call(seL4_CPtr dest, seL4_MessageInfo_t msgInfo) * @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). * @return A seL4_MessageInfo_t structure. This is information about the repy message. * https://github.com/seL4/seL4/blob/master/libsel4/arch_include/x86/sel4/arch/syscalls.h#L242 * 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_Call(ep_cap_path.capPtr, tag); /* TODO 10: get the reply message */ /* 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); /* check that we got the expected repy */ assert(seL4_MessageInfo_get_length(tag) == 1); assert(msg == ~MSG_DATA); printf("main: got a reply: %#x\n", msg); return 0; }