|
@@ -17,6 +17,8 @@
|
|
#include "monitor/monitor.h"
|
|
#include "monitor/monitor.h"
|
|
#include "migration/blocker.h"
|
|
#include "migration/blocker.h"
|
|
#include "qemu/sockets.h"
|
|
#include "qemu/sockets.h"
|
|
|
|
+#include "hw/remote/mpqemu-link.h"
|
|
|
|
+#include "qemu/error-report.h"
|
|
|
|
|
|
static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
|
|
static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
|
|
{
|
|
{
|
|
@@ -65,6 +67,56 @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
|
|
error_free(dev->migration_blocker);
|
|
error_free(dev->migration_blocker);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
|
|
|
|
+ int len, unsigned int op)
|
|
|
|
+{
|
|
|
|
+ MPQemuMsg msg = { 0 };
|
|
|
|
+ uint64_t ret = -EINVAL;
|
|
|
|
+ Error *local_err = NULL;
|
|
|
|
+
|
|
|
|
+ msg.cmd = op;
|
|
|
|
+ msg.data.pci_conf_data.addr = addr;
|
|
|
|
+ msg.data.pci_conf_data.val = (op == MPQEMU_CMD_PCI_CFGWRITE) ? *val : 0;
|
|
|
|
+ msg.data.pci_conf_data.len = len;
|
|
|
|
+ msg.size = sizeof(PciConfDataMsg);
|
|
|
|
+
|
|
|
|
+ ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
|
|
|
|
+ if (local_err) {
|
|
|
|
+ error_report_err(local_err);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ret == UINT64_MAX) {
|
|
|
|
+ error_report("Failed to perform PCI config %s operation",
|
|
|
|
+ (op == MPQEMU_CMD_PCI_CFGREAD) ? "READ" : "WRITE");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (op == MPQEMU_CMD_PCI_CFGREAD) {
|
|
|
|
+ *val = (uint32_t)ret;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static uint32_t pci_proxy_read_config(PCIDevice *d, uint32_t addr, int len)
|
|
|
|
+{
|
|
|
|
+ uint32_t val;
|
|
|
|
+
|
|
|
|
+ config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGREAD);
|
|
|
|
+
|
|
|
|
+ return val;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val,
|
|
|
|
+ int len)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * Some of the functions access the copy of remote device's PCI config
|
|
|
|
+ * space which is cached in the proxy device. Therefore, maintain
|
|
|
|
+ * it updated.
|
|
|
|
+ */
|
|
|
|
+ pci_default_write_config(d, addr, val, len);
|
|
|
|
+
|
|
|
|
+ config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGWRITE);
|
|
|
|
+}
|
|
|
|
+
|
|
static Property proxy_properties[] = {
|
|
static Property proxy_properties[] = {
|
|
DEFINE_PROP_STRING("fd", PCIProxyDev, fd),
|
|
DEFINE_PROP_STRING("fd", PCIProxyDev, fd),
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
@@ -77,6 +129,9 @@ static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
|
|
|
|
|
|
k->realize = pci_proxy_dev_realize;
|
|
k->realize = pci_proxy_dev_realize;
|
|
k->exit = pci_proxy_dev_exit;
|
|
k->exit = pci_proxy_dev_exit;
|
|
|
|
+ k->config_read = pci_proxy_read_config;
|
|
|
|
+ k->config_write = pci_proxy_write_config;
|
|
|
|
+
|
|
device_class_set_props(dc, proxy_properties);
|
|
device_class_set_props(dc, proxy_properties);
|
|
}
|
|
}
|
|
|
|
|