예제 #1
0
/*
 * 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
}
예제 #2
0
// 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;
}
예제 #3
0
파일: main.c 프로젝트: jm--/seL4Examples
/*
 * 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);
}
예제 #4
0
파일: main.c 프로젝트: hypernewbie/refos
/*! @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();
}
예제 #5
0
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;
}
예제 #6
0
파일: main.c 프로젝트: jm--/seL4Examples
//=============================================================================
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);
    }
}
예제 #7
0
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);
}
예제 #8
0
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
    });
예제 #9
0
파일: main.c 프로젝트: gapry/AOS
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");
}
예제 #10
0
파일: main.c 프로젝트: jm--/seL4Examples
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;
}
예제 #11
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;
}
예제 #12
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(&regs, (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(&regs, 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, &regs);
    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;
}
예제 #13
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));
}
예제 #14
0
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(&regs, (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(&regs, 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, &regs);
    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;
}
예제 #15
0
파일: main.c 프로젝트: gapry/sel4-tutorials
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, &regs);
    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;
}
예제 #16
0
파일: main.c 프로젝트: gapry/sel4-tutorials
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;
}
예제 #17
0
파일: main.c 프로젝트: gapry/sel4-tutorials
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(&regs, (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(&regs, 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, &regs);
    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;
}