예제 #1
0
파일: main.c 프로젝트: jm--/seL4Examples
void testEP(env_t env) {

    UNUSED int error;

    cspacepath_t epb1;	//badged endpoint (derived from env->aep)
    seL4_CapData_t badge1 = seL4_CapData_Badge_new (1);
    //mint a badged endpoint with badge value 1
    error = vka_mint_object(&env->vka, &env->aep, &epb1, seL4_CanWrite, badge1);
    assert(error == 0);

    cspacepath_t epb2;	//badged endpoint (derived from env->aep)
    seL4_CapData_t badge2 = seL4_CapData_Badge_new (2);
    //mint a badged endpoint with badge value 2
    error = vka_mint_object(&env->vka, &env->aep, &epb2, seL4_CanWrite, badge2);
    assert(error == 0);

    seL4_Notify(epb1.capPtr, 0);
    seL4_Notify(epb2.capPtr, 0);

    seL4_Word senderBadge;
    seL4_Wait(env->aep.cptr, &senderBadge);
    printf("senderBadge= %d\n", senderBadge); //prints 3; the two badges 1|2
    //=======================================
//    uint32_t label = 0xF;
//    uint32_t capsUnwrapped = 0;
//    uint32_t extraCaps = 0;
//    uint32_t length = 3;
//    seL4_MessageInfo_t tag = seL4_MessageInfo_new(
//    		label, capsUnwrapped, extraCaps, length);
//    seL4_SetMR(0, 0); //0xAFF);
//    seL4_SetMR(1, 0); //0xBFF);
//    seL4_SetMR(2, 0xCFF);
//    seL4_SetMR(3, 0xDFF);
//    seL4_SetMR(4, 0xEFF);
//    seL4_SetMR(5, 0xFFF);
//    seL4_NBSend(epb1.capPtr, tag);
//    tag = seL4_Wait(env->aep.cptr, &senderBadge);
//    printf("senderBadge %d\n", senderBadge);
//
//    // in build/x86/pc99/libsel4/include/sel4/types_gen.h
//    label = seL4_MessageInfo_get_label(tag);
//    length = seL4_MessageInfo_get_length(tag);
//
//    printf("** label=%x \n", label);
//    printf("** length=%x \n", length);
//    printf("** seL4_GetMR0=%x \n", seL4_GetMR(0));
//    printf("** seL4_GetMR1=%x \n", seL4_GetMR(1));
//    printf("** seL4_GetMR2=%x \n", seL4_GetMR(2));
//    printf("** seL4_GetMR3=%x \n", seL4_GetMR(3));
//    printf("** seL4_GetMR4=%x \n", seL4_GetMR(4));
//    printf("** seL4_GetMR4=%x \n", seL4_GetMR(5));

}
예제 #2
0
파일: vmm.c 프로젝트: seL4/seL4_libs
seL4_CPtr vmm_create_async_event_notification_cap(vmm_t *vmm, seL4_Word badge) {

    if (!(badge & BIT(27))) {
        ZF_LOGE("Invalid badge");
        return seL4_CapNull;
    }

    // notification cap
    seL4_CPtr ntfn = vmm->plat_callbacks.get_async_event_notification();

    // path to notification cap slot
    cspacepath_t ntfn_path = {};
    vka_cspace_make_path(&vmm->vka, ntfn, &ntfn_path);

    // allocate slot to store copy
    cspacepath_t minted_ntfn_path = {};
    vka_cspace_alloc_path(&vmm->vka, &minted_ntfn_path);

    // mint the notification cap
    seL4_CapData_t badge_data = seL4_CapData_Badge_new(badge);
    int error = vka_cnode_mint(&minted_ntfn_path, &ntfn_path, seL4_AllRights, badge_data);

    if (error != seL4_NoError) {
        ZF_LOGE("Failed to mint notification cap");
        return seL4_CapNull;
    }

    return minted_ntfn_path.capPtr;
}
예제 #3
0
/* Binds and IRQ to an endpoint */
static seL4_CPtr
irq_bind(irq_t irq, seL4_CPtr notification_cap, int idx, vka_t* vka, simple_t *simple)
{
    seL4_CPtr irq_cap, bnotification_cap;
    cspacepath_t irq_path, notification_path, bnotification_path;
    seL4_CapData_t badge;
    int err;

    /* Create an IRQ cap */
    err = vka_cspace_alloc(vka, &irq_cap);
    if (err != 0) {
        ZF_LOGE("Failed to allocate cslot for irq\n");
        return seL4_CapNull;
    }
    vka_cspace_make_path(vka, irq_cap, &irq_path);
    err = simple_get_IRQ_control(simple, irq, irq_path);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to get cap to irq_number %d\n", irq);
        vka_cspace_free(vka, irq_cap);
        return seL4_CapNull;
    }
    /* Badge the provided endpoint. The bit position of the badge tells us the array
     * index of the associated IRQ data. */
    err = vka_cspace_alloc(vka, &bnotification_cap);
    if (err != 0) {
        ZF_LOGE("Failed to allocate cslot for irq\n");
        vka_cspace_free(vka, irq_cap);
        return seL4_CapNull;
    }
    vka_cspace_make_path(vka, notification_cap, &notification_path);
    vka_cspace_make_path(vka, bnotification_cap, &bnotification_path);
    badge = seL4_CapData_Badge_new(BIT(idx));
    err = vka_cnode_mint(&bnotification_path, &notification_path, seL4_AllRights, badge);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to badge IRQ notification endpoint\n");
        vka_cspace_free(vka, irq_cap);
        vka_cspace_free(vka, bnotification_cap);
        return seL4_CapNull;
    }
    /* bind the IRQ cap to our badged endpoint */
    err = seL4_IRQHandler_SetNotification(irq_cap, bnotification_cap);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to bind IRQ handler to notification\n");
        vka_cspace_free(vka, irq_cap);
        vka_cspace_free(vka, bnotification_cap);
        return seL4_CapNull;
    }
    /* Finally ACK any pending IRQ and enable the IRQ */
    seL4_IRQHandler_Ack(irq_cap);

    DIRQSERVER("Registered IRQ %d with badge 0x%lx\n", irq, BIT(idx));
    return irq_cap;
}
예제 #4
0
int
serial_server_allocate_client_badged_ep(cspacepath_t dest_slot)
{
    cspacepath_t server_ep_cspath;

    seL4_Word new_badge_value = serial_server_badge_value_alloc();
    if (new_badge_value == SERIAL_SERVER_BADGE_VALUE_EMPTY) {
        return -1;
    }

    parent_ep_obj_to_cspath(&server_ep_cspath);
    return vka_cnode_mint(&dest_slot, &server_ep_cspath, seL4_AllRights,
                          seL4_CapData_Badge_new(new_badge_value));
}
예제 #5
0
int
vm_install_service(vm_t* vm, seL4_CPtr service, int index, uint32_t b)
{
    cspacepath_t src, dst;
    seL4_CapData_t badge;
    int err;
    badge = seL4_CapData_Badge_new(b);
    vka_cspace_make_path(vm->vka, service, &src);
    dst.root = vm->cspace.cptr;
    dst.capPtr = index;
    dst.capDepth = VM_CSPACE_SIZE_BITS;
    err =  vka_cnode_mint(&dst, &src, seL4_AllRights, badge);
    return err;
}
예제 #6
0
seL4_CPtr
serial_server_parent_mint_endpoint_to_process(sel4utils_process_t *p)
{
    if (p == NULL) {
        return 0;
    }

    cspacepath_t server_ep_cspath;
    seL4_Word new_badge_value = serial_server_badge_value_alloc();
    if (new_badge_value == SERIAL_SERVER_BADGE_VALUE_EMPTY) {
        return -1;
    }

    parent_ep_obj_to_cspath(&server_ep_cspath);
    return sel4utils_mint_cap_to_process(p, server_ep_cspath,
                                         seL4_AllRights,
                                         seL4_CapData_Badge_new(new_badge_value));
}
예제 #7
0
int
serial_server_parent_vka_mint_endpoint(vka_t *client_vka,
                                   cspacepath_t *badged_server_ep_cspath)
{
    if (client_vka == NULL || badged_server_ep_cspath == NULL) {
        return seL4_InvalidArgument;
    }

    seL4_Word new_badge_value = serial_server_badge_value_alloc();
    if (new_badge_value == SERIAL_SERVER_BADGE_VALUE_EMPTY) {
        return -1;
    }

    /* Mint the Endpoint to a new client. */
    return vka_mint_object_inter_cspace(get_serial_server()->server_vka,
                                        &get_serial_server()->server_ep_obj,
                                        client_vka,
                                        badged_server_ep_cspath,
                                        seL4_AllRights,
                                        seL4_CapData_Badge_new(new_badge_value));
}
예제 #8
0
파일: serv_common.c 프로젝트: seL4/refos
seL4_CPtr
srv_mint(int badge, seL4_CPtr ep)
{
    assert(ep);
    seL4_CPtr mintEP = csalloc();
    if (!mintEP) {
        ROS_ERROR("Could not allocate cslot to mint badge.");
        return 0;
    }
    int error = seL4_CNode_Mint (
        REFOS_CSPACE, mintEP, REFOS_CDEPTH,
        REFOS_CSPACE, ep, REFOS_CDEPTH,
        seL4_NoRead,
        seL4_CapData_Badge_new(badge)
    );
    if (error != seL4_NoError) {
        ROS_ERROR("Could not mint badge.");
        csfree(mintEP);
        return 0;
    }
    return mintEP;
}
예제 #9
0
int
vm_create(const char* name, int priority,
          seL4_CPtr vmm_endpoint, seL4_Word vm_badge,
          vka_t *vka, simple_t *simple, vspace_t *vmm_vspace,
          ps_io_ops_t* io_ops,
          vm_t* vm)
{

    seL4_CapData_t null_cap_data = {{0}};
    seL4_CapData_t cspace_root_data;
    cspacepath_t src, dst;

    int err;

    vm->name = name;
    vm->ndevices = 0;
    vm->onode_head = NULL;
    vm->entry_point = NULL;
    vm->vka = vka;
    vm->simple = simple;
    vm->vmm_vspace = vmm_vspace;
    vm->io_ops = io_ops;

    vm->vchan_num_cons = 0;
    vm->vchan_cons = NULL;

    /* Create a cspace */
    err = vka_alloc_cnode_object(vka, VM_CSPACE_SIZE_BITS, &vm->cspace);
    assert(!err);
    vka_cspace_make_path(vka, vm->cspace.cptr, &src);
    cspace_root_data = seL4_CapData_Guard_new(0, 32 - VM_CSPACE_SIZE_BITS);
    dst.root = vm->cspace.cptr;
    dst.capPtr = VM_CSPACE_SLOT;
    dst.capDepth = VM_CSPACE_SIZE_BITS;
    err = vka_cnode_mint(&dst, &src, seL4_AllRights, cspace_root_data);
    assert(!err);

    /* Create a vspace */
    err = vka_alloc_page_directory(vka, &vm->pd);
    assert(!err);
    err = simple_ASIDPool_assign(simple, vm->pd.cptr);
    assert(err == seL4_NoError);
    err = sel4utils_get_vspace(vmm_vspace, &vm->vm_vspace, &vm->data, vka, vm->pd.cptr,
                               &vm_object_allocation_cb, (void*)vm);
    assert(!err);

    /* Badge the endpoint */
    vka_cspace_make_path(vka, vmm_endpoint, &src);
    err = vka_cspace_alloc_path(vka, &dst);
    assert(!err);
    err = vka_cnode_mint(&dst, &src, seL4_AllRights, seL4_CapData_Badge_new(vm_badge));
    assert(!err);
    /* Copy it to the cspace of the VM for fault IPC */
    src = dst;
    dst.root = vm->cspace.cptr;
    dst.capPtr = VM_FAULT_EP_SLOT;
    dst.capDepth = VM_CSPACE_SIZE_BITS;
    err = vka_cnode_copy(&dst, &src, seL4_AllRights);
    assert(!err);

    /* Create TCB */
    err = vka_alloc_tcb(vka, &vm->tcb);
    assert(!err);
    err = seL4_TCB_Configure(vm_get_tcb(vm), VM_FAULT_EP_SLOT, priority - 1,
                             vm->cspace.cptr, cspace_root_data,
                             vm->pd.cptr, null_cap_data, 0, seL4_CapNull);
    assert(!err);

    /* Create VCPU */
    err = vka_alloc_vcpu(vka, &vm->vcpu);
    assert(!err);
    err = seL4_ARM_VCPU_SetTCB(vm->vcpu.cptr, vm_get_tcb(vm));
    assert(!err);

    /* Initialise fault system */
    vm->fault = fault_init(vm);
    assert(vm->fault);

    return err;
}
예제 #10
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;
}
예제 #11
0
파일: endpoints.c 프로젝트: BwRy/sel4test
static int
test_ep_recycle(env_t env)
{
    seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0);
    struct {
        helper_thread_t thread;
        seL4_CPtr badged_ep;
        seL4_CPtr derived_badged_ep;
        volatile seL4_Word done;
    } senders[NUM_BADGED_CLIENTS];
    helper_thread_t bouncer;
    seL4_CPtr bounce_ep;
    UNUSED int error;
    seL4_CPtr ep;

    /* Create the master endpoint. */
    ep = vka_alloc_endpoint_leaky(&env->vka);

    /* Create N badged endpoints, and derive each of them. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        senders[i].badged_ep = get_free_slot(env);
        assert(senders[i].badged_ep != 0);

        senders[i].derived_badged_ep = get_free_slot(env);
        assert(senders[i].derived_badged_ep != 0);

        seL4_CapData_t cap_data;
        cap_data = seL4_CapData_Badge_new (i + 200);
        error = cnode_mint(env, ep, senders[i].badged_ep, seL4_AllRights, cap_data);
        assert(!error);

        error = cnode_copy(env, senders[i].badged_ep, senders[i].derived_badged_ep, seL4_AllRights);
        assert(!error);

        create_helper_thread(env, &senders[i].thread);
        set_helper_priority(&senders[i].thread, 100);

        senders[i].done = -1;
    }
    /* Create a bounce thread so we can get lower prio threads to run. */
    bounce_ep = vka_alloc_endpoint_leaky(&env->vka);
    create_helper_thread(env, &bouncer);
    set_helper_priority(&bouncer, 0);
    start_helper(env, &bouncer, bouncer_func, bounce_ep, 0, 0, 0);

    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        start_helper(env, &senders[i].thread, (helper_fn_t) call_func,
                     senders[i].derived_badged_ep, i + 100, (seL4_Word) &senders[i].done, 0);
    }

    /* Let the sender threads run. */
    seL4_Call(bounce_ep, tag);
    /* Receive a message from each endpoint and check the badge. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        seL4_Word sender_badge;
        seL4_MessageInfo_ptr_set_length(&tag, 1);
        tag = seL4_Recv(ep, &sender_badge);
        assert(seL4_MessageInfo_get_length(tag) == 1);
        assert(seL4_GetMR(0) == sender_badge - 100);
        seL4_SetMR(0, ~seL4_GetMR(0));
        seL4_Reply(tag);
    }
    /* Let the sender threads run. */
    seL4_Call(bounce_ep, tag);
    /* Check none of the threads have failed yet. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        assert(senders[i].done == 0);
    }
    /* Recycle each endpoint. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        error = cnode_recycle(env, senders[i].badged_ep);
        assert(!error);

        /* Let thread run. */
        seL4_Call(bounce_ep, tag);
        /* Check that only the intended threads have now aborted. */
        for (int j = 0; j < NUM_BADGED_CLIENTS; j++) {
            if (j <= i) {
                assert(senders[j].done == 1);
            } else {
                assert(senders[j].done == 0);
            }
        }
    }
    seL4_Call(bounce_ep, tag);
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        cleanup_helper(env, &senders[i].thread);
    }
    cleanup_helper(env, &bouncer);

    return sel4test_get_result();
}
예제 #12
0
파일: endpoints.c 프로젝트: BwRy/sel4test
/* RECYCLE0001 only tests if a thread gets its IPC canceled. The IPC
 * can succeed even if the cap it used got deleted provided the final
 * capability was not recycled (thus causing an IPC cancel to happen)
 * This means that RECYCLE0001 will pass even if all the derived badges
 * are deleted, since deleting them did NOT delete the final capability
 * or cause a recycle so outstanding IPCs were not canceled */
static int
test_ep_recycle2(env_t env)
{
    seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0);
    struct {
        helper_thread_t thread;
        seL4_CPtr sync_ep;
        seL4_CPtr badged_ep;
        seL4_CPtr derived_badged_ep;
        volatile seL4_Word last_status;
    } helpers[NUM_BADGED_CLIENTS];
    seL4_CPtr ep;
    helper_thread_t reply_thread;
    UNUSED int error;

    /* Create the main EP we are testing */
    ep = vka_alloc_endpoint_leaky(&env->vka);
    /* spawn a thread to keep replying to any messages on main ep */
    create_helper_thread(env, &reply_thread);
    start_helper(env, &reply_thread, bouncer_func, ep, 0, 0, 0);
    /* Spawn helper threads each with their own sync ep and a badged copy of the main ep */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        helpers[i].badged_ep = get_free_slot(env);
        assert(helpers[i].badged_ep != 0);

        helpers[i].derived_badged_ep = get_free_slot(env);
        assert(helpers[i].derived_badged_ep != 0);

        helpers[i].sync_ep = vka_alloc_endpoint_leaky(&env->vka);

        seL4_CapData_t cap_data;
        cap_data = seL4_CapData_Badge_new (i + 200);
        error = cnode_mint(env, ep, helpers[i].badged_ep, seL4_AllRights, cap_data);
        assert(!error);

        error = cnode_copy(env, helpers[i].badged_ep, helpers[i].derived_badged_ep, seL4_AllRights);
        assert(!error);

        helpers[i].last_status = -1;

        create_helper_thread(env, &helpers[i].thread);
        start_helper(env, &helpers[i].thread, (helper_fn_t) ep_test_func,
                     helpers[i].sync_ep, helpers[i].derived_badged_ep, (seL4_Word) &helpers[i].last_status, 0);
    }
    /* Test that every thread and endpoint is working */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        seL4_Call(helpers[i].sync_ep, tag);
    }
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        test_assert(helpers[i].last_status);
    }
    /* Now start recycling endpoints and make sure the correct endpoints disappear */
    for (int i = 0 ; i < NUM_BADGED_CLIENTS; i++) {
        /* Recycle an ep */
        error = cnode_recycle(env, helpers[i].badged_ep);
        assert(!error);
        /* Now run every thread */
        for (int j = 0; j < NUM_BADGED_CLIENTS; j++) {
            seL4_Call(helpers[j].sync_ep, tag);
        }
        for (int j = 0; j < NUM_BADGED_CLIENTS; j++) {
            if (j <= i) {
                test_assert(!helpers[j].last_status);
            } else {
                test_assert(helpers[j].last_status);
            }
        }
    }
    return sel4test_get_result();
}
예제 #13
0
파일: swap.c 프로젝트: ahixon/papaya
/* sends off a frame to the relevant swap file (in or out) 
 *
 * returns True if the root server needs to be notified immediately (ie not 
 * waiting for an async reply */
static int
mmap_queue_schedule (int direction, vaddr_t vaddr, struct frameinfo *frame,
	void* callback, struct pawpaw_event* evt) {

	struct mmap_queue_item* q = mmap_queue_new (frame, callback, evt);
	if (!q) {
		return false;
	}

	//assert (frame);

	if (direction == PAGE_SWAP_IN) {
		assert (frame->file);
		assert (frame->file->file);

		/* FIXME: seriously this needs work */
		struct seen_item *item = regd_caps;
		while (item) {
			if (item->cap == frame->file->file) {
			   break;
			}

		   item = item->next;
		}

		/* register with the filesystem for async notifications if this is our
		 * first time with this file */
		if (!item) {
			seL4_MessageInfo_t reg_msg = seL4_MessageInfo_new (0, 0, 1, 1);

			seL4_CPtr their_cap = cspace_mint_cap (cur_cspace, cur_cspace,
				_mmap_ep, seL4_AllRights,
				seL4_CapData_Badge_new ((seL4_Word)frame));

			assert (their_cap);

			seL4_SetMR (0, VFS_REGISTER_CAP);
			seL4_SetCap (0, their_cap);

			seL4_Call (frame->file->file, reg_msg);

			seL4_Word id = seL4_GetMR (0);
			assert (id > 0);

			item = malloc (sizeof (struct seen_item));
			assert (item);
			item->cap = frame->file->file;
			item->id = id;

			item->next = regd_caps;
			regd_caps = item;
		}

		seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 1, 4);

		seL4_Word id = cid_next ();
		maps_append (id, ((thread_t)evt->args[1])->pid, vaddr);

		/* create a "valid badge" in the badgemap so we can mount the
	 	 * shared buffer */
		seL4_CPtr badge_cap = cspace_mint_cap (
			cur_cspace, cur_cspace, _badgemap_ep, seL4_AllRights,
			seL4_CapData_Badge_new (id));

		assert (badge_cap);
		assert (frame->file);

		msg = seL4_MessageInfo_new (0, 0, 1, 7);
		seL4_SetCap (0, badge_cap);
		seL4_SetMR (0, VFS_READ_OFFSET);
		seL4_SetMR (1, id);
		seL4_SetMR (2, frame->file->load_length);
		seL4_SetMR (3, frame->file->file_offset);
		seL4_SetMR (4, frame->file->load_offset);
		seL4_SetMR (5, item->id);	/* async ID */
		seL4_SetMR (6, (seL4_Word)frame);	/* use frame ptr as "event id" */

		seL4_Send (frame->file->file, msg);

		/* and we go back to waiting on our EP */
	} else if (direction == PAGE_SWAP_OUT) {
		seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 1, 4);

		/* FIXME: needs to be cleaned up on successful swap */
		seL4_Word id = cid_next ();
		maps_append (id, 0, vaddr);

		/* create a "valid badge" in the badgemap so we can mount the shared 
		 * buffer */
		seL4_CPtr badge_cap = cspace_mint_cap (cur_cspace, cur_cspace,
			_badgemap_ep, seL4_AllRights, seL4_CapData_Badge_new (id));

		assert (badge_cap);

		seL4_Word page_id = last_page_id * PAGE_SIZE;
		last_page_id++;

		seL4_Word wrote = 0;
		while (wrote < PAGE_SIZE) {
			msg = seL4_MessageInfo_new (0, 0, 1, 7);
			seL4_SetCap (0, badge_cap);
			seL4_SetMR (0, VFS_WRITE_OFFSET);
			seL4_SetMR (1, id);
			seL4_SetMR (2, PAGE_SIZE - wrote);	/* write whole page out */
			seL4_SetMR (3, page_id + wrote);	/* file offset */
			seL4_SetMR (4, wrote);				/* load into start of share */
			//seL4_SetMR (5, swap_id);			/* async ID - NOT USED */
			seL4_SetMR (6, (seL4_Word)frame);

			/* and write it out */
			seL4_Call (swap_cap, msg);
			seL4_Word wrote_this_call = seL4_GetMR (0);
			assert (wrote_this_call >= 0);
			wrote += wrote_this_call;
		}

		cspace_delete_cap (cur_cspace, badge_cap);

		/* memory map it */
		frame->file = frame_create_mmap (swap_cap, 0, page_id, PAGE_SIZE);
		assert (frame->file);

		mmap_move_done (q);
		return true;
		/* and we go back to waiting on our EP */
	} else if (direction == BUFFER_OPEN_LOAD) {
		seL4_Word share_id = cid_next ();
		maps_append (share_id, 0, vaddr);

		/* create a "valid badge" in the badgemap so we can mount the shared 
		 * buffer */
		seL4_CPtr badge_cap = cspace_mint_cap (cur_cspace, cur_cspace,
			_badgemap_ep, seL4_AllRights, seL4_CapData_Badge_new (share_id));

		assert (badge_cap);

	    seL4_CPtr recv_cap = cspace_alloc_slot (cur_cspace);
	    assert (recv_cap);
	    seL4_SetCapReceivePath (cur_cspace->root_cnode, recv_cap, CSPACE_DEPTH);

	    printf ("OK, asking VFS to open our file '%s'\n", (char*)vaddr);

	    seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 1, 4);
	    seL4_SetCap (0, badge_cap);
	    seL4_SetMR (0, VFS_OPEN);
	    seL4_SetMR (1, share_id);
	    seL4_SetMR (2, FM_READ);
	    seL4_SetMR (3, 0);

	    /* XXX: hack of the century - should really ask VFS async
	     * for cap */
	    seL4_CPtr nfs_fs_cap = service_lookup ("fs_nfs");
	    while (!nfs_fs_cap) {
	    	printf ("failed to find nfs service\n");
	    	nfs_fs_cap = service_lookup ("fs_nfs");
	        //return false;
	    }

	    printf ("calling on %d\n", nfs_fs_cap);
	    seL4_MessageInfo_t reply = seL4_Call (nfs_fs_cap, msg);

	    if (seL4_GetMR (0) != 0) {
	        printf ("%s: failed to open file\n", __FUNCTION__);
	        //return false;
	        mmap_move_done (q);
	        q->frame = NULL;
	    	return true;
	    }

	    assert (seL4_MessageInfo_get_capsUnwrapped (reply) == 0);

	    if (seL4_MessageInfo_get_extraCaps (reply) != 1) {
	        /* could not find file */
	        printf ("%s: did not have cap\n", __FUNCTION__);
	        return false;
	    }

	   	printf ("yum, setting evt arg\n");
	    evt->args[2] = recv_cap;

	    /* then, load in the first page worth of the file into kmem, so we
	     * can read the headers we need */

	    printf ("sweeto, trying to read in data...\n");
	    msg = seL4_MessageInfo_new (0, 0, 1, 3);
	    seL4_SetCap (0, badge_cap);
	    seL4_SetMR (0, VFS_READ);
	    seL4_SetMR (1, share_id);
	    seL4_SetMR (2, PAGE_SIZE);
	    //seL4_SetMR (3, 0);  /* offset */

	    printf ("ASKING TO READ FILE\n");
	    seL4_Call (recv_cap, msg);
	    if (seL4_GetMR (0) <= 0) {
	        printf ("%s: read was empty/failed\n", __FUNCTION__);
	        //return NULL;
	        return false;
	    }

	    printf("read was ok\n");

	    mmap_move_done (q);
	    return true;
	}

	return false;
}
예제 #14
0
seL4_Error
serial_server_parent_spawn_thread(simple_t *parent_simple, vka_t *parent_vka,
                                  vspace_t *parent_vspace,
                                  uint8_t priority)
{
    const size_t shmem_max_size = SERIAL_SERVER_SHMEM_MAX_SIZE;
    seL4_Error error;
    size_t shmem_max_n_pages;
    cspacepath_t parent_cspace_cspath;
    seL4_MessageInfo_t tag;

    if (parent_simple == NULL || parent_vka == NULL || parent_vspace == NULL) {
        return seL4_InvalidArgument;
    }

    memset(get_serial_server(), 0, sizeof(serial_server_context_t));

    /* Get a CPtr to the parent's root cnode. */
    shmem_max_n_pages = BYTES_TO_4K_PAGES(shmem_max_size);
    vka_cspace_make_path(parent_vka, 0, &parent_cspace_cspath);

    get_serial_server()->server_vka = parent_vka;
    get_serial_server()->server_vspace = parent_vspace;
    get_serial_server()->server_cspace = parent_cspace_cspath.root;
    get_serial_server()->server_simple = parent_simple;

    /* Allocate the Endpoint that the server will be listening on. */
    error = vka_alloc_endpoint(parent_vka, &get_serial_server()->server_ep_obj);
    if (error != 0) {
        ZF_LOGE(SERSERVP"spawn_thread: failed to alloc endpoint, err=%d.",
                error);
        return error;
    }

    /* And also allocate a badged copy of the Server's endpoint that the Parent
     * can use to send to the Server. This is used to allow the Server to report
     * back to the Parent on whether or not the Server successfully bound to a
     * platform serial driver.
     *
     * This badged endpoint will be reused by the library as the Parent's badged
     * Endpoint cap, if the Parent itself ever chooses to connect() to the
     * Server later on.
     */

    get_serial_server()->parent_badge_value = serial_server_badge_value_alloc();
    if (get_serial_server()->parent_badge_value == SERIAL_SERVER_BADGE_VALUE_EMPTY) {
        error = seL4_NotEnoughMemory;
        goto out;
    }

    error = vka_mint_object(parent_vka, &get_serial_server()->server_ep_obj,
                            &get_serial_server()->_badged_server_ep_cspath,
                            seL4_AllRights,
                            seL4_CapData_Badge_new(get_serial_server()->parent_badge_value));
    if (error != 0) {
        ZF_LOGE(SERSERVP"spawn_thread: Failed to mint badged Endpoint cap to "
                "server.\n"
                "\tParent cannot confirm Server thread successfully spawned.");
        goto out;
    }

    /* Allocate enough Cnode slots in our CSpace to enable us to receive
     * frame caps from our clients, sufficient to cover "shmem_max_size".
     * The problem here is that we're sort of forced to assume that we get
     * these slots contiguously. If they're not, we have a problem.
     *
     * If a client tries to send us too many frames, we respond with an error,
     * and indicate our shmem_max_size in the SSMSGREG_RESPONSE
     * message register.
     */
    get_serial_server()->frame_cap_recv_cspaths = calloc(shmem_max_n_pages,
                                                   sizeof(cspacepath_t));
    if (get_serial_server()->frame_cap_recv_cspaths == NULL) {
        error = seL4_NotEnoughMemory;
        goto out;
    }

    for (size_t i = 0; i < shmem_max_n_pages; i++) {
        error = vka_cspace_alloc_path(parent_vka,
                                      &get_serial_server()->frame_cap_recv_cspaths[i]);
        if (error != 0) {
            ZF_LOGE(SERSERVP"spawn_thread: Failed to alloc enough cnode slots "
                "to receive shmem frame caps equal to %d bytes.",
                shmem_max_size);
            goto out;
        }
    }

    error = sel4utils_configure_thread(parent_vka, parent_vspace, parent_vspace,
                                       get_serial_server()->server_ep_obj.cptr, priority,
                                       parent_cspace_cspath.root, seL4_NilData,
                                       &get_serial_server()->server_thread);
    if (error != 0) {
        ZF_LOGE(SERSERVP"spawn_thread: sel4utils_configure_thread failed "
                "with %d.", error);
        goto out;
    }

    error = sel4utils_start_thread(&get_serial_server()->server_thread,
                                   &serial_server_main,
                                   NULL, NULL, 1);
    if (error != 0) {
        ZF_LOGE(SERSERVP"spawn_thread: sel4utils_start_thread failed with "
                "%d.", error);
        goto out;
    }

    /* When the Server is spawned, it will reply to tell us whether or not it
     * successfully bound itself to the platform serial device. Block here
     * and wait for that reply.
     */
    seL4_SetMR(SSMSGREG_FUNC, FUNC_SERVER_SPAWN_SYNC_REQ);
    tag = seL4_MessageInfo_new(0, 0, 0, SSMSGREG_SPAWN_SYNC_REQ_END);
    tag = seL4_Call(get_serial_server()->_badged_server_ep_cspath.capPtr, tag);

    /* Did all go well with the server? */
    if (seL4_GetMR(SSMSGREG_FUNC) != FUNC_SERVER_SPAWN_SYNC_ACK) {
        ZF_LOGE(SERSERVP"spawn_thread: Server thread sync message after spawn "
                "was not a SYNC_ACK as expected.");
        error = seL4_InvalidArgument;
        goto out;
    }
    error = seL4_MessageInfo_get_label(tag);
    if (error != 0) {
        ZF_LOGE(SERSERVP"spawn_thread: Server thread failed to bind to the "
                "platform serial device.");
        goto out;
    }

    get_serial_server()->shmem_max_size = shmem_max_size;
    get_serial_server()->shmem_max_n_pages = shmem_max_n_pages;
    return 0;

out:
    if (get_serial_server()->frame_cap_recv_cspaths != NULL) {
        for (size_t i = 0; i < shmem_max_n_pages; i++) {
            /* Since the array was allocated with calloc(), it was zero'd out. So
             * those indexes that didn't get allocated will have NULL in them.
             * Break early on the first index that has NULL.
             */
            if (get_serial_server()->frame_cap_recv_cspaths[i].capPtr == 0) {
                break;
            }
            vka_cspace_free_path(parent_vka, get_serial_server()->frame_cap_recv_cspaths[i]);
        }
    }
    free(get_serial_server()->frame_cap_recv_cspaths);

    if (get_serial_server()->_badged_server_ep_cspath.capPtr != 0) {
        vka_cspace_free_path(parent_vka, get_serial_server()->_badged_server_ep_cspath);
    }
    if (get_serial_server()->parent_badge_value != SERIAL_SERVER_BADGE_VALUE_EMPTY) {
        serial_server_badge_value_free(get_serial_server()->parent_badge_value);
    }
    vka_free_object(parent_vka, &get_serial_server()->server_ep_obj);
    return error;
}
예제 #15
0
파일: main.c 프로젝트: gapry/AOS
static inline seL4_CPtr badge_irq_ep(seL4_CPtr ep, seL4_Word badge) {
    seL4_CPtr badged_cap = cspace_mint_cap(cur_cspace, cur_cspace, ep, seL4_AllRights, seL4_CapData_Badge_new(badge | IRQ_EP_BADGE));
    conditional_panic(!badged_cap, "Failed to allocate badged cap");
    return badged_cap;
}
예제 #16
0
파일: create.c 프로젝트: thumphries/aos
static void _enable_ipc(int err, seL4_Word sos_vaddr, void *cookie) {
    process_create_data *proc = (process_create_data *) cookie;

    if (err) {
        dprintf(6, "process_create_enable_ipc: could not pin IPC buf (%d)\n",
                err);
        _fail(err, proc);
        return;
    }

    // Record the faulted frame address
    proc->pcb->ipc_vaddr = sos_vaddr;

    // Store the process capability for the IPC buffer into our PCB
    dprintf(6, "\t\tCopying process cap...\n");
    err = frame_process_cap(proc->pcb->ipc_vaddr,
                            proc->pcb,
                            &(proc->pcb->ipc_cap));
    // Broken invariant if that failed
    conditional_panic(err, "Failed to obtain IPC process cap");

    // Copy the fault endpoint to the user app to enable IPC
    dprintf(6, "\t\tMinting cap...\n");
    proc->pcb->ep_cap = cspace_mint_cap(proc->pcb->cspace,
                                       cur_cspace,
                                       _sos_ipc_ep_cap,
                                       seL4_AllRights,
                                       seL4_CapData_Badge_new(proc->pcb->pid));

    // Make sure fault endpoint is in the first cspace slot
    if (!(proc->pcb->ep_cap == 1)) {
        _fail(1, proc);
        return;
    }

    // remainder of process creation
    dprintf(5, "\tCreating stack frame...\n");
    err = _create_stack_frame(proc->pcb);
    if (err) {
        _fail(err, proc);
        return;
    }

    dprintf(5, "\tCreating heap...\n");
    err = _create_heap(proc->pcb);
    if (err) {
        _fail(err, proc);
        return;
    }

    dprintf(5, "\tCreating seL4 TCB...\n");
    err = _create_tcb(proc->pcb, SOS_PROCESS_PRIORITY);
    if (err) {
        _fail(err, proc);
        return;
    }

    dprintf(5, "\tLoading ELF...\n");
    err = _load_elf(proc->pcb, proc->pcb->app_name, proc);
    if (err) {
        _fail(err, proc);
        return;
    }

    dprintf(5, "\tCreating children list...\n");
    proc->pcb->children = list_init();
    if (proc->pcb->children == NULL) {
        dprintf(5, "FAILED to create list head\n");
        _fail(SOS_PROCESS_OOM, proc);
        return;
    }
}
예제 #17
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;
}
예제 #18
0
파일: main.c 프로젝트: jm--/seL4Examples
int main()
{
    UNUSED int err;
    setup_system();

    /* enable serial driver */
    platsupport_serial_setup_simple(NULL, &simple, &vka);

    printf("\n\n>>>>>>>>>> multi-irqs <<<<<<<<<< \n\n");
    simple_print(&simple);

    /* TODO: lots of duplicate code here ... */
    chardev_t serial1;
    chardev_t serial2;
    chardev_t keyboard;

    struct ps_io_ops    opsIO;
    sel4platsupport_get_io_port_ops(&opsIO.io_port_ops, &simple);
    ps_chardevice_t *ret;
    ret = ps_cdev_init(PS_SERIAL0, &opsIO, &serial1.dev);
    assert(ret != NULL);
    ret = ps_cdev_init(PS_SERIAL1, &opsIO, &serial2.dev);
    assert(ret != NULL);
    ret = ps_cdev_init(PC99_KEYBOARD_PS2, &opsIO, &keyboard.dev);
    assert(ret != NULL);

    ///////////////////

    /* async endpoint*/
    vka_object_t aep;

    // create endpoint
    err = vka_alloc_async_endpoint(&vka, &aep);
    assert(err == 0);

    seL4_CapData_t badge1 = seL4_CapData_Badge_new (1);
    //mint a badged endpoint with badge value 1
    err = vka_mint_object(&vka, &aep, &serial1.ep, seL4_AllRights, badge1);
    assert(err == 0);

    seL4_CapData_t badge2 = seL4_CapData_Badge_new (2);
    //mint a badged endpoint with badge value 2
    err = vka_mint_object(&vka, &aep, &serial2.ep, seL4_AllRights, badge2);
    assert(err == 0);

    seL4_CapData_t badge3 = seL4_CapData_Badge_new (4);
    //mint a badged endpoint with badge value 4
    err = vka_mint_object(&vka, &aep, &keyboard.ep, seL4_AllRights, badge3);
    assert(err == 0);

    ///////////////////
    set_devEp(&serial1);
    set_devEp(&serial2);
    set_devEp(&keyboard);

    for (;;) {
        seL4_Word sender_badge;
        printf("waiting:\n");
        UNUSED seL4_MessageInfo_t msg = seL4_Wait(aep.cptr, &sender_badge);

        printf("seL4_Wait returned with badge: %d\n", sender_badge);

        if (sender_badge & 1) {
            handle_cdev_event("serial1", &serial1);
        }
        if (sender_badge & 2) {
            handle_cdev_event("serial2", &serial2);
        }
        if (sender_badge & 4) {
            handle_cdev_event("keyboard", &keyboard);
        }
    }

    return 0;
}