[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v12 14/19] multi-process: Forward PCI config space acceses to the
From: |
Jagannathan Raman |
Subject: |
[PATCH v12 14/19] multi-process: Forward PCI config space acceses to the remote process |
Date: |
Tue, 1 Dec 2020 15:22:49 -0500 |
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
The Proxy Object sends the PCI config space accesses as messages
to the remote process over the communication channel
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
include/hw/remote/mpqemu-link.h | 9 ++++++
hw/remote/message.c | 62 +++++++++++++++++++++++++++++++++++++++++
hw/remote/mpqemu-link.c | 6 ++++
hw/remote/proxy.c | 51 +++++++++++++++++++++++++++++++++
4 files changed, 128 insertions(+)
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
index cee9468..057c98b 100644
--- a/include/hw/remote/mpqemu-link.h
+++ b/include/hw/remote/mpqemu-link.h
@@ -34,6 +34,8 @@ typedef enum {
MPQEMU_CMD_INIT,
SYNC_SYSMEM,
RET_MSG,
+ PCI_CONFIG_WRITE,
+ PCI_CONFIG_READ,
MPQEMU_CMD_MAX,
} MPQemuCmd;
@@ -43,6 +45,12 @@ typedef struct {
off_t offsets[REMOTE_MAX_FDS];
} SyncSysmemMsg;
+typedef struct {
+ uint32_t addr;
+ uint32_t val;
+ int l;
+} PciConfDataMsg;
+
/**
* MPQemuMsg:
* @cmd: The remote command
@@ -60,6 +68,7 @@ typedef struct {
union {
uint64_t u64;
+ PciConfDataMsg pci_conf_data;
SyncSysmemMsg sync_sysmem;
} data;
diff --git a/hw/remote/message.c b/hw/remote/message.c
index 1f2edc7..52a6f6f 100644
--- a/hw/remote/message.c
+++ b/hw/remote/message.c
@@ -15,6 +15,12 @@
#include "hw/remote/mpqemu-link.h"
#include "qapi/error.h"
#include "sysemu/runstate.h"
+#include "hw/pci/pci.h"
+
+static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
+ MPQemuMsg *msg);
+static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
+ MPQemuMsg *msg);
void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
{
@@ -43,6 +49,12 @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
}
switch (msg.cmd) {
+ case PCI_CONFIG_WRITE:
+ process_config_write(com->ioc, pci_dev, &msg);
+ break;
+ case PCI_CONFIG_READ:
+ process_config_read(com->ioc, pci_dev, &msg);
+ break;
default:
error_setg(&local_err,
"Unknown command (%d) received for device %s (pid=%d)",
@@ -60,3 +72,53 @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
return;
}
+
+static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
+ MPQemuMsg *msg)
+{
+ PciConfDataMsg *conf = (PciConfDataMsg *)&msg->data.pci_conf_data;
+ MPQemuMsg ret = { 0 };
+ Error *local_err = NULL;
+
+ if ((conf->addr + sizeof(conf->val)) > pci_config_size(dev)) {
+ error_report("Bad address received when writing PCI config, pid %d",
+ getpid());
+ ret.data.u64 = UINT64_MAX;
+ } else {
+ pci_default_write_config(dev, conf->addr, conf->val, conf->l);
+ }
+
+ ret.cmd = RET_MSG;
+ ret.size = sizeof(ret.data.u64);
+
+ mpqemu_msg_send(&ret, ioc, &local_err);
+ if (local_err) {
+ error_report("Could not send message to proxy from pid %d",
+ getpid());
+ }
+}
+
+static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
+ MPQemuMsg *msg)
+{
+ PciConfDataMsg *conf = (PciConfDataMsg *)&msg->data.pci_conf_data;
+ MPQemuMsg ret = { 0 };
+ Error *local_err = NULL;
+
+ if ((conf->addr + sizeof(conf->val)) > pci_config_size(dev)) {
+ error_report("Bad address received when reading PCI config, pid %d",
+ getpid());
+ ret.data.u64 = UINT64_MAX;
+ } else {
+ ret.data.u64 = pci_default_read_config(dev, conf->addr, conf->l);
+ }
+
+ ret.cmd = RET_MSG;
+ ret.size = sizeof(ret.data.u64);
+
+ mpqemu_msg_send(&ret, ioc, &local_err);
+ if (local_err) {
+ error_report("Could not send message to proxy from pid %d",
+ getpid());
+ }
+}
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
index 18c8a54..83dbd65 100644
--- a/hw/remote/mpqemu-link.c
+++ b/hw/remote/mpqemu-link.c
@@ -283,6 +283,12 @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
return false;
}
break;
+ case PCI_CONFIG_WRITE:
+ case PCI_CONFIG_READ:
+ if (msg->size != sizeof(PciConfDataMsg)) {
+ return false;
+ }
+ break;
default:
break;
}
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
index 29100bc..c193484 100644
--- a/hw/remote/proxy.c
+++ b/hw/remote/proxy.c
@@ -16,6 +16,8 @@
#include "hw/qdev-properties.h"
#include "monitor/monitor.h"
#include "migration/blocker.h"
+#include "hw/remote/mpqemu-link.h"
+#include "qemu/error-report.h"
static void proxy_set_socket(PCIProxyDev *pdev, int fd, Error **errp)
{
@@ -69,6 +71,52 @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
error_free(dev->migration_blocker);
}
+static int config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
+ int l, 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 == PCI_CONFIG_WRITE) ? *val : 0;
+ msg.data.pci_conf_data.l = l;
+ msg.size = sizeof(PciConfDataMsg);
+
+ ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ if (op == PCI_CONFIG_READ) {
+ *val = (uint32_t)ret;
+ }
+
+ return ret;
+}
+
+static uint32_t pci_proxy_read_config(PCIDevice *d, uint32_t addr, int len)
+{
+ uint32_t val;
+
+ (void)config_op_send(PCI_PROXY_DEV(d), addr, &val, len, PCI_CONFIG_READ);
+
+ return val;
+}
+
+static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val,
+ int l)
+{
+ /*
+ * 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, l);
+
+ (void)config_op_send(PCI_PROXY_DEV(d), addr, &val, l, PCI_CONFIG_WRITE);
+}
+
static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -76,6 +124,9 @@ static void pci_proxy_dev_class_init(ObjectClass *klass,
void *data)
k->realize = pci_proxy_dev_realize;
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);
}
--
1.8.3.1
- [PATCH v12 19/19] multi-process: perform device reset in the remote process, (continued)
[PATCH v12 10/19] multi-process: Associate fd of a PCIDevice with its object, Jagannathan Raman, 2020/12/01
[PATCH v12 14/19] multi-process: Forward PCI config space acceses to the remote process,
Jagannathan Raman <=
[PATCH v12 18/19] multi-process: Retrieve PCI info from remote process, Jagannathan Raman, 2020/12/01
Re: [PATCH v12 00/19] Initial support for multi-process Qemu, Stefan Hajnoczi, 2020/12/03
Re: [PATCH v12 00/19] Initial support for multi-process Qemu, Jagannathan Raman, 2020/12/03