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