示例#1
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();
}
示例#2
0
文件: device_irq.c 项目: seL4/refos
int dev_handle_irq(dev_irq_state_t *irqState, uint32_t irq,
                   dev_irq_callback_fn_t callback, void *cookie)
{
    assert(irqState && irqState->magic == DEVICE_IRQ_MAGIC);

    if (irq >= DEVICE_MAX_IRQ) {
        ROS_ERROR("dev_handle_irq IRQ num too high. Try raising DEVICE_MAX_IRQ.");
        assert(!"Try raising DEVICE_MAX_IRQ.");
        return EINVALIDPARAM;
    }

    /* Retrieve the handler, if necessary. */
    if (!irqState->handler[irq].handler) {
        assert(irqState->cfg.getIRQHandlerEndpoint);
        irqState->handler[irq].handler = irqState->cfg.getIRQHandlerEndpoint(
            irqState->cfg.getIRQHandlerEndpointCookie, irq
        );
        if (!irqState->handler[irq].handler) {
            ROS_WARNING("dev_handle_irq : could not get IRQ handler for irq %u.\n", irq);
            return EINVALID;
        }
    }

    /* Determine next round-robin channel to go in. */
    uint32_t nextChannel = irqState->cfg.badgeBaseBit + irqState->nextIRQChannel;
    cvector_add(&irqState->channel[irqState->nextIRQChannel], (cvector_item_t) irq);
    irqState->nextIRQChannel = (irqState->nextIRQChannel + 1) % irqState->cfg.numIRQChannels;

    /* Mint the badged AEP. */
    assert(irqState->cfg.notifyAsyncEP);
    seL4_CPtr irqBadge = srv_mint((1 << nextChannel) | irqState->cfg.badgeMaskBits,
                                  irqState->cfg.notifyAsyncEP);
    if (!irqBadge) {
        ROS_WARNING("dev_handle_irq : could not mint badged aep for irq %u.\n", irq);
        return EINVALID;
    }

    /* Assign AEP to the IRQ handler. */
    int error = seL4_IRQHandler_SetNotification(irqState->handler[irq].handler, irqBadge);
    if (error) {
        ROS_WARNING("dev_handle_irq : could not set notify aep for irq %u.\n", irq);
        csfree_delete(irqBadge);
        return EINVALID;
    }
    seL4_IRQHandler_Ack(irqState->handler[irq].handler);

    /* Set callback function and cookie. */
    irqState->handler[irq].callback = callback;
    irqState->handler[irq].cookie = cookie;

    csfree_delete(irqBadge);
    return ESUCCESS;
}
示例#3
0
/*! @brief Starts a new process. */
refos_err_t
proc_new_proc_handler(void *rpc_userptr , char* rpc_name , char* rpc_params , bool rpc_block ,
                      int32_t rpc_priority , int32_t* rpc_status)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    assert(pcb->magic == REFOS_PCB_MAGIC);
    
    if (!rpc_name) {
        return EINVALIDPARAM;
    }

    /* Kick off an instance of selfloader, which will do the actual process loading work. */
    int error = proc_load_direct("selfloader", rpc_priority, rpc_name, pcb->pid, 0x0);
    if (error != ESUCCESS) {
        ROS_WARNING("failed to run selfloader for new process [%s].", rpc_name);
        return error;
    }

    /* Optionally block parent process until child process has finished. */
    if (rpc_block) {
        /* Save the reply endpoint. */
        proc_save_caller(pcb);
        pcb->parentWaiting = true;
        pcb->rpcClient.skip_reply = true;
        return ESUCCESS;
    }

    /* Immediately resume the parent process. */
    return ESUCCESS;
}
示例#4
0
文件: mem_syscall.c 项目: seL4/refos
refos_err_t
proc_unregister_as_pager_handler(void *rpc_userptr , seL4_CPtr rpc_window)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 1)) {
        return EINVALIDPARAM;
    }

    /* Retrieve and verify the window cap. */
    if (!dispatcher_badge_window(rpc_window)) {
        ROS_WARNING("Invalid window badge.");
        return EINVALIDPARAM;
    }
    struct w_window *win = w_get_window(&procServ.windowList, rpc_window - W_BADGE_BASE);
    if (!win) {
        ROS_ERROR("invalid window ID.");
        return EINVALIDPARAM;
    }
    assert(win->magic == W_MAGIC);

    /* Unset the pager endpoint. If there was anything else mapped to this window, it will be
       unmapped. */
    cspacepath_t emptyPath;
    memset(&emptyPath, 0, sizeof(cspacepath_t));
    w_set_pager_endpoint(win, emptyPath, PID_NULL);
    return ESUCCESS;
}
示例#5
0
int
dispatch_vm_fault(struct procserv_msg *m, void **userptr) {
    if (check_dispatch_fault(m,  userptr) != DISPATCH_SUCCESS) {
        return DISPATCH_PASS;
    }
    (void) userptr;

    /* Find the faulting client's PCB. */
    struct proc_pcb *pcb = pid_get_pcb_from_badge(&procServ.PIDList, m->badge);
    if (!pcb) {
        ROS_WARNING("Unknown client.");
        return DISPATCH_ERROR;
    }
    assert(pcb->magic == REFOS_PCB_MAGIC);
    assert(pcb->pid == m->badge - PID_BADGE_BASE);

    /* Fill out the VM fault message info structure. */
    struct procserv_vmfault_msg vmfault;
    vmfault.pcb = pcb;
    vmfault.pc = seL4_GetMR(seL4_VMFault_IP);
    vmfault.faultAddr = seL4_GetMR(seL4_VMFault_Addr);
    vmfault.instruction = seL4_GetMR(seL4_VMFault_PrefetchFault);
    vmfault.fsr = seL4_GetMR(seL4_VMFault_FSR);
    vmfault.read = sel4utils_is_read_fault();

    /* Handle the VM fault. */
    handle_vm_fault(m, &vmfault);
    return DISPATCH_SUCCESS;
}
示例#6
0
refos_err_t
data_close_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 1)) {
        ROS_ERROR("data_close EINVALIDPARAM: bad dataspace capability.\n");
        return EINVALIDWINDOW;
    }

    /* Verify and find the RAM dataspace. */
    if (!dispatcher_badge_dspace(rpc_dspace_fd)) {
        ROS_ERROR("EINVALIDPARAM: invalid RAM dataspace badge..\n");
        return EINVALIDPARAM;
    }
    struct ram_dspace *dspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dspace_fd);
    if (!dspace) {
        ROS_ERROR("EINVALIDPARAM: dataspace not found.\n");
        return EINVALIDPARAM;
    }

    /* Purge the dataspace from all windows, unmapping every instance of it. */
    w_purge_dspace(&procServ.windowList, dspace);

    /* Purge the dataspace from all notification buffers and ring buffers. */
    pid_iterate(&procServ.PIDList, proc_dspace_delete_callback, (void*) dspace);

    /* Check that this is the last reference to the dataspace. */
    if (dspace->ref != 1) {
        ROS_WARNING("Dataspace reference is %d and not 1.", dspace->ref);
        ROS_WARNING("This is either a book-keeping bug or corruption.");
    }

    /* And finally destroy the RAM dataspace. */
    ram_dspace_unref(&procServ.dspaceList, dspace->ID);
    return ESUCCESS;
}
示例#7
0
文件: mem_syscall.c 项目: seL4/refos
void
mem_syscall_postaction()
{
    if (procServ.unblockClientFaultPID != PID_NULL) {
        struct proc_pcb *clientPCB = pid_get_pcb(&procServ.PIDList, procServ.unblockClientFaultPID);
        if (!clientPCB) {
            ROS_WARNING("mem_syscall_postaction error: No such PID!");
            procServ.unblockClientFaultPID = PID_NULL;
            return;
        }

        /* Resume the blocked faulting thread if there is one. */
        proc_fault_reply(clientPCB);
        procServ.unblockClientFaultPID = PID_NULL;
    }
}
示例#8
0
/*! \brief Reply from another dataserver to provide the process server with content, in reply to a
           notification the process server has sent it which asked for content.
*/
refos_err_t
data_provide_data_from_parambuffer_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd ,
                                           uint32_t rpc_offset , uint32_t rpc_contentSize)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 1)) {
        return EINVALIDPARAM;
    }

    /* Verify and find the RAM dataspace. */
    if (!dispatcher_badge_dspace(rpc_dspace_fd)) {
        ROS_ERROR("EINVALIDPARAM: invalid RAM dataspace badge..\n");
        return EINVALIDPARAM;
    }
    struct ram_dspace *dspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dspace_fd);
    if (!dspace) {
        ROS_ERROR("EINVALIDPARAM: dataspace not found.\n");
        return EINVALIDPARAM;
    }

    char *initContentBuffer = dispatcher_read_param(pcb, rpc_contentSize);
    if (!initContentBuffer) {
        ROS_WARNING("data_provide_data_from_parambuffer_handler: failed to read from paramBuffer.");
        return ENOPARAMBUFFER;
    }

    /* Initialise the page of the ram dataspace with these contents. */
    int error = ram_dspace_write(initContentBuffer, rpc_contentSize, dspace, rpc_offset);
    if (error != ESUCCESS) {
        return error;
    }

    /* Set the bit that says this page has been provided, and notify all waiters blocking on it. */
    rpc_offset = REFOS_PAGE_ALIGN(rpc_offset);
    int npages = (rpc_contentSize / REFOS_PAGE_SIZE) + (rpc_contentSize % REFOS_PAGE_SIZE ? 1 : 0);
    for (vaddr_t i = 0; i < npages; i++) {
        vaddr_t offset = rpc_offset + (i * REFOS_PAGE_SIZE);
        ram_dspace_set_content_init_provided(dspace, offset);
        ram_dspace_content_init_reply_waiters(dspace, offset);
    }

    return ESUCCESS;
}
示例#9
0
文件: mem_syscall.c 项目: seL4/refos
/*! @brief Handles server pager setup syscalls.

    A dataserver calls the process server with this call in order to set up to be the pager of
    one of its client processes for a particular window. The client process is identified by the
    passing of its liveliness cap. All faults for the client's process which happen at that window
    will then be delegated to the dataserver to be handled.
*/
refos_err_t
proc_register_as_pager_handler(void *rpc_userptr , seL4_CPtr rpc_window ,
                               seL4_CPtr rpc_faultNotifyEP , seL4_Word* rpc_winID) 
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 2)) {
        return EINVALIDPARAM;
    }

    /* Retrieve and verify the window cap. */
    if (!dispatcher_badge_window(rpc_window)) {
        ROS_WARNING("Invalid window badge.");
        return EINVALIDPARAM;
    }
    struct w_window *win = w_get_window(&procServ.windowList, rpc_window - W_BADGE_BASE);
    if (!win) {
        ROS_ERROR("invalid window ID.");
        return EINVALIDPARAM;
    }
    assert(win->magic == W_MAGIC);

    /* Copy out the fault endpoint. */
    seL4_CPtr faultNotifyEP = dispatcher_copyout_cptr(rpc_faultNotifyEP);
    if (!faultNotifyEP) {
        dvprintf("could not copy out faultNotifyEP.");
        return EINVALIDPARAM; 
    }

    /* Set the pager endpoint. If there was anything else mapped to this window, it will be
       unmapped. */
    cspacepath_t faultNotifyEPPath;
    vka_cspace_make_path(&procServ.vka, faultNotifyEP, &faultNotifyEPPath);
    w_set_pager_endpoint(win, faultNotifyEPPath, pcb->pid);

    if (rpc_winID) {
        (*rpc_winID) = win->wID;
    }
    return ESUCCESS;
}
示例#10
0
int
timer_read_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , uint32_t rpc_offset ,
                        rpc_buffer_t rpc_buf , uint32_t rpc_count)
{
    if (!rpc_buf.count) {
        return -EINVALIDPARAM;
    }
    if (rpc_buf.count < sizeof(uint64_t)) {
        ROS_WARNING("Buffer not large enough: need %d only got %d.", sizeof(uint64_t),
                    rpc_buf.count);
        return 0;
    }

    assert(rpc_dspace_fd == TIMESERV_DSPACE_BADGE_TIMER);

    /* Reading from the timer dataspace results in a sys_get_time call. */
    uint64_t time = device_timer_get_time(&timeServ.devTimer);
    memcpy(rpc_buf.data, &time, sizeof(uint64_t));
    return sizeof(uint64_t);
}
示例#11
0
文件: serv_common.c 项目: seL4/refos
int
srv_dispatch_notification(srv_common_t *srv, srv_common_notify_handler_callbacks_t callbacks)
{
    assert(srv && srv->magic == SRV_MAGIC);

    /* Allocate a notification structure. */
    struct proc_notification *notification = malloc(sizeof(struct proc_notification)); 
    if (!notification) {
        dprintf("Out of memory while creating notification struct.\n");
        return DISPATCH_ERROR;
    }

    dvprintf("%s recieved fault notification!\n", srv->config.serverName);
    data_mapping_t *nb = &srv->notifyBuffer;
    uint32_t bytesRead = 0;
    int error = DISPATCH_PASS;

    while (1) {
        bytesRead = 0;

        error = refos_share_read (
                (char*) notification, sizeof(struct proc_notification),
                nb->vaddr, nb->size,
                &srv->notifyBufferStart, &bytesRead
        );
        if (!error && bytesRead == 0) {
            /* No more notifications to read. */
            break;
        }

        if (error || bytesRead != sizeof(struct proc_notification)) {
            /* Error during reading notification. */
            dprintf("Could not read information from notification buffer!\n");
            dprintf("    error = %d\n, read = %d", error, bytesRead);
            free(notification);
            return DISPATCH_ERROR;
        }

        /* Paranoid sanity check here. */
        assert(notification->magic == PROCSERV_NOTIFICATION_MAGIC);

        error = DISPATCH_ERROR;
        switch (notification->label) {
        case PROCSERV_NOTIFY_FAULT_DELEGATION:
            if (callbacks.handle_server_fault) {
                error = callbacks.handle_server_fault(notification);
                break;
            }
        case PROCSERV_NOTIFY_CONTENT_INIT:
            if (callbacks.handle_server_content_init) {
                error = callbacks.handle_server_content_init(notification);
                break;
            }
        case PROCSERV_NOTIFY_DEATH:
            if (callbacks.handle_server_death_notification) {
                error = callbacks.handle_server_death_notification(notification);
                break;
            }
        default:
            /* Should never get here. */
            ROS_WARNING("Unknown notification.\n");
            assert(!"Unknown notification.");
            break;
        }
    }

    if (error) {
        ROS_WARNING("Notification handling error on %s: %d\n", srv->config.serverName, error);
    }

    free(notification);
    return error;
}