Pablo Greco e6a3ae
From 2d0261e575197b60fd17850f1079359375fb82a3 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Danilo de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
Date: Wed, 22 May 2019 20:24:33 +0100
Pablo Greco e6a3ae
Subject: [PATCH 11/12] spice: set device address and device display ID in QXL
Pablo Greco e6a3ae
 interface
Pablo Greco e6a3ae
MIME-Version: 1.0
Pablo Greco e6a3ae
Content-Type: text/plain; charset=UTF-8
Pablo Greco e6a3ae
Content-Transfer-Encoding: 8bit
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Danilo de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
Message-id: <20190522202434.2529-2-ddepaula@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 88166
Pablo Greco e6a3ae
O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] spice: set device address and device display ID in QXL interface
Pablo Greco e6a3ae
Bugzilla: 1712946
Pablo Greco e6a3ae
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
From: Lukáš Hrázký <lhrazky@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Calls the new SPICE QXL interface function spice_qxl_set_device_info to
Pablo Greco e6a3ae
set the hardware address of the graphics device represented by the QXL
Pablo Greco e6a3ae
interface (e.g. a PCI path) and the device display IDs (the IDs of the
Pablo Greco e6a3ae
device's monitors that belong to this QXL interface).
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Also stops using the deprecated spice_qxl_set_max_monitors, the new
Pablo Greco e6a3ae
interface function replaces it.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Signed-off-by: Lukáš Hrázký <lhrazky@redhat.com>
Pablo Greco e6a3ae
Message-Id: <20190215150919.8263-1-lhrazky@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit be812c0ab7d5ab741d0d87387a75a0e8bb6461e7)
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 hw/display/qxl.c           | 14 ++++++++++++-
Pablo Greco e6a3ae
 include/ui/spice-display.h |  4 ++++
Pablo Greco e6a3ae
 ui/spice-core.c            | 51 ++++++++++++++++++++++++++++++++++++++++++++++
Pablo Greco e6a3ae
 ui/spice-display.c         | 11 ++++++++++
Pablo Greco e6a3ae
 4 files changed, 79 insertions(+), 1 deletion(-)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
Pablo Greco e6a3ae
index e36ef32..b373c50 100644
Pablo Greco e6a3ae
--- a/hw/display/qxl.c
Pablo Greco e6a3ae
+++ b/hw/display/qxl.c
Pablo Greco e6a3ae
@@ -275,7 +275,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
Pablo Greco e6a3ae
                     QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
Pablo Greco e6a3ae
                     0));
Pablo Greco e6a3ae
     } else {
Pablo Greco e6a3ae
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
Pablo Greco e6a3ae
+/* >= release 0.12.6, < release 0.14.2 */
Pablo Greco e6a3ae
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
Pablo Greco e6a3ae
         if (qxl->max_outputs) {
Pablo Greco e6a3ae
             spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
@@ -2161,6 +2162,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
Pablo Greco e6a3ae
                    SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
Pablo Greco e6a3ae
         return;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
Pablo Greco e6a3ae
+    char device_address[256] = "";
Pablo Greco e6a3ae
+    if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
Pablo Greco e6a3ae
+        spice_qxl_set_device_info(&qxl->ssd.qxl,
Pablo Greco e6a3ae
+                                  device_address,
Pablo Greco e6a3ae
+                                  0,
Pablo Greco e6a3ae
+                                  qxl->max_outputs);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+#endif
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
     qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
Pablo Greco e6a3ae
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
Pablo Greco e6a3ae
index 87a84a5..53c3612 100644
Pablo Greco e6a3ae
--- a/include/ui/spice-display.h
Pablo Greco e6a3ae
+++ b/include/ui/spice-display.h
Pablo Greco e6a3ae
@@ -179,3 +179,7 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
Pablo Greco e6a3ae
 void qemu_spice_display_start(void);
Pablo Greco e6a3ae
 void qemu_spice_display_stop(void);
Pablo Greco e6a3ae
 int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+bool qemu_spice_fill_device_address(QemuConsole *con,
Pablo Greco e6a3ae
+                                    char *device_address,
Pablo Greco e6a3ae
+                                    size_t size);
Pablo Greco e6a3ae
diff --git a/ui/spice-core.c b/ui/spice-core.c
Pablo Greco e6a3ae
index ae8921a..ebc2f09 100644
Pablo Greco e6a3ae
--- a/ui/spice-core.c
Pablo Greco e6a3ae
+++ b/ui/spice-core.c
Pablo Greco e6a3ae
@@ -35,6 +35,7 @@
Pablo Greco e6a3ae
 #include "qemu/option.h"
Pablo Greco e6a3ae
 #include "migration/misc.h"
Pablo Greco e6a3ae
 #include "hw/hw.h"
Pablo Greco e6a3ae
+#include "hw/pci/pci_bus.h"
Pablo Greco e6a3ae
 #include "ui/spice-display.h"
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 /* core bits */
Pablo Greco e6a3ae
@@ -872,6 +873,56 @@ bool qemu_spice_have_display_interface(QemuConsole *con)
Pablo Greco e6a3ae
     return false;
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+/*
Pablo Greco e6a3ae
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
Pablo Greco e6a3ae
+ * up in the PCI hierarchy.
Pablo Greco e6a3ae
+ *
Pablo Greco e6a3ae
+ * @returns true on success, false when the buffer wasn't large enough
Pablo Greco e6a3ae
+ */
Pablo Greco e6a3ae
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice *pci)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    PCIBus *bus = pci_get_bus(pci);
Pablo Greco e6a3ae
+    /*
Pablo Greco e6a3ae
+     * equivalent to if (!pci_bus_is_root(bus)), but the function is not built
Pablo Greco e6a3ae
+     * with PCI_CONFIG=n, avoid using an #ifdef by checking directly
Pablo Greco e6a3ae
+     */
Pablo Greco e6a3ae
+    if (bus->parent_dev != NULL) {
Pablo Greco e6a3ae
+        append_pci_address(buf, buf_size, bus->parent_dev);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    size_t len = strlen(buf);
Pablo Greco e6a3ae
+    ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
Pablo Greco e6a3ae
+        PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    return written > 0 && written < buf_size - len;
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+bool qemu_spice_fill_device_address(QemuConsole *con,
Pablo Greco e6a3ae
+                                    char *device_address,
Pablo Greco e6a3ae
+                                    size_t size)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con),
Pablo Greco e6a3ae
+                                                       "device",
Pablo Greco e6a3ae
+                                                       &error_abort));
Pablo Greco e6a3ae
+    PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev),
Pablo Greco e6a3ae
+                                                       TYPE_PCI_DEVICE);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    if (pci == NULL) {
Pablo Greco e6a3ae
+        warn_report("Setting device address of a display device to SPICE: "
Pablo Greco e6a3ae
+                    "Not a PCI device.");
Pablo Greco e6a3ae
+        return false;
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    strncpy(device_address, "pci/0000", size);
Pablo Greco e6a3ae
+    if (!append_pci_address(device_address, size, pci)) {
Pablo Greco e6a3ae
+        warn_report("Setting device address of a display device to SPICE: "
Pablo Greco e6a3ae
+            "Too many PCI devices in the chain.");
Pablo Greco e6a3ae
+        return false;
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    return true;
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     if (g_slist_find(spice_consoles, con)) {
Pablo Greco e6a3ae
diff --git a/ui/spice-display.c b/ui/spice-display.c
Pablo Greco e6a3ae
index fe73482..22332f4 100644
Pablo Greco e6a3ae
--- a/ui/spice-display.c
Pablo Greco e6a3ae
+++ b/ui/spice-display.c
Pablo Greco e6a3ae
@@ -1115,6 +1115,17 @@ static void qemu_spice_display_init_one(QemuConsole *con)
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     ssd->qxl.base.sif = &dpy_interface.base;
Pablo Greco e6a3ae
     qemu_spice_add_display_interface(&ssd->qxl, con);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
Pablo Greco e6a3ae
+    char device_address[256] = "";
Pablo Greco e6a3ae
+    if (qemu_spice_fill_device_address(con, device_address, 256)) {
Pablo Greco e6a3ae
+        spice_qxl_set_device_info(&ssd->qxl,
Pablo Greco e6a3ae
+                                  device_address,
Pablo Greco e6a3ae
+                                  qemu_console_get_head(con),
Pablo Greco e6a3ae
+                                  1);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+#endif
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
     qemu_spice_create_host_memslot(ssd);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     register_displaychangelistener(&ssd->dcl);
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae