mpqemu-link.c (7019B)
1/* 2 * Communication channel between QEMU and remote device process 3 * 4 * Copyright © 2018, 2021 Oracle and/or its affiliates. 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * 9 */ 10 11#include "qemu/osdep.h" 12#include "qemu-common.h" 13 14#include "qemu/module.h" 15#include "hw/remote/mpqemu-link.h" 16#include "qapi/error.h" 17#include "qemu/iov.h" 18#include "qemu/error-report.h" 19#include "qemu/main-loop.h" 20#include "io/channel.h" 21#include "sysemu/iothread.h" 22#include "trace.h" 23 24/* 25 * Send message over the ioc QIOChannel. 26 * This function is safe to call from: 27 * - main loop in co-routine context. Will block the main loop if not in 28 * co-routine context; 29 * - vCPU thread with no co-routine context and if the channel is not part 30 * of the main loop handling; 31 * - IOThread within co-routine context, outside of co-routine context 32 * will block IOThread; 33 * Returns true if no errors were encountered, false otherwise. 34 */ 35bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp) 36{ 37 bool iolock = qemu_mutex_iothread_locked(); 38 bool iothread = qemu_in_iothread(); 39 struct iovec send[2] = {}; 40 int *fds = NULL; 41 size_t nfds = 0; 42 bool ret = false; 43 44 send[0].iov_base = msg; 45 send[0].iov_len = MPQEMU_MSG_HDR_SIZE; 46 47 send[1].iov_base = (void *)&msg->data; 48 send[1].iov_len = msg->size; 49 50 if (msg->num_fds) { 51 nfds = msg->num_fds; 52 fds = msg->fds; 53 } 54 55 /* 56 * Dont use in IOThread out of co-routine context as 57 * it will block IOThread. 58 */ 59 assert(qemu_in_coroutine() || !iothread); 60 61 /* 62 * Skip unlocking/locking iothread lock when the IOThread is running 63 * in co-routine context. Co-routine context is asserted above 64 * for IOThread case. 65 * Also skip lock handling while in a co-routine in the main context. 66 */ 67 if (iolock && !iothread && !qemu_in_coroutine()) { 68 qemu_mutex_unlock_iothread(); 69 } 70 71 if (!qio_channel_writev_full_all(ioc, send, G_N_ELEMENTS(send), 72 fds, nfds, errp)) { 73 ret = true; 74 } else { 75 trace_mpqemu_send_io_error(msg->cmd, msg->size, nfds); 76 } 77 78 if (iolock && !iothread && !qemu_in_coroutine()) { 79 /* See above comment why skip locking here. */ 80 qemu_mutex_lock_iothread(); 81 } 82 83 return ret; 84} 85 86/* 87 * Read message from the ioc QIOChannel. 88 * This function is safe to call from: 89 * - From main loop in co-routine context. Will block the main loop if not in 90 * co-routine context; 91 * - From vCPU thread with no co-routine context and if the channel is not part 92 * of the main loop handling; 93 * - From IOThread within co-routine context, outside of co-routine context 94 * will block IOThread; 95 */ 96static ssize_t mpqemu_read(QIOChannel *ioc, void *buf, size_t len, int **fds, 97 size_t *nfds, Error **errp) 98{ 99 struct iovec iov = { .iov_base = buf, .iov_len = len }; 100 bool iolock = qemu_mutex_iothread_locked(); 101 bool iothread = qemu_in_iothread(); 102 int ret = -1; 103 104 /* 105 * Dont use in IOThread out of co-routine context as 106 * it will block IOThread. 107 */ 108 assert(qemu_in_coroutine() || !iothread); 109 110 if (iolock && !iothread && !qemu_in_coroutine()) { 111 qemu_mutex_unlock_iothread(); 112 } 113 114 ret = qio_channel_readv_full_all_eof(ioc, &iov, 1, fds, nfds, errp); 115 116 if (iolock && !iothread && !qemu_in_coroutine()) { 117 qemu_mutex_lock_iothread(); 118 } 119 120 return (ret <= 0) ? ret : iov.iov_len; 121} 122 123bool mpqemu_msg_recv(MPQemuMsg *msg, QIOChannel *ioc, Error **errp) 124{ 125 ERRP_GUARD(); 126 g_autofree int *fds = NULL; 127 size_t nfds = 0; 128 ssize_t len; 129 bool ret = false; 130 131 len = mpqemu_read(ioc, msg, MPQEMU_MSG_HDR_SIZE, &fds, &nfds, errp); 132 if (len <= 0) { 133 goto fail; 134 } else if (len != MPQEMU_MSG_HDR_SIZE) { 135 error_setg(errp, "Message header corrupted"); 136 goto fail; 137 } 138 139 if (msg->size > sizeof(msg->data)) { 140 error_setg(errp, "Invalid size for message"); 141 goto fail; 142 } 143 144 if (!msg->size) { 145 goto copy_fds; 146 } 147 148 len = mpqemu_read(ioc, &msg->data, msg->size, NULL, NULL, errp); 149 if (len <= 0) { 150 goto fail; 151 } 152 if (len != msg->size) { 153 error_setg(errp, "Unable to read full message"); 154 goto fail; 155 } 156 157copy_fds: 158 msg->num_fds = nfds; 159 if (nfds > G_N_ELEMENTS(msg->fds)) { 160 error_setg(errp, 161 "Overflow error: received %zu fds, more than max of %d fds", 162 nfds, REMOTE_MAX_FDS); 163 goto fail; 164 } 165 if (nfds) { 166 memcpy(msg->fds, fds, nfds * sizeof(int)); 167 } 168 169 ret = true; 170 171fail: 172 if (*errp) { 173 trace_mpqemu_recv_io_error(msg->cmd, msg->size, nfds); 174 } 175 while (*errp && nfds) { 176 close(fds[nfds - 1]); 177 nfds--; 178 } 179 180 return ret; 181} 182 183/* 184 * Send msg and wait for a reply with command code RET_MSG. 185 * Returns the message received of size u64 or UINT64_MAX 186 * on error. 187 * Called from VCPU thread in non-coroutine context. 188 * Used by the Proxy object to communicate to remote processes. 189 */ 190uint64_t mpqemu_msg_send_and_await_reply(MPQemuMsg *msg, PCIProxyDev *pdev, 191 Error **errp) 192{ 193 MPQemuMsg msg_reply = {0}; 194 uint64_t ret = UINT64_MAX; 195 196 assert(!qemu_in_coroutine()); 197 198 QEMU_LOCK_GUARD(&pdev->io_mutex); 199 if (!mpqemu_msg_send(msg, pdev->ioc, errp)) { 200 return ret; 201 } 202 203 if (!mpqemu_msg_recv(&msg_reply, pdev->ioc, errp)) { 204 return ret; 205 } 206 207 if (!mpqemu_msg_valid(&msg_reply) || msg_reply.cmd != MPQEMU_CMD_RET) { 208 error_setg(errp, "ERROR: Invalid reply received for command %d", 209 msg->cmd); 210 return ret; 211 } 212 213 return msg_reply.data.u64; 214} 215 216bool mpqemu_msg_valid(MPQemuMsg *msg) 217{ 218 if (msg->cmd >= MPQEMU_CMD_MAX || msg->cmd < 0) { 219 return false; 220 } 221 222 /* Verify FDs. */ 223 if (msg->num_fds >= REMOTE_MAX_FDS) { 224 return false; 225 } 226 227 if (msg->num_fds > 0) { 228 for (int i = 0; i < msg->num_fds; i++) { 229 if (fcntl(msg->fds[i], F_GETFL) == -1) { 230 return false; 231 } 232 } 233 } 234 235 /* Verify message specific fields. */ 236 switch (msg->cmd) { 237 case MPQEMU_CMD_SYNC_SYSMEM: 238 if (msg->num_fds == 0 || msg->size != sizeof(SyncSysmemMsg)) { 239 return false; 240 } 241 break; 242 case MPQEMU_CMD_PCI_CFGWRITE: 243 case MPQEMU_CMD_PCI_CFGREAD: 244 if (msg->size != sizeof(PciConfDataMsg)) { 245 return false; 246 } 247 break; 248 case MPQEMU_CMD_BAR_WRITE: 249 case MPQEMU_CMD_BAR_READ: 250 if ((msg->size != sizeof(BarAccessMsg)) || (msg->num_fds != 0)) { 251 return false; 252 } 253 break; 254 case MPQEMU_CMD_SET_IRQFD: 255 if (msg->size || (msg->num_fds != 2)) { 256 return false; 257 } 258 break; 259 default: 260 break; 261 } 262 263 return true; 264}