@@ -17,11 +17,45 @@
static void proxy_set_socket(Object *obj, const char *str, Error **errp)
{
PCIProxyDev *pdev = PCI_PROXY_DEV(obj);
+ DeviceState *dev = DEVICE(obj);
+ MPQemuMsg msg = { 0 };
+ int wait, fd[2];
pdev->socket = atoi(str);
mpqemu_init_channel(pdev->mpqemu_link, &pdev->mpqemu_link->com,
pdev->socket);
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
+ error_setg(errp, "Failed to create socket for device channel");
+ return;
+ }
+
+ wait = GET_REMOTE_WAIT;
+
+ msg.cmd = CONNECT_DEV;
+ msg.bytestream = 1;
+ msg.data2 = (uint8_t *)g_strdup(dev->id);
+ msg.size = sizeof(msg.data2);
+ msg.num_fds = 2;
+ msg.fds[0] = wait;
+ msg.fds[1] = fd[1];
+
+ mpqemu_msg_send(&msg, pdev->mpqemu_link->com);
+
+ if (wait_for_remote(wait)) {
+ error_setg(errp, "Failed to connect device to the remote");
+ close(fd[0]);
+ } else {
+ mpqemu_init_channel(pdev->mpqemu_link, &pdev->mpqemu_link->dev,
+ fd[0]);
+ }
+
+ PUT_REMOTE_WAIT(wait);
+
+ close(fd[1]);
+
+ g_free(msg.data2);
}
static void proxy_init(Object *obj)
@@ -38,6 +38,7 @@
typedef enum {
INIT = 0,
SYNC_SYSMEM,
+ CONNECT_DEV,
MAX,
} mpqemu_cmd_t;
@@ -120,8 +121,12 @@ struct MPQemuLinkState {
GMainLoop *loop;
MPQemuChannel *com;
+ MPQemuChannel *dev;
mpqemu_link_callback callback;
+
+ void *opaque;
+ QemuThread thread;
};
MPQemuLinkState *mpqemu_link_create(void);
@@ -46,6 +46,9 @@ MPQemuLinkState *mpqemu_link_create(void)
MPQemuLinkState *link = MPQEMU_LINK(object_new(TYPE_MPQEMU_LINK));
link->com = NULL;
+ link->dev = NULL;
+
+ link->opaque = NULL;
return link;
}
@@ -34,8 +34,48 @@
#include "block/block.h"
#include "exec/ramlist.h"
+static void process_msg(GIOCondition cond, MPQemuLinkState *link,
+ MPQemuChannel *chan);
+
static MPQemuLinkState *mpqemu_link;
+#define LINK_TO_DEV(link) ((PCIDevice *)link->opaque)
+
+static gpointer dev_thread(gpointer data)
+{
+ MPQemuLinkState *link = data;
+
+ mpqemu_start_coms(link, link->dev);
+
+ return NULL;
+}
+
+static void process_connect_dev_msg(MPQemuMsg *msg)
+{
+ char *devid = (char *)msg->data2;
+ MPQemuLinkState *link = NULL;
+ DeviceState *dev = NULL;
+ int wait = msg->fds[0];
+ int ret = 0;
+
+ dev = qdev_find_recursive(sysbus_get_default(), devid);
+ if (!dev) {
+ ret = 0xff;
+ goto exit;
+ }
+
+ link = mpqemu_link_create();
+ link->opaque = (void *)PCI_DEVICE(dev);
+
+ mpqemu_init_channel(link, &link->dev, msg->fds[1]);
+ mpqemu_link_set_callback(link, process_msg);
+ qemu_thread_create(&link->thread, "dev_thread", dev_thread, link,
+ QEMU_THREAD_JOINABLE);
+
+exit:
+ notify_proxy(wait, ret);
+}
+
static void process_msg(GIOCondition cond, MPQemuLinkState *link,
MPQemuChannel *chan)
{
@@ -56,6 +96,9 @@ static void process_msg(GIOCondition cond, MPQemuLinkState *link,
switch (msg->cmd) {
case INIT:
break;
+ case CONNECT_DEV:
+ process_connect_dev_msg(msg);
+ break;
default:
error_setg(&err, "Unknown command");
goto finalize_loop;