struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop, struct vas_rx_win_attr *rxattr) { struct vas_window *rxwin; struct vas_winctx winctx; struct vas_instance *vinst; trace_vas_rx_win_open(current, vasid, cop, rxattr); if (!rx_win_args_valid(cop, rxattr)) return ERR_PTR(-EINVAL); vinst = find_vas_instance(vasid); if (!vinst) { pr_devel("vasid %d not found!\n", vasid); return ERR_PTR(-EINVAL); } pr_devel("Found instance %d\n", vasid); rxwin = vas_window_alloc(vinst); if (IS_ERR(rxwin)) { pr_devel("Unable to allocate memory for Rx window\n"); return rxwin; } rxwin->tx_win = false; rxwin->nx_win = rxattr->nx_win; rxwin->user_win = rxattr->user_win; rxwin->cop = cop; rxwin->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT; if (rxattr->user_win) rxwin->pid = task_pid_vnr(current); init_winctx_for_rxwin(rxwin, rxattr, &winctx); init_winctx_regs(rxwin, &winctx); set_vinst_win(vinst, rxwin); return rxwin; }
struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop, struct vas_tx_win_attr *attr) { int rc; struct vas_window *txwin; struct vas_window *rxwin; struct vas_winctx winctx; struct vas_instance *vinst; if (!tx_win_args_valid(cop, attr)) return ERR_PTR(-EINVAL); /* * If caller did not specify a vasid but specified the PSWID of a * receive window (applicable only to FTW windows), use the vasid * from that receive window. */ if (vasid == -1 && attr->pswid) decode_pswid(attr->pswid, &vasid, NULL); vinst = find_vas_instance(vasid); if (!vinst) { pr_devel("vasid %d not found!\n", vasid); return ERR_PTR(-EINVAL); } rxwin = get_vinst_rxwin(vinst, cop, attr->pswid); if (IS_ERR(rxwin)) { pr_devel("No RxWin for vasid %d, cop %d\n", vasid, cop); return rxwin; } txwin = vas_window_alloc(vinst); if (IS_ERR(txwin)) { rc = PTR_ERR(txwin); goto put_rxwin; } txwin->cop = cop; txwin->tx_win = 1; txwin->rxwin = rxwin; txwin->nx_win = txwin->rxwin->nx_win; txwin->pid = attr->pid; txwin->user_win = attr->user_win; txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT; init_winctx_for_txwin(txwin, attr, &winctx); init_winctx_regs(txwin, &winctx); /* * If its a kernel send window, map the window address into the * kernel's address space. For user windows, user must issue an * mmap() to map the window into their address space. * * NOTE: If kernel ever resubmits a user CRB after handling a page * fault, we will need to map this into kernel as well. */ if (!txwin->user_win) { txwin->paste_kaddr = map_paste_region(txwin); if (IS_ERR(txwin->paste_kaddr)) { rc = PTR_ERR(txwin->paste_kaddr); goto free_window; } } /* * Now that we have a send window, ensure context switch issues * CP_ABORT for this thread. */ rc = -EINVAL; if (set_thread_uses_vas() < 0) goto free_window; set_vinst_win(vinst, txwin); return txwin; free_window: vas_window_free(txwin); put_rxwin: put_rx_win(rxwin); return ERR_PTR(rc); }