diff mbox series

[RESEND,v6,24/36] multi-process: Retrieve PCI info from remote process

Message ID edd1d0741c6be69831dbaa8f9ef2321bce3169e3.1587614626.git.elena.ufimtseva@oracle.com (mailing list archive)
State New, archived
Headers show
Series [RESEND,v6,01/36] memory: alloc RAM from file at offset | expand

Commit Message

Elena Ufimtseva April 23, 2020, 4:13 a.m. UTC
From: Jagannathan Raman <jag.raman@oracle.com>

Retrieve PCI configuration info about the remote device and
configure the Proxy PCI object based on the returned information

Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
 hw/proxy/qemu-proxy.c    | 84 ++++++++++++++++++++++++++++++++++++++++
 include/io/mpqemu-link.h | 10 +++++
 remote/remote-main.c     | 21 ++++++++++
 3 files changed, 115 insertions(+)

Comments

Stefan Hajnoczi May 12, 2020, 4:07 p.m. UTC | #1
On Wed, Apr 22, 2020 at 09:13:59PM -0700, elena.ufimtseva@oracle.com wrote:
> @@ -291,3 +299,79 @@ const MemoryRegionOps proxy_default_ops = {
>          .max_access_size = 1,
>      },
>  };
> +
> +static void probe_pci_info(PCIDevice *dev)
> +{
> +    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
> +    DeviceClass *dc = DEVICE_CLASS(pc);
> +    PCIProxyDev *pdev = PCI_PROXY_DEV(dev);
> +    MPQemuLinkState *mpqemu_link = pdev->mpqemu_link;
> +    MPQemuMsg msg, ret;
> +    uint32_t orig_val, new_val, class;
> +    uint8_t type;
> +    int i, size;
> +    char *name;
> +
> +    memset(&msg, 0, sizeof(MPQemuMsg));
> +    msg.bytestream = 0;
> +    msg.size = 0;
> +    msg.cmd = GET_PCI_INFO;
> +    mpqemu_msg_send(&msg, mpqemu_link->dev);
> +
> +    mpqemu_msg_recv(&ret, mpqemu_link->dev);
> +
> +    pc->vendor_id = ret.data1.ret_pci_info.vendor_id;
> +    pc->device_id = ret.data1.ret_pci_info.device_id;
> +    pc->class_id = ret.data1.ret_pci_info.class_id;
> +    pc->subsystem_id = ret.data1.ret_pci_info.subsystem_id;
> +

Why introduce the GET_PCI_INFO/RET_PCI_INFO messages when the same
information can already be fetched using PCI_CONFIG_READ?

> +    config_op_send(pdev, 11, &class, 1, PCI_CONFIG_READ);

Please use constants like PCI_CLASS_DEVICE instead of magic numbers.

> diff --git a/include/io/mpqemu-link.h b/include/io/mpqemu-link.h
> index 14e4be2bd0..102c736705 100644
> --- a/include/io/mpqemu-link.h
> +++ b/include/io/mpqemu-link.h
> @@ -48,6 +48,8 @@ typedef enum {
>      BAR_WRITE,
>      BAR_READ,
>      SET_IRQFD,
> +    GET_PCI_INFO,
> +    RET_PCI_INFO,

Ah, I see reply messages are being used after all. I suggest dropping
the eventfd wait mechanism and using reply messages instead. Otherwise
you need to duplicate the wait timeout for reply messages. Using
temporary eventfds is more complex and maybe also slower.
diff mbox series

Patch

diff --git a/hw/proxy/qemu-proxy.c b/hw/proxy/qemu-proxy.c
index a78694736b..730e28483e 100644
--- a/hw/proxy/qemu-proxy.c
+++ b/hw/proxy/qemu-proxy.c
@@ -19,6 +19,8 @@ 
 #include "sysemu/kvm.h"
 #include "util/event_notifier-posix.c"
 
+static void probe_pci_info(PCIDevice *dev);
+
 static int config_op_send(PCIProxyDev *dev, uint32_t addr, uint32_t *val, int l,
                           unsigned int op)
 {
@@ -182,8 +184,12 @@  static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
 {
     PCIProxyDev *dev = PCI_PROXY_DEV(device);
     PCIProxyDevClass *k = PCI_PROXY_DEV_GET_CLASS(dev);
+    uint8_t *pci_conf = device->config;
     Error *local_err = NULL;
 
+    pci_conf[PCI_LATENCY_TIMER] = 0xff;
+    pci_conf[PCI_INTERRUPT_PIN] = 0x01;
+
     if (k->realize) {
         k->realize(dev, &local_err);
         if (local_err) {
@@ -196,6 +202,8 @@  static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
     configure_memory_sync(dev->sync, dev->mpqemu_link);
 
     setup_irqfd(dev);
+
+    probe_pci_info(PCI_DEVICE(dev));
 }
 
 static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
@@ -291,3 +299,79 @@  const MemoryRegionOps proxy_default_ops = {
         .max_access_size = 1,
     },
 };
+
+static void probe_pci_info(PCIDevice *dev)
+{
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+    DeviceClass *dc = DEVICE_CLASS(pc);
+    PCIProxyDev *pdev = PCI_PROXY_DEV(dev);
+    MPQemuLinkState *mpqemu_link = pdev->mpqemu_link;
+    MPQemuMsg msg, ret;
+    uint32_t orig_val, new_val, class;
+    uint8_t type;
+    int i, size;
+    char *name;
+
+    memset(&msg, 0, sizeof(MPQemuMsg));
+    msg.bytestream = 0;
+    msg.size = 0;
+    msg.cmd = GET_PCI_INFO;
+    mpqemu_msg_send(&msg, mpqemu_link->dev);
+
+    mpqemu_msg_recv(&ret, mpqemu_link->dev);
+
+    pc->vendor_id = ret.data1.ret_pci_info.vendor_id;
+    pc->device_id = ret.data1.ret_pci_info.device_id;
+    pc->class_id = ret.data1.ret_pci_info.class_id;
+    pc->subsystem_id = ret.data1.ret_pci_info.subsystem_id;
+
+    config_op_send(pdev, 11, &class, 1, PCI_CONFIG_READ);
+    switch (class) {
+    case PCI_BASE_CLASS_BRIDGE:
+        set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+        break;
+    case PCI_BASE_CLASS_STORAGE:
+        set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+        break;
+    case PCI_BASE_CLASS_NETWORK:
+        set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+        break;
+    case PCI_BASE_CLASS_INPUT:
+        set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+        break;
+    case PCI_BASE_CLASS_DISPLAY:
+        set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+        break;
+    case PCI_BASE_CLASS_PROCESSOR:
+        set_bit(DEVICE_CATEGORY_CPU, dc->categories);
+        break;
+    default:
+        set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+        break;
+    }
+
+    for (i = 0; i < 6; i++) {
+        config_op_send(pdev, 0x10 + (4 * i), &orig_val, 4, PCI_CONFIG_READ);
+        new_val = 0xffffffff;
+        config_op_send(pdev, 0x10 + (4 * i), &new_val, 4, PCI_CONFIG_WRITE);
+        config_op_send(pdev, 0x10 + (4 * i), &new_val, 4, PCI_CONFIG_READ);
+        size = (~(new_val & 0xFFFFFFF0)) + 1;
+        config_op_send(pdev, 0x10 + (4 * i), &orig_val, 4, PCI_CONFIG_WRITE);
+        type = (new_val & 0x1) ?
+                   PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;
+
+        if (size) {
+            pdev->region[i].dev = pdev;
+            pdev->region[i].present = true;
+            if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
+                pdev->region[i].memory = true;
+            }
+            name = g_strdup_printf("bar-region-%d", i);
+            memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
+                                  &proxy_default_ops, &pdev->region[i],
+                                  name, size);
+            pci_register_bar(dev, i, type, &pdev->region[i].mr);
+            g_free(name);
+        }
+    }
+}
diff --git a/include/io/mpqemu-link.h b/include/io/mpqemu-link.h
index 14e4be2bd0..102c736705 100644
--- a/include/io/mpqemu-link.h
+++ b/include/io/mpqemu-link.h
@@ -48,6 +48,8 @@  typedef enum {
     BAR_WRITE,
     BAR_READ,
     SET_IRQFD,
+    GET_PCI_INFO,
+    RET_PCI_INFO,
     MAX,
 } mpqemu_cmd_t;
 
@@ -70,6 +72,13 @@  typedef struct {
     bool memory;
 } bar_access_msg_t;
 
+typedef struct {
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint16_t class_id;
+    uint16_t subsystem_id;
+} ret_pci_info_msg_t;
+
 /**
  * MPQemuMsg:
  * @cmd: The remote command
@@ -98,6 +107,7 @@  typedef struct {
         sync_sysmem_msg_t sync_sysmem;
         bar_access_msg_t bar_access;
         set_irqfd_msg_t set_irqfd;
+        ret_pci_info_msg_t ret_pci_info;
     } data1;
 
     int fds[REMOTE_MAX_FDS];
diff --git a/remote/remote-main.c b/remote/remote-main.c
index 7cc1a60c3d..f5a479e9b2 100644
--- a/remote/remote-main.c
+++ b/remote/remote-main.c
@@ -188,6 +188,24 @@  fail:
     PUT_REMOTE_WAIT(wait);
 }
 
+static void process_get_pci_info_msg(MPQemuLinkState *link, MPQemuMsg *msg)
+{
+    PCIDevice *pci_dev = LINK_TO_DEV(link);
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+    MPQemuMsg ret = { 0 };
+
+    ret.cmd = RET_PCI_INFO;
+
+    ret.data1.ret_pci_info.vendor_id = pc->vendor_id;
+    ret.data1.ret_pci_info.device_id = pc->device_id;
+    ret.data1.ret_pci_info.class_id = pc->class_id;
+    ret.data1.ret_pci_info.subsystem_id = pc->subsystem_id;
+
+    ret.size = sizeof(ret.data1);
+
+    mpqemu_msg_send(&ret, link->dev);
+}
+
 static void process_msg(GIOCondition cond, MPQemuLinkState *link,
                         MPQemuChannel *chan)
 {
@@ -246,6 +264,9 @@  static void process_msg(GIOCondition cond, MPQemuLinkState *link,
     case SET_IRQFD:
         process_set_irqfd_msg(LINK_TO_DEV(link), msg);
         break;
+    case GET_PCI_INFO:
+        process_get_pci_info_msg(link, msg);
+        break;
     default:
         error_setg(&err, "Unknown command in %s", print_pid_exec(pid_exec));
         goto finalize_loop;