Esempio n. 1
0
uint32_t
data_get_size_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("bad dspace capability.\n");
        return 0;
    }

    /* 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;
    }

    return dspace->npages * REFOS_PAGE_SIZE;
}
Esempio n. 2
0
/*! @brief Sets the process's parameter buffer.

    Sets the process's parameter buffer to the given RAM dataspace. Only support a RAM dataspace
    which orginated from the process server's own dataspace implementation, does not support
    an external dataspace.
*/
refos_err_t
proc_set_parambuffer_handler(void *rpc_userptr , seL4_CPtr rpc_dataspace , uint32_t rpc_size)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb->magic == REFOS_PCB_MAGIC);
    struct ram_dspace *dataspace;

    /* Special case zero size and NULL parameter buffer - means unset the parameter buffer. */
    if (rpc_size == 0 && rpc_dataspace == 0) {
        proc_set_parambuffer(pcb, NULL);
        return ESUCCESS;
    }

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

    /* Check if the given badge is a RAM dataspace. */
    if (!dispatcher_badge_dspace(rpc_dataspace)) {
        return EINVALIDPARAM;
    }

    /* Retrieve RAM dataspace structure. */
    dataspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dataspace);
    if (!dataspace) {
        dvprintf("No such dataspace!.\n");
        return EINVALID;
    }

    /* Set new parameter buffer. */
    proc_set_parambuffer(pcb, dataspace);
    return ESUCCESS;
}
Esempio n. 3
0
/*! \brief Call from external dataserver asking to be the content initialiser for this dataspace. */
refos_err_t
data_have_data_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , seL4_CPtr rpc_faultNotifyEP ,
                       uint32_t* rpc_dataID)
{
    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) || check_dispatch_caps(m, 0x00000001, 1))) {
        return EINVALIDPARAM;
    }

    if (rpc_dataID) {
        (*rpc_dataID) = 0;
    }

    /* 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;
    }

    /* Special case - no fault notify EP, means unset content-init mode. */
    if (!rpc_faultNotifyEP) {
        cspacepath_t path;
        vka_cspace_make_path(&procServ.vka, 0, &path);
        return ram_dspace_content_init(dspace, path, PID_NULL);
    }

    /* Copyout the content-init fault notify EP. */
    seL4_CPtr faultNotifyEP = dispatcher_copyout_cptr(rpc_faultNotifyEP);
    if (!faultNotifyEP) {
        dvprintf("could not copy out faultNotifyEP.");
        return EINVALIDPARAM; 
    }
    cspacepath_t path;
    vka_cspace_make_path(&procServ.vka, faultNotifyEP, &path);

    /* Initialise the dataspace content with given dataserver EP. */
    int error = ram_dspace_content_init(dspace, path, pcb->pid);
    if (error != ESUCCESS) {
        dispatcher_release_copyout_cptr(faultNotifyEP);
        return error;
    }

    if (rpc_dataID) {
        (*rpc_dataID) = dspace->ID;
    }
    return ESUCCESS;
}
Esempio n. 4
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;
}
Esempio n. 5
0
/*! \brief Maps the given dataspace to the given memory window. */
refos_err_t
data_datamap_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , seL4_CPtr rpc_memoryWindow,
                     uint32_t rpc_offset)
{
    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, 0x00000003, 2)) {
        return EINVALIDPARAM;
    }

    /* Retrieve and validate window badge. */
    if (!dispatcher_badge_window(rpc_memoryWindow)) { 
        return EINVALIDWINDOW;
    }
    struct w_window *window = w_get_window(&procServ.windowList, rpc_memoryWindow - W_BADGE_BASE);
    if (!window) {
        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;
    }

    /* Check that the offset is sane. */
    if (rpc_offset > (dspace->npages * REFOS_PAGE_SIZE)) {
        return EINVALIDPARAM;
    }

    /* Associate the dataspace with the window. This will release whatever the window was associated
       with beforehand. */
    w_set_anon_dspace(window, dspace, rpc_offset);
    return ESUCCESS;
}
Esempio n. 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;
}
Esempio n. 7
0
/*! @brief Handles server notification buffer setup syscalls.

    A server calls this on the process server in order to set up its notification buffer, used
    for notification messages such as content-initialisation and pager fault-delegation.
 */
refos_err_t
proc_notification_buffer_handler(void *rpc_userptr , seL4_CPtr rpc_dataspace)
{
    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 & find the dataspace. */
    if (!dispatcher_badge_dspace(rpc_dataspace)) {
        return EINVALIDPARAM;
    }
    struct ram_dspace *dspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dataspace);
    if (!dspace) {
        return EINVALIDPARAM;
    }
 
    /* Set the notification buffer. */
    return proc_set_notificationbuffer(pcb, dspace);
}