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; }
/*! @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; }
/*! \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; }
/*! \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; }
/*! \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; }
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; }
/*! @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); }