[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v8 12/20] multi-process: Forward PCI config space acceses to the
From: |
Jagannathan Raman |
Subject: |
[PATCH v8 12/20] multi-process: Forward PCI config space acceses to the remote process |
Date: |
Fri, 31 Jul 2020 14:20:19 -0400 |
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
TODO:
Investigate if the local PCI config writes can be dropped.
Without the proxy local PCI config space writes for the device,
the driver in the guest times out on the probing.
We have tried to only refer to the remote for the PCI config writes,
but the driver timeout in the guest forced as to left this
as it is (removing local PCI config only).
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>
---
hw/i386/remote-msg.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/pci/proxy.c | 55 ++++++++++++++++++++++++++++++++++++++++
include/io/mpqemu-link.h | 8 ++++++
io/mpqemu-link.c | 14 +++++++++++
4 files changed, 142 insertions(+)
diff --git a/hw/i386/remote-msg.c b/hw/i386/remote-msg.c
index 4315d2c..c5b8651 100644
--- a/hw/i386/remote-msg.c
+++ b/hw/i386/remote-msg.c
@@ -15,6 +15,12 @@
#include "io/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);
gboolean mpqemu_process_msg(QIOChannel *ioc, GIOCondition cond,
gpointer opaque)
@@ -46,6 +52,12 @@ gboolean mpqemu_process_msg(QIOChannel *ioc, GIOCondition
cond,
}
switch (msg.cmd) {
+ case PCI_CONFIG_WRITE:
+ process_config_write(ioc, pci_dev, &msg);
+ break;
+ case PCI_CONFIG_READ:
+ process_config_read(ioc, pci_dev, &msg);
+ break;
default:
error_setg(&local_err,
"Unknown command (%d) received for device %s (pid=%d)",
@@ -62,3 +74,56 @@ exit:
return TRUE;
}
+
+static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
+ MPQemuMsg *msg)
+{
+ ConfDataMsg *conf = (ConfDataMsg *)msg->data2;
+ 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.data1.u64 = UINT64_MAX;
+ } else {
+ pci_default_write_config(dev, conf->addr, conf->val, conf->l);
+ }
+
+ ret.cmd = RET_MSG;
+ ret.bytestream = 0;
+ ret.size = sizeof(ret.data1);
+
+ 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)
+{
+ ConfDataMsg *conf = (ConfDataMsg *)msg->data2;
+ 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.data1.u64 = UINT64_MAX;
+ } else {
+ ret.data1.u64 = pci_default_read_config(dev, conf->addr, conf->l);
+ }
+
+ ret.cmd = RET_MSG;
+ ret.bytestream = 0;
+ ret.size = sizeof(ret.data1);
+
+ 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/pci/proxy.c b/hw/pci/proxy.c
index 014c1cb..945cc35 100644
--- a/hw/pci/proxy.c
+++ b/hw/pci/proxy.c
@@ -15,6 +15,8 @@
#include "io/channel-util.h"
#include "hw/qdev-properties.h"
#include "monitor/monitor.h"
+#include "io/mpqemu-link.h"
+#include "qemu/error-report.h"
static void proxy_set_socket(PCIProxyDev *pdev, int fd, Error **errp)
{
@@ -51,6 +53,56 @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
qio_channel_close(dev->ioc, NULL);
}
+static int config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
+ int l, unsigned int op)
+{
+ ConfDataMsg conf_data;
+ MPQemuMsg msg = { 0 };
+ long ret = -EINVAL;
+ Error *local_err = NULL;
+
+ conf_data.addr = addr;
+ conf_data.val = (op == PCI_CONFIG_WRITE) ? *val : 0;
+ conf_data.l = l;
+
+ msg.data2 = (uint8_t *)&conf_data;
+
+ msg.size = sizeof(conf_data);
+ msg.cmd = op;
+ msg.bytestream = 1;
+
+ ret = mpqemu_msg_send_and_await_reply(&msg, pdev->ioc, &local_err);
+ if (local_err) {
+ error_report("Failed to exchange PCI_CONFIG message with remote");
+ }
+ 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 the remote device
+ * PCI config space, 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);
@@ -58,6 +110,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);
}
diff --git a/include/io/mpqemu-link.h b/include/io/mpqemu-link.h
index 98383f9..9bd754e 100644
--- a/include/io/mpqemu-link.h
+++ b/include/io/mpqemu-link.h
@@ -34,6 +34,8 @@ typedef enum {
INIT = 0,
SYNC_SYSMEM,
RET_MSG,
+ PCI_CONFIG_WRITE,
+ PCI_CONFIG_READ,
MAX = INT_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;
+} ConfDataMsg;
+
/**
* Maximum size of data2 field in the message to be transmitted.
*/
diff --git a/io/mpqemu-link.c b/io/mpqemu-link.c
index aad1d77..5d04b81 100644
--- a/io/mpqemu-link.c
+++ b/io/mpqemu-link.c
@@ -255,6 +255,20 @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
return false;
}
break;
+ case PCI_CONFIG_WRITE:
+ case PCI_CONFIG_READ:
+ if (msg->size != sizeof(ConfDataMsg)) {
+ return false;
+ }
+ if (!msg->bytestream) {
+ return false;
+ }
+ ConfDataMsg *conf = (ConfDataMsg *)msg->data2;
+
+ if (conf->l != 1 && conf->l != 2 && conf->l != 4) {
+ return false;
+ }
+ break;
default:
break;
}
--
1.8.3.1
- [PATCH v8 04/20] multi-process: setup a machine object for remote device process, (continued)
- [PATCH v8 04/20] multi-process: setup a machine object for remote device process, Jagannathan Raman, 2020/07/31
- [PATCH v8 11/20] multi-process: introduce proxy object, Jagannathan Raman, 2020/07/31
- [PATCH v8 13/20] multi-process: PCI BAR read/write handling for proxy & remote endpoints, Jagannathan Raman, 2020/07/31
- [PATCH v8 14/20] multi-process: Synchronize remote memory, Jagannathan Raman, 2020/07/31
- [PATCH v8 15/20] multi-process: create IOHUB object to handle irq, Jagannathan Raman, 2020/07/31
- [PATCH v8 16/20] multi-process: Retrieve PCI info from remote process, Jagannathan Raman, 2020/07/31
- [PATCH v8 18/20] multi-process: perform device reset in the remote process, Jagannathan Raman, 2020/07/31
- [PATCH v8 20/20] multi-process: add configure and usage information, Jagannathan Raman, 2020/07/31
- [PATCH v8 19/20] multi-process: add the concept description to docs/devel/qemu-multiprocess, Jagannathan Raman, 2020/07/31
- [PATCH v8 06/20] multi-process: define MPQemuMsg format and transmission functions, Jagannathan Raman, 2020/07/31
- [PATCH v8 12/20] multi-process: Forward PCI config space acceses to the remote process,
Jagannathan Raman <=
- [PATCH v8 17/20] multi-process: heartbeat messages to remote, Jagannathan Raman, 2020/07/31
- [PATCH v8 10/20] multi-process: setup memory manager for remote device, Jagannathan Raman, 2020/07/31