diff mbox series

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

Message ID c873c6abec14cb5ddd82e855424013f7b5d7be9d.1586165556.git.elena.ufimtseva@oracle.com (mailing list archive)
State New, archived
Headers show
Series Initial support for multi-process qemu | expand

Commit Message

Elena Ufimtseva April 6, 2020, 9:41 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(+)
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 697fb992a1..d249eba9e8 100644
--- a/remote/remote-main.c
+++ b/remote/remote-main.c
@@ -165,6 +165,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)
 {
@@ -219,6 +237,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");
         goto finalize_loop;