@@ -22,6 +22,7 @@ static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
static void process_get_pci_info_msg(QIOChannel *ioc, MPQemuMsg *msg,
PCIDevice *pci_dev);
+static void process_proxy_ping_msg(QIOChannel *ioc);
gboolean mpqemu_process_msg(QIOChannel *ioc, GIOCondition cond,
gpointer opaque)
@@ -76,6 +77,9 @@ gboolean mpqemu_process_msg(QIOChannel *ioc, GIOCondition cond,
case GET_PCI_INFO:
process_get_pci_info_msg(ioc, &msg, pci_dev);
break;
+ case PROXY_PING:
+ process_proxy_ping_msg(ioc);
+ break;
default:
error_setg(&local_err, "Unknown command (%d) received from proxy \
in remote process pid=%d", msg.cmd, getpid());
@@ -269,3 +273,13 @@ static void process_get_pci_info_msg(QIOChannel *ioc, MPQemuMsg *msg,
mpqemu_msg_send(&ret, ioc);
}
+
+static void process_proxy_ping_msg(QIOChannel *ioc)
+{
+ MPQemuMsg ret = { 0 };
+
+ ret.cmd = RET_MSG;
+ ret.size = sizeof(ret.data1);
+
+ mpqemu_msg_send(&ret, ioc);
+}
@@ -24,6 +24,8 @@
#include "util/event_notifier-posix.c"
static void probe_pci_info(PCIDevice *dev);
+static void start_hb_timer(PCIProxyDev *dev);
+static void pci_proxy_dev_exit(PCIDevice *pdev);
static void proxy_set_socket(PCIProxyDev *pdev, int fd, Error **errp)
{
@@ -132,6 +134,8 @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
setup_irqfd(dev);
probe_pci_info(PCI_DEVICE(dev));
+
+ start_hb_timer(dev);
}
static int config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
@@ -192,6 +196,7 @@ static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
k->realize = pci_proxy_dev_realize;
k->config_read = pci_proxy_read_config;
k->config_write = pci_proxy_write_config;
+ k->exit = pci_proxy_dev_exit;
device_class_set_props(dc, proxy_properties);
}
@@ -356,3 +361,56 @@ static void probe_pci_info(PCIDevice *dev)
}
}
}
+
+static void hb_msg(PCIProxyDev *dev)
+{
+ DeviceState *ds = DEVICE(dev);
+ MPQemuMsg msg = { 0 };
+ long ret = -EINVAL;
+ Error *local_err = NULL;
+
+ msg.cmd = PROXY_PING;
+ msg.bytestream = 0;
+ msg.size = 0;
+
+ ret = mpqemu_msg_send_reply_co(&msg, dev->com, &local_err);
+ if (local_err) {
+ error_report("Lost contact with remote device %s, error code %ld",
+ ds->id, ret);
+ }
+}
+
+#define NOP_INTERVAL 1000
+
+static void remote_ping(void *opaque)
+{
+ PCIProxyDev *dev = opaque;
+
+ hb_msg(dev);
+
+ timer_mod(dev->hb_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NOP_INTERVAL);
+}
+
+static void start_hb_timer(PCIProxyDev *dev)
+{
+ dev->hb_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+ remote_ping,
+ dev);
+
+ timer_mod(dev->hb_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NOP_INTERVAL);
+}
+
+static void stop_hb_timer(PCIProxyDev *dev)
+{
+ timer_del(dev->hb_timer);
+ timer_free(dev->hb_timer);
+}
+
+static void pci_proxy_dev_exit(PCIDevice *pdev)
+{
+ PCIProxyDev *dev = PCI_PROXY_DEV(pdev);
+
+ stop_hb_timer(dev);
+}
@@ -53,6 +53,8 @@ struct PCIProxyDev {
EventNotifier intr;
EventNotifier resample;
+ QEMUTimer *hb_timer;
+
ProxyMemoryRegion region[PCI_NUM_REGIONS];
};
@@ -44,6 +44,7 @@ typedef enum {
BAR_READ,
SET_IRQFD,
GET_PCI_INFO,
+ PROXY_PING,
MAX = INT_MAX,
} MPQemuCmd;
@@ -264,6 +264,7 @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
}
break;
case GET_PCI_INFO:
+ case PROXY_PING:
if (msg->size) {
return false;
}