qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 00/29] Misc HW patches for 2024-12-31
@ 2024-12-31 20:21 Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 01/29] hw/pci-host/gpex: Allow more than 4 legacy IRQs Philippe Mathieu-Daudé
                   ` (29 more replies)
  0 siblings, 30 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé

The following changes since commit 7c89e226f878539b633dde3fd9c9f061c34094e3:

  Merge tag 'pull-request-2024-12-29' of https://gitlab.com/huth/qemu into staging (2024-12-29 03:25:41 -0500)

are available in the Git repository at:

  https://github.com/philmd/qemu.git tags/hw-misc-20241231

for you to fetch changes up to c6f59e3b68abefc1f6942d4b4e3063d96d903b27:

  hw/display/qxl: Do not use C99 // comments (2024-12-31 21:21:34 +0100)

Ignored checkpatch errors:

 WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
 (I asked Gustavo to fix that in a following patch)

----------------------------------------------------------------
Misc HW patches queue

- Allow more than 4 legacy IRQs on Generic PCI Express Bridge (Alexander)
- Add MMIO-based Inter-VM shared memory device 'ivshmem-flat' (Gustavo)
- Use UHCI register definitions (Guenter)
- Propagate CPU endianness to microblaze_load_kernel (Philippe)
- Mark x86/TriCore devices as little-endian, OpenRISC/SPARC as big (Philippe)
- Don't set callback_opaque NULL in fw_cfg_modify_bytes_read (Shameer)
- Simplify non-KVM checks on AMD IOMMU XTSup feature (Philippe)
- Trivial cleanups on xilinx_ethlite, vmcoreinfo, qxl (Philippe, Hyman)
- Move USB-HCD-XHCI msi/msix properties from NEC to superclass (Phil)
- Redesign of main thread event handling due to macOS Cocoa (Phil)
- Introduce ParavirtualizedGraphics.Framework support 'apple-gfx' (Phil)
- Pad short Ethernet frames on macOS vmnet (William)

----------------------------------------------------------------

Alexander Graf (1):
  hw/pci-host/gpex: Allow more than 4 legacy IRQs

Guenter Roeck (2):
  hw/usb/uhci: checkpatch cleanup
  hw/usb/uhci: Introduce and use register defines

Gustavo Romero (2):
  hw/misc/ivshmem-flat: Add ivshmem-flat device
  hw/misc/ivshmem: Rename ivshmem to ivshmem-pci

Hyman Huang (1):
  hw/display/qxl: Do not use C99 // comments

Phil Dennis-Jordan (8):
  hw/block/virtio-blk: Replaces request free function with g_free
  hw/usb/hcd-xhci-pci: Move msi/msix properties from NEC to superclass
  hw/usb/hcd-xhci: Unimplemented/guest error logging for port MMIO
  ui & main loop: Redesign of system-specific main thread event handling
  hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework
    support
  hw/display/apple-gfx: Adds PCI implementation
  hw/display/apple-gfx: Adds configurable mode list
  MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF

Philippe Mathieu-Daudé (13):
  hw/microblaze: Propagate CPU endianness to microblaze_load_kernel()
  hw/i386: Mark devices as little-endian
  hw/tricore: Mark devices as little-endian
  hw/openrisc: Mark devices as big-endian
  hw/sparc: Mark devices as big-endian
  hw/net/xilinx_ethlite: Convert some debug logs to trace events
  hw/net/xilinx_ethlite: Remove unuseful debug logs
  hw/net/xilinx_ethlite: Update QOM style
  hw/net/xilinx_ethlite: Correct maximum RX buffer size
  hw/net/xilinx_ethlite: Rename rxbuf -> port_index
  hw/misc/vmcoreinfo: Declare QOM type using DEFINE_TYPES macro
  hw/misc/vmcoreinfo: Rename opaque pointer as 'opaque'
  hw/i386/amd_iommu: Simplify non-KVM checks on XTSup feature

Shameer Kolothum (1):
  fw_cfg: Don't set callback_opaque NULL in fw_cfg_modify_bytes_read()

William Hooper (1):
  net/vmnet: Pad short Ethernet frames

 MAINTAINERS                              |   7 +
 docs/system/device-emulation.rst         |   1 +
 docs/system/devices/ivshmem-flat.rst     |  33 +
 meson.build                              |   4 +
 hw/display/apple-gfx.h                   |  74 ++
 hw/microblaze/boot.h                     |   4 +-
 include/hw/misc/ivshmem-flat.h           |  85 +++
 include/hw/pci-host/gpex.h               |   7 +-
 include/hw/usb/uhci-regs.h               |  11 +
 include/qemu-main.h                      |  14 +-
 hw/arm/sbsa-ref.c                        |   2 +-
 hw/arm/virt.c                            |   2 +-
 hw/block/virtio-blk.c                    |  43 +-
 hw/display/qxl.c                         |   2 +-
 hw/i386/amd_iommu.c                      |  11 +-
 hw/i386/kvm/apic.c                       |   2 +-
 hw/i386/microvm.c                        |   2 +-
 hw/i386/pc.c                             |   4 +-
 hw/i386/vapic.c                          |   2 +-
 hw/i386/xen/xen_apic.c                   |   2 +-
 hw/i386/xen/xen_platform.c               |   2 +-
 hw/loongarch/virt.c                      |  12 +-
 hw/microblaze/boot.c                     |   8 +-
 hw/microblaze/petalogix_ml605_mmu.c      |   2 +-
 hw/microblaze/petalogix_s3adsp1800_mmu.c |   2 +-
 hw/microblaze/xlnx-zynqmp-pmu.c          |   2 +-
 hw/mips/loongson3_virt.c                 |   2 +-
 hw/misc/ivshmem-flat.c                   | 459 ++++++++++++
 hw/misc/{ivshmem.c => ivshmem-pci.c}     |   0
 hw/misc/vmcoreinfo.c                     |  29 +-
 hw/net/xilinx_ethlite.c                  |  78 +-
 hw/nvram/fw_cfg.c                        |   1 -
 hw/openrisc/openrisc_sim.c               |   2 +-
 hw/openrisc/virt.c                       |  14 +-
 hw/pci-host/gpex.c                       |  43 +-
 hw/riscv/virt.c                          |  12 +-
 hw/sparc/sun4m_iommu.c                   |   2 +-
 hw/sparc64/sun4u.c                       |   2 +-
 hw/tricore/tricore_testdevice.c          |   2 +-
 hw/usb/hcd-uhci.c                        | 122 ++--
 hw/usb/hcd-xhci-nec.c                    |   2 -
 hw/usb/hcd-xhci-pci.c                    |   6 +
 hw/usb/hcd-xhci.c                        |  25 +-
 hw/xen/xen-pvh-common.c                  |   2 +-
 hw/xtensa/virt.c                         |   2 +-
 system/main.c                            |  38 +-
 tests/qtest/fuzz/fuzz.c                  |   1 +
 ui/gtk.c                                 |   4 +
 ui/sdl2.c                                |   4 +
 hw/display/Kconfig                       |  13 +
 hw/display/apple-gfx-mmio.m              | 285 ++++++++
 hw/display/apple-gfx-pci.m               | 157 ++++
 hw/display/apple-gfx.m                   | 879 +++++++++++++++++++++++
 hw/display/meson.build                   |   7 +
 hw/display/trace-events                  |  30 +
 hw/misc/Kconfig                          |   5 +
 hw/misc/meson.build                      |   4 +-
 hw/misc/trace-events                     |  16 +
 hw/net/trace-events                      |   4 +
 net/vmnet-common.m                       |  23 +-
 ui/cocoa.m                               |  54 +-
 61 files changed, 2413 insertions(+), 256 deletions(-)
 create mode 100644 docs/system/devices/ivshmem-flat.rst
 create mode 100644 hw/display/apple-gfx.h
 create mode 100644 include/hw/misc/ivshmem-flat.h
 create mode 100644 hw/misc/ivshmem-flat.c
 rename hw/misc/{ivshmem.c => ivshmem-pci.c} (100%)
 create mode 100644 hw/display/apple-gfx-mmio.m
 create mode 100644 hw/display/apple-gfx-pci.m
 create mode 100644 hw/display/apple-gfx.m

-- 
2.47.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PULL 01/29] hw/pci-host/gpex: Allow more than 4 legacy IRQs
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 02/29] hw/misc/ivshmem-flat: Add ivshmem-flat device Philippe Mathieu-Daudé
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, Phil Dennis-Jordan, Akihiko Odaki,
	Philippe Mathieu-Daudé

From: Alexander Graf <graf@amazon.com>

Some boards such as vmapple don't do real legacy PCI IRQ swizzling.
Instead, they just keep allocating more board IRQ lines for each new
legacy IRQ. Let's support that mode by giving instantiators a new
"nr_irqs" property they can use to support more than 4 legacy IRQ lines.
In this mode, GPEX will export more IRQ lines, one for each device.

Signed-off-by: Alexander Graf <graf@amazon.com>
Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Tested-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241223221645.29911-9-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/pci-host/gpex.h |  7 +++----
 hw/arm/sbsa-ref.c          |  2 +-
 hw/arm/virt.c              |  2 +-
 hw/i386/microvm.c          |  2 +-
 hw/loongarch/virt.c        | 12 +++++------
 hw/mips/loongson3_virt.c   |  2 +-
 hw/openrisc/virt.c         | 12 +++++------
 hw/pci-host/gpex.c         | 43 ++++++++++++++++++++++++++++++--------
 hw/riscv/virt.c            | 12 +++++------
 hw/xen/xen-pvh-common.c    |  2 +-
 hw/xtensa/virt.c           |  2 +-
 11 files changed, 61 insertions(+), 37 deletions(-)

diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
index dce883573ba..84471533af0 100644
--- a/include/hw/pci-host/gpex.h
+++ b/include/hw/pci-host/gpex.h
@@ -32,8 +32,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(GPEXHost, GPEX_HOST)
 #define TYPE_GPEX_ROOT_DEVICE "gpex-root"
 OBJECT_DECLARE_SIMPLE_TYPE(GPEXRootState, GPEX_ROOT_DEVICE)
 
-#define GPEX_NUM_IRQS 4
-
 struct GPEXRootState {
     /*< private >*/
     PCIDevice parent_obj;
@@ -49,6 +47,7 @@ struct GPEXConfig {
     PCIBus      *bus;
 };
 
+typedef struct GPEXIrq GPEXIrq;
 struct GPEXHost {
     /*< private >*/
     PCIExpressHost parent_obj;
@@ -60,8 +59,8 @@ struct GPEXHost {
     MemoryRegion io_mmio;
     MemoryRegion io_ioport_window;
     MemoryRegion io_mmio_window;
-    qemu_irq irq[GPEX_NUM_IRQS];
-    int irq_num[GPEX_NUM_IRQS];
+    GPEXIrq *irq;
+    uint8_t num_irqs;
 
     bool allow_unmapped_accesses;
 
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 581655d7716..6183111f2de 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -673,7 +673,7 @@ static void create_pcie(SBSAMachineState *sms)
     /* Map IO port space */
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
                            qdev_get_gpio_in(sms->gic, irq + i));
         gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f9b33808157..99e0a68b6c5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1547,7 +1547,7 @@ static void create_pcie(VirtMachineState *vms)
     /* Map IO port space */
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
                            qdev_get_gpio_in(vms->gic, irq + i));
         gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index c3d7fe3c428..a8d354aabe5 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -139,7 +139,7 @@ static void create_gpex(MicrovmMachineState *mms)
                                     mms->gpex.mmio64.base, mmio64_alias);
     }
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
                            x86ms->gsi[mms->gpex.irq + i]);
     }
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 99594a13a0c..60bd4dc9d35 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -452,7 +452,7 @@ static void fdt_add_pcie_irq_map_node(const LoongArchVirtMachineState *lvms,
 {
     int pin, dev;
     uint32_t irq_map_stride = 0;
-    uint32_t full_irq_map[GPEX_NUM_IRQS *GPEX_NUM_IRQS * 10] = {};
+    uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS * 10] = {};
     uint32_t *irq_map = full_irq_map;
     const MachineState *ms = MACHINE(lvms);
 
@@ -465,11 +465,11 @@ static void fdt_add_pcie_irq_map_node(const LoongArchVirtMachineState *lvms,
      * to wrap to any number of devices.
      */
 
-    for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
+    for (dev = 0; dev < PCI_NUM_PINS; dev++) {
         int devfn = dev * 0x8;
 
-        for (pin = 0; pin  < GPEX_NUM_IRQS; pin++) {
-            int irq_nr = 16 + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
+        for (pin = 0; pin < PCI_NUM_PINS; pin++) {
+            int irq_nr = 16 + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
             int i = 0;
 
             /* Fill PCI address cells */
@@ -493,7 +493,7 @@ static void fdt_add_pcie_irq_map_node(const LoongArchVirtMachineState *lvms,
 
 
     qemu_fdt_setprop(ms->fdt, nodename, "interrupt-map", full_irq_map,
-                     GPEX_NUM_IRQS * GPEX_NUM_IRQS *
+                     PCI_NUM_PINS * PCI_NUM_PINS *
                      irq_map_stride * sizeof(uint32_t));
     qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupt-map-mask",
                      0x1800, 0, 0, 0x7);
@@ -805,7 +805,7 @@ static void virt_devices_init(DeviceState *pch_pic,
     memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE,
                                 pio_alias);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         sysbus_connect_irq(d, i,
                            qdev_get_gpio_in(pch_pic, 16 + i));
         gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index f12f8c3d3cc..f3cc7a8376f 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -458,7 +458,7 @@ static inline void loongson3_virt_devices_init(MachineState *machine,
                                 virt_memmap[VIRT_PCIE_PIO].base, s->pio_alias);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i);
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
         gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i);
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index 0d83e33f9ea..22ae057992e 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -318,7 +318,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
 {
     int pin, dev;
     uint32_t irq_map_stride = 0;
-    uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {};
+    uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS * 6] = {};
     uint32_t *irq_map = full_irq_map;
 
     /*
@@ -330,11 +330,11 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
      * possible slot) seeing the interrupt-map-mask will allow the table
      * to wrap to any number of devices.
      */
-    for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
+    for (dev = 0; dev < PCI_NUM_PINS; dev++) {
         int devfn = dev << 3;
 
-        for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
-            int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
+        for (pin = 0; pin < PCI_NUM_PINS; pin++) {
+            int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
             int i = 0;
 
             /* Fill PCI address cells */
@@ -357,7 +357,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
     }
 
     qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map,
-                     GPEX_NUM_IRQS * GPEX_NUM_IRQS *
+                     PCI_NUM_PINS * PCI_NUM_PINS *
                      irq_map_stride * sizeof(uint32_t));
 
     qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
@@ -409,7 +409,7 @@ static void openrisc_virt_pcie_init(OR1KVirtState *state,
     memory_region_add_subregion(get_system_memory(), pio_base, alias);
 
     /* Connect IRQ lines. */
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         pcie_irq = get_per_cpu_irq(cpus, num_cpus, irq_base + i);
 
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pcie_irq);
diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
index c6aa8e87a22..9fcedd7fc58 100644
--- a/hw/pci-host/gpex.c
+++ b/hw/pci-host/gpex.c
@@ -32,6 +32,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/irq.h"
+#include "hw/pci/pci_bus.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -41,20 +42,25 @@
  * GPEX host
  */
 
+struct GPEXIrq {
+    qemu_irq irq;
+    int irq_num;
+};
+
 static void gpex_set_irq(void *opaque, int irq_num, int level)
 {
     GPEXHost *s = opaque;
 
-    qemu_set_irq(s->irq[irq_num], level);
+    qemu_set_irq(s->irq[irq_num].irq, level);
 }
 
 int gpex_set_irq_num(GPEXHost *s, int index, int gsi)
 {
-    if (index >= GPEX_NUM_IRQS) {
+    if (index >= s->num_irqs) {
         return -EINVAL;
     }
 
-    s->irq_num[index] = gsi;
+    s->irq[index].irq_num = gsi;
     return 0;
 }
 
@@ -62,7 +68,7 @@ static PCIINTxRoute gpex_route_intx_pin_to_irq(void *opaque, int pin)
 {
     PCIINTxRoute route;
     GPEXHost *s = opaque;
-    int gsi = s->irq_num[pin];
+    int gsi = s->irq[pin].irq_num;
 
     route.irq = gsi;
     if (gsi < 0) {
@@ -74,6 +80,13 @@ static PCIINTxRoute gpex_route_intx_pin_to_irq(void *opaque, int pin)
     return route;
 }
 
+static int gpex_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
+{
+    PCIBus *bus = pci_device_root_bus(pci_dev);
+
+    return (PCI_SLOT(pci_dev->devfn) + pin) % bus->nirq;
+}
+
 static void gpex_host_realize(DeviceState *dev, Error **errp)
 {
     PCIHostState *pci = PCI_HOST_BRIDGE(dev);
@@ -82,6 +95,8 @@ static void gpex_host_realize(DeviceState *dev, Error **errp)
     PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev);
     int i;
 
+    s->irq = g_malloc0_n(s->num_irqs, sizeof(*s->irq));
+
     pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX);
     sysbus_init_mmio(sbd, &pex->mmio);
 
@@ -128,19 +143,27 @@ static void gpex_host_realize(DeviceState *dev, Error **errp)
         sysbus_init_mmio(sbd, &s->io_ioport);
     }
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
-        sysbus_init_irq(sbd, &s->irq[i]);
-        s->irq_num[i] = -1;
+    for (i = 0; i < s->num_irqs; i++) {
+        sysbus_init_irq(sbd, &s->irq[i].irq);
+        s->irq[i].irq_num = -1;
     }
 
     pci->bus = pci_register_root_bus(dev, "pcie.0", gpex_set_irq,
-                                     pci_swizzle_map_irq_fn, s, &s->io_mmio,
-                                     &s->io_ioport, 0, 4, TYPE_PCIE_BUS);
+                                     gpex_swizzle_map_irq_fn,
+                                     s, &s->io_mmio, &s->io_ioport, 0,
+                                     s->num_irqs, TYPE_PCIE_BUS);
 
     pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq);
     qdev_realize(DEVICE(&s->gpex_root), BUS(pci->bus), &error_fatal);
 }
 
+static void gpex_host_unrealize(DeviceState *dev)
+{
+    GPEXHost *s = GPEX_HOST(dev);
+
+    g_free(s->irq);
+}
+
 static const char *gpex_host_root_bus_path(PCIHostState *host_bridge,
                                           PCIBus *rootbus)
 {
@@ -166,6 +189,7 @@ static const Property gpex_host_properties[] = {
                        gpex_cfg.mmio64.base, 0),
     DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MMIO_SIZE, GPEXHost,
                      gpex_cfg.mmio64.size, 0),
+    DEFINE_PROP_UINT8("num-irqs", GPEXHost, num_irqs, PCI_NUM_PINS),
 };
 
 static void gpex_host_class_init(ObjectClass *klass, void *data)
@@ -175,6 +199,7 @@ static void gpex_host_class_init(ObjectClass *klass, void *data)
 
     hc->root_bus_path = gpex_host_root_bus_path;
     dc->realize = gpex_host_realize;
+    dc->unrealize = gpex_host_unrealize;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     dc->fw_name = "pci";
     device_class_set_props(dc, gpex_host_properties);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index c792ab9c359..2bc5a9dd981 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -179,7 +179,7 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
 {
     int pin, dev;
     uint32_t irq_map_stride = 0;
-    uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS *
+    uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS *
                           FDT_MAX_INT_MAP_WIDTH] = {};
     uint32_t *irq_map = full_irq_map;
 
@@ -191,11 +191,11 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
      * possible slot) seeing the interrupt-map-mask will allow the table
      * to wrap to any number of devices.
      */
-    for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
+    for (dev = 0; dev < PCI_NUM_PINS; dev++) {
         int devfn = dev * 0x8;
 
-        for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
-            int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
+        for (pin = 0; pin < PCI_NUM_PINS; pin++) {
+            int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
             int i = 0;
 
             /* Fill PCI address cells */
@@ -221,7 +221,7 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
     }
 
     qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map,
-                     GPEX_NUM_IRQS * GPEX_NUM_IRQS *
+                     PCI_NUM_PINS * PCI_NUM_PINS *
                      irq_map_stride * sizeof(uint32_t));
 
     qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
@@ -1246,7 +1246,7 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
 
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         irq = qdev_get_gpio_in(irqchip, PCIE_IRQ + i);
 
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
diff --git a/hw/xen/xen-pvh-common.c b/hw/xen/xen-pvh-common.c
index a10c44cc758..9c21fa858d3 100644
--- a/hw/xen/xen-pvh-common.c
+++ b/hw/xen/xen-pvh-common.c
@@ -169,7 +169,7 @@ static inline void xenpvh_gpex_init(XenPVHMachineState *s,
      */
     assert(xpc->set_pci_intx_irq);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         qemu_irq irq = qemu_allocate_irq(xpc->set_pci_intx_irq, s, i);
 
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c
index 98622ae86dc..b08404fc17c 100644
--- a/hw/xtensa/virt.c
+++ b/hw/xtensa/virt.c
@@ -93,7 +93,7 @@ static void create_pcie(MachineState *ms, CPUXtensaState *env, int irq_base,
     /* Connect IRQ lines. */
     extints = xtensa_get_extints(env);
 
-    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+    for (i = 0; i < PCI_NUM_PINS; i++) {
         void *q = extints[irq_base + i];
 
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, q);
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 02/29] hw/misc/ivshmem-flat: Add ivshmem-flat device
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 01/29] hw/pci-host/gpex: Allow more than 4 legacy IRQs Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2025-01-02 21:19   ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 03/29] hw/misc/ivshmem: Rename ivshmem to ivshmem-pci Philippe Mathieu-Daudé
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gustavo Romero, Philippe Mathieu-Daudé

From: Gustavo Romero <gustavo.romero@linaro.org>

Add a new device, ivshmem-flat, which is similar to the ivshmem PCI but
does not require a PCI bus. It's meant to be used on machines like those
with Cortex-M MCUs, which usually lack a PCI/PCIe bus, e.g. lm3s6965evb
and mps2-an385.

The device currently only supports the sysbus bus.

The new device, just like the ivshmem PCI device, supports both peer
notification via hardware interrupts and shared memory.

The device shared memory size can be set using the 'shmem-size' option
and it defaults to 4 MiB, which is the default size of shmem allocated
by the ivshmem server.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1134
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
[PMD: Rebased updating Property and using DEFINE_TYPES macro]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241216141818.111255-2-gustavo.romero@linaro.org>
---
 docs/system/device-emulation.rst     |   1 +
 docs/system/devices/ivshmem-flat.rst |  33 ++
 include/hw/misc/ivshmem-flat.h       |  85 +++++
 hw/misc/ivshmem-flat.c               | 459 +++++++++++++++++++++++++++
 hw/misc/Kconfig                      |   5 +
 hw/misc/meson.build                  |   2 +
 hw/misc/trace-events                 |  16 +
 7 files changed, 601 insertions(+)
 create mode 100644 docs/system/devices/ivshmem-flat.rst
 create mode 100644 include/hw/misc/ivshmem-flat.h
 create mode 100644 hw/misc/ivshmem-flat.c

diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
index f19777411cd..a1b0d7997e0 100644
--- a/docs/system/device-emulation.rst
+++ b/docs/system/device-emulation.rst
@@ -86,6 +86,7 @@ Emulated Devices
    devices/ccid.rst
    devices/cxl.rst
    devices/ivshmem.rst
+   devices/ivshmem-flat.rst
    devices/keyboard.rst
    devices/net.rst
    devices/nvme.rst
diff --git a/docs/system/devices/ivshmem-flat.rst b/docs/system/devices/ivshmem-flat.rst
new file mode 100644
index 00000000000..1f97052804a
--- /dev/null
+++ b/docs/system/devices/ivshmem-flat.rst
@@ -0,0 +1,33 @@
+Inter-VM Shared Memory Flat Device
+----------------------------------
+
+The ivshmem-flat device is meant to be used on machines that lack a PCI bus,
+making them unsuitable for the use of the traditional ivshmem device modeled as
+a PCI device. Machines like those with a Cortex-M MCU are good candidates to use
+the ivshmem-flat device. Also, since the flat version maps the control and
+status registers directly to the memory, it requires a quite tiny "device
+driver" to interact with other VMs, which is useful in some RTOSes, like
+Zephyr, which usually run on constrained resource targets.
+
+Similar to the ivshmem device, the ivshmem-flat device supports both peer
+notification via HW interrupts and Inter-VM shared memory. This allows the
+device to be used together with the traditional ivshmem, enabling communication
+between, for instance, an aarch64 VM  (using the traditional ivshmem device and
+running Linux), and an arm VM (using the ivshmem-flat device and running Zephyr
+instead).
+
+The ivshmem-flat device does not support the use of a ``memdev`` option (see
+ivshmem.rst for more details). It relies on the ivshmem server to create and
+distribute the proper shared memory file descriptor and the eventfd(s) to notify
+(interrupt) the peers. Therefore, to use this device, it is always necessary to
+have an ivshmem server up and running for proper device creation.
+
+Although the ivshmem-flat supports both peer notification (interrupts) and
+shared memory, the interrupt mechanism is optional. If no input IRQ is
+specified for the device it is disabled, preventing the VM from notifying or
+being notified by other VMs (a warning will be displayed to the user to inform
+the IRQ mechanism is disabled). The shared memory region is always present.
+
+The MMRs (INTRMASK, INTRSTATUS, IVPOSITION, and DOORBELL registers) offsets at
+the MMR region, and their functions, follow the ivshmem spec, so they work
+exactly as in the ivshmem PCI device (see ./specs/ivshmem-spec.txt).
diff --git a/include/hw/misc/ivshmem-flat.h b/include/hw/misc/ivshmem-flat.h
new file mode 100644
index 00000000000..97ca0ddce61
--- /dev/null
+++ b/include/hw/misc/ivshmem-flat.h
@@ -0,0 +1,85 @@
+/*
+ * Inter-VM Shared Memory Flat Device
+ *
+ * SPDX-FileCopyrightText: 2023 Linaro Ltd.
+ * SPDX-FileContributor: Gustavo Romero <gustavo.romero@linaro.org>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#ifndef IVSHMEM_FLAT_H
+#define IVSHMEM_FLAT_H
+
+#include "qemu/queue.h"
+#include "qemu/event_notifier.h"
+#include "chardev/char-fe.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+#define IVSHMEM_MAX_VECTOR_NUM 64
+
+/*
+ * QEMU interface:
+ *  + QOM property "chardev" is the character device id of the ivshmem server
+ *    socket
+ *  + QOM property "shmem-size" sets the size of the RAM region shared between
+ *    the device and the ivshmem server
+ *  + sysbus MMIO region 0: device I/O mapped registers
+ *  + sysbus MMIO region 1: shared memory with ivshmem server
+ *  + sysbus IRQ 0: single output interrupt
+ */
+
+#define TYPE_IVSHMEM_FLAT "ivshmem-flat"
+typedef struct IvshmemFTState IvshmemFTState;
+
+DECLARE_INSTANCE_CHECKER(IvshmemFTState, IVSHMEM_FLAT, TYPE_IVSHMEM_FLAT)
+
+/* Ivshmem registers. See ./docs/specs/ivshmem-spec.txt for details. */
+enum ivshmem_registers {
+    INTMASK = 0,
+    INTSTATUS = 4,
+    IVPOSITION = 8,
+    DOORBELL = 12,
+};
+
+typedef struct VectorInfo {
+    EventNotifier event_notifier;
+    uint16_t id;
+} VectorInfo;
+
+typedef struct IvshmemPeer {
+    QTAILQ_ENTRY(IvshmemPeer) next;
+    VectorInfo vector[IVSHMEM_MAX_VECTOR_NUM];
+    int vector_counter;
+    uint16_t id;
+} IvshmemPeer;
+
+struct IvshmemFTState {
+    SysBusDevice parent_obj;
+
+    uint64_t msg_buf;
+    int msg_buffered_bytes;
+
+    QTAILQ_HEAD(, IvshmemPeer) peer;
+    IvshmemPeer own;
+
+    CharBackend server_chr;
+
+    /* IRQ */
+    qemu_irq irq;
+
+    /* I/O registers */
+    MemoryRegion iomem;
+    uint32_t intmask;
+    uint32_t intstatus;
+    uint32_t ivposition;
+    uint32_t doorbell;
+
+    /* Shared memory */
+    MemoryRegion shmem;
+    int shmem_fd;
+    uint32_t shmem_size;
+};
+
+#endif /* IVSHMEM_FLAT_H */
diff --git a/hw/misc/ivshmem-flat.c b/hw/misc/ivshmem-flat.c
new file mode 100644
index 00000000000..33fc9425d20
--- /dev/null
+++ b/hw/misc/ivshmem-flat.c
@@ -0,0 +1,459 @@
+/*
+ * Inter-VM Shared Memory Flat Device
+ *
+ * SPDX-FileCopyrightText: 2023 Linaro Ltd.
+ * SPDX-FileContributor: Gustavo Romero <gustavo.romero@linaro.org>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/error-report.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "exec/address-spaces.h"
+#include "trace.h"
+
+#include "hw/misc/ivshmem-flat.h"
+
+static int64_t ivshmem_flat_recv_msg(IvshmemFTState *s, int *pfd)
+{
+    int64_t msg;
+    int n, ret;
+
+    n = 0;
+    do {
+        ret = qemu_chr_fe_read_all(&s->server_chr, (uint8_t *)&msg + n,
+                                   sizeof(msg) - n);
+        if (ret < 0) {
+            if (ret == -EINTR) {
+                continue;
+            }
+            exit(1);
+        }
+        n += ret;
+    } while (n < sizeof(msg));
+
+    if (pfd) {
+        *pfd = qemu_chr_fe_get_msgfd(&s->server_chr);
+    }
+    return le64_to_cpu(msg);
+}
+
+static void ivshmem_flat_irq_handler(void *opaque)
+{
+    VectorInfo *vi = opaque;
+    EventNotifier *e = &vi->event_notifier;
+    uint16_t vector_id;
+    const VectorInfo (*v)[64];
+
+    assert(e->initialized);
+
+    vector_id = vi->id;
+
+    /*
+     * The vector info struct is passed to the handler via the 'opaque' pointer.
+     * This struct pointer allows the retrieval of the vector ID and its
+     * associated event notifier. However, for triggering an interrupt using
+     * qemu_set_irq, it's necessary to also have a pointer to the device state,
+     * i.e., a pointer to the IvshmemFTState struct. Since the vector info
+     * struct is contained within the IvshmemFTState struct, its pointer can be
+     * used to obtain the pointer to IvshmemFTState through simple pointer math.
+     */
+    v = (void *)(vi - vector_id); /* v =  &IvshmemPeer->vector[0] */
+    IvshmemPeer *own_peer = container_of(v, IvshmemPeer, vector);
+    IvshmemFTState *s = container_of(own_peer, IvshmemFTState, own);
+
+    /* Clear event  */
+    if (!event_notifier_test_and_clear(e)) {
+        return;
+    }
+
+    trace_ivshmem_flat_irq_handler(vector_id);
+
+    /*
+     * Toggle device's output line, which is connected to interrupt controller,
+     * generating an interrupt request to the CPU.
+     */
+    qemu_irq_pulse(s->irq);
+}
+
+static IvshmemPeer *ivshmem_flat_find_peer(IvshmemFTState *s, uint16_t peer_id)
+{
+    IvshmemPeer *peer;
+
+    /* Own ID */
+    if (s->own.id == peer_id) {
+        return &s->own;
+    }
+
+    /* Peer ID */
+    QTAILQ_FOREACH(peer, &s->peer, next) {
+        if (peer->id == peer_id) {
+            return peer;
+        }
+    }
+
+    return NULL;
+}
+
+static IvshmemPeer *ivshmem_flat_add_peer(IvshmemFTState *s, uint16_t peer_id)
+{
+    IvshmemPeer *new_peer;
+
+    new_peer = g_malloc0(sizeof(*new_peer));
+    new_peer->id = peer_id;
+    new_peer->vector_counter = 0;
+
+    QTAILQ_INSERT_TAIL(&s->peer, new_peer, next);
+
+    trace_ivshmem_flat_new_peer(peer_id);
+
+    return new_peer;
+}
+
+static void ivshmem_flat_remove_peer(IvshmemFTState *s, uint16_t peer_id)
+{
+    IvshmemPeer *peer;
+
+    peer = ivshmem_flat_find_peer(s, peer_id);
+    assert(peer);
+
+    QTAILQ_REMOVE(&s->peer, peer, next);
+    for (int n = 0; n < peer->vector_counter; n++) {
+        int efd;
+        efd = event_notifier_get_fd(&(peer->vector[n].event_notifier));
+        close(efd);
+    }
+
+    g_free(peer);
+}
+
+static void ivshmem_flat_add_vector(IvshmemFTState *s, IvshmemPeer *peer,
+                                    int vector_fd)
+{
+    if (peer->vector_counter >= IVSHMEM_MAX_VECTOR_NUM) {
+        trace_ivshmem_flat_add_vector_failure(peer->vector_counter,
+                                              vector_fd, peer->id);
+        close(vector_fd);
+
+        return;
+    }
+
+    trace_ivshmem_flat_add_vector_success(peer->vector_counter,
+                                          vector_fd, peer->id);
+
+    /*
+     * Set vector ID and its associated eventfd notifier and add them to the
+     * peer.
+     */
+    peer->vector[peer->vector_counter].id = peer->vector_counter;
+    g_unix_set_fd_nonblocking(vector_fd, true, NULL);
+    event_notifier_init_fd(&peer->vector[peer->vector_counter].event_notifier,
+                           vector_fd);
+
+    /*
+     * If it's the device's own ID, register also the handler for the eventfd
+     * so the device can be notified by the other peers.
+     */
+    if (peer == &s->own) {
+        qemu_set_fd_handler(vector_fd, ivshmem_flat_irq_handler, NULL,
+                            &peer->vector);
+    }
+
+    peer->vector_counter++;
+}
+
+static void ivshmem_flat_process_msg(IvshmemFTState *s, uint64_t msg, int fd)
+{
+    uint16_t peer_id;
+    IvshmemPeer *peer;
+
+    peer_id = msg & 0xFFFF;
+    peer = ivshmem_flat_find_peer(s, peer_id);
+
+    if (!peer) {
+        peer = ivshmem_flat_add_peer(s, peer_id);
+    }
+
+    if (fd >= 0) {
+        ivshmem_flat_add_vector(s, peer, fd);
+    } else { /* fd == -1, which is received when peers disconnect. */
+        ivshmem_flat_remove_peer(s, peer_id);
+    }
+}
+
+static int ivshmem_flat_can_receive_data(void *opaque)
+{
+    IvshmemFTState *s = opaque;
+
+    assert(s->msg_buffered_bytes < sizeof(s->msg_buf));
+    return sizeof(s->msg_buf) - s->msg_buffered_bytes;
+}
+
+static void ivshmem_flat_read_msg(void *opaque, const uint8_t *buf, int size)
+{
+    IvshmemFTState *s = opaque;
+    int fd;
+    int64_t msg;
+
+    assert(size >= 0 && s->msg_buffered_bytes + size <= sizeof(s->msg_buf));
+    memcpy((unsigned char *)&s->msg_buf + s->msg_buffered_bytes, buf, size);
+    s->msg_buffered_bytes += size;
+    if (s->msg_buffered_bytes < sizeof(s->msg_buf)) {
+        return;
+    }
+    msg = le64_to_cpu(s->msg_buf);
+    s->msg_buffered_bytes = 0;
+
+    fd = qemu_chr_fe_get_msgfd(&s->server_chr);
+
+    ivshmem_flat_process_msg(s, msg, fd);
+}
+
+static uint64_t ivshmem_flat_iomem_read(void *opaque,
+                                        hwaddr offset, unsigned size)
+{
+    IvshmemFTState *s = opaque;
+    uint32_t ret;
+
+    trace_ivshmem_flat_read_mmr(offset);
+
+    switch (offset) {
+    case INTMASK:
+        ret = 0; /* Ignore read since all bits are reserved in rev 1. */
+        break;
+    case INTSTATUS:
+        ret = 0; /* Ignore read since all bits are reserved in rev 1. */
+        break;
+    case IVPOSITION:
+        ret = s->own.id;
+        break;
+    case DOORBELL:
+        trace_ivshmem_flat_read_mmr_doorbell(); /* DOORBELL is write-only */
+        ret = 0;
+        break;
+    default:
+        /* Should never reach out here due to iomem map range being exact */
+        trace_ivshmem_flat_read_write_mmr_invalid(offset);
+        ret = 0;
+    }
+
+    return ret;
+}
+
+static int ivshmem_flat_interrupt_peer(IvshmemFTState *s,
+                                       uint16_t peer_id, uint16_t vector_id)
+{
+    IvshmemPeer *peer;
+
+    peer = ivshmem_flat_find_peer(s, peer_id);
+    if (!peer) {
+        trace_ivshmem_flat_interrupt_invalid_peer(peer_id);
+        return 1;
+    }
+
+    event_notifier_set(&(peer->vector[vector_id].event_notifier));
+
+    return 0;
+}
+
+static void ivshmem_flat_iomem_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    IvshmemFTState *s = opaque;
+    uint16_t peer_id = (value >> 16) & 0xFFFF;
+    uint16_t vector_id = value & 0xFFFF;
+
+    trace_ivshmem_flat_write_mmr(offset);
+
+    switch (offset) {
+    case INTMASK:
+        break;
+    case INTSTATUS:
+        break;
+    case IVPOSITION:
+        break;
+    case DOORBELL:
+        trace_ivshmem_flat_interrupt_peer(peer_id, vector_id);
+        ivshmem_flat_interrupt_peer(s, peer_id, vector_id);
+        break;
+    default:
+        /* Should never reach out here due to iomem map range being exact. */
+        trace_ivshmem_flat_read_write_mmr_invalid(offset);
+        break;
+    }
+
+    return;
+}
+
+static const MemoryRegionOps ivshmem_flat_ops = {
+    .read = ivshmem_flat_iomem_read,
+    .write = ivshmem_flat_iomem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = { /* Read/write aligned at 32 bits. */
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void ivshmem_flat_instance_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    IvshmemFTState *s = IVSHMEM_FLAT(obj);
+
+    /*
+     * Init mem region for 4 MMRs (ivshmem_registers),
+     * 32 bits each => 16 bytes (0x10).
+     */
+    memory_region_init_io(&s->iomem, obj, &ivshmem_flat_ops, s,
+                          "ivshmem-mmio", 0x10);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    /*
+     * Create one output IRQ that will be connect to the
+     * machine's interrupt controller.
+     */
+    sysbus_init_irq(sbd, &s->irq);
+
+    QTAILQ_INIT(&s->peer);
+}
+
+static bool ivshmem_flat_connect_server(DeviceState *dev, Error **errp)
+{
+    IvshmemFTState *s = IVSHMEM_FLAT(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    int64_t protocol_version, msg;
+    int shmem_fd;
+    uint16_t peer_id;
+    struct stat fdstat;
+
+    /* Check ivshmem server connection. */
+    if (!qemu_chr_fe_backend_connected(&s->server_chr)) {
+        error_setg(errp, "ivshmem server socket not specified or incorret."
+                         " Can't create device.");
+        return false;
+    }
+
+    /*
+     * Message sequence from server on new connection:
+     *  _____________________________________
+     * |STEP| uint64_t msg  | int fd         |
+     *  -------------------------------------
+     *
+     *  0    PROTOCOL        -1              \
+     *  1    OWN PEER ID     -1               |-- Header/Greeting
+     *  2    -1              shmem fd        /
+     *
+     *  3    PEER IDx        Other peer's Vector 0 eventfd
+     *  4    PEER IDx        Other peer's Vector 1 eventfd
+     *  .                    .
+     *  .                    .
+     *  .                    .
+     *  N    PEER IDy        Other peer's Vector 0 eventfd
+     *  N+1  PEER IDy        Other peer's Vector 1 eventfd
+     *  .                    .
+     *  .                    .
+     *  .                    .
+     *
+     *  ivshmem_flat_recv_msg() calls return 'msg' and 'fd'.
+     *
+     *  See ./docs/specs/ivshmem-spec.txt for details on the protocol.
+     */
+
+    /* Step 0 */
+    protocol_version = ivshmem_flat_recv_msg(s, NULL);
+
+    /* Step 1 */
+    msg = ivshmem_flat_recv_msg(s, NULL);
+    peer_id = 0xFFFF & msg;
+    s->own.id = peer_id;
+    s->own.vector_counter = 0;
+
+    trace_ivshmem_flat_proto_ver_own_id(protocol_version, s->own.id);
+
+    /* Step 2 */
+    msg = ivshmem_flat_recv_msg(s, &shmem_fd);
+    /* Map shmem fd and MMRs into memory regions. */
+    if (msg != -1 || shmem_fd < 0) {
+        error_setg(errp, "Could not receive valid shmem fd."
+                         " Can't create device!");
+        return false;
+    }
+
+    if (fstat(shmem_fd, &fdstat) != 0) {
+        error_setg(errp, "Could not determine shmem fd size."
+                         " Can't create device!");
+        return false;
+    }
+    trace_ivshmem_flat_shmem_size(shmem_fd, fdstat.st_size);
+
+    /*
+     * Shmem size provided by the ivshmem server must be equal to
+     * device's shmem size.
+     */
+    if (fdstat.st_size != s->shmem_size) {
+        error_setg(errp, "Can't map shmem fd: shmem size different"
+                         " from device size!");
+        return false;
+    }
+
+    /*
+     * Beyond step 2 ivshmem_process_msg, called by ivshmem_flat_read_msg
+     * handler -- when data is available on the server socket -- will handle
+     * the additional messages that will be generated by the server as peers
+     * connect or disconnect.
+     */
+    qemu_chr_fe_set_handlers(&s->server_chr, ivshmem_flat_can_receive_data,
+                             ivshmem_flat_read_msg, NULL, NULL, s, NULL, true);
+
+    memory_region_init_ram_from_fd(&s->shmem, OBJECT(s),
+                                   "ivshmem-shmem", s->shmem_size,
+                                   RAM_SHARED, shmem_fd, 0, NULL);
+    sysbus_init_mmio(sbd, &s->shmem);
+
+    return true;
+}
+
+static void ivshmem_flat_realize(DeviceState *dev, Error **errp)
+{
+    if (!ivshmem_flat_connect_server(dev, errp)) {
+        return;
+    }
+}
+
+static const Property ivshmem_flat_props[] = {
+    DEFINE_PROP_CHR("chardev", IvshmemFTState, server_chr),
+    DEFINE_PROP_UINT32("shmem-size", IvshmemFTState, shmem_size, 4 * MiB),
+};
+
+static void ivshmem_flat_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->hotpluggable = true;
+    dc->realize = ivshmem_flat_realize;
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    device_class_set_props(dc, ivshmem_flat_props);
+
+    /* Reason: Must be wired up in code (sysbus MRs and IRQ) */
+    dc->user_creatable = false;
+}
+
+static const TypeInfo ivshmem_flat_types[] = {
+    {
+        .name           = TYPE_IVSHMEM_FLAT,
+        .parent         = TYPE_SYS_BUS_DEVICE,
+        .instance_size  = sizeof(IvshmemFTState),
+        .instance_init  = ivshmem_flat_instance_init,
+        .class_init     = ivshmem_flat_class_init,
+    },
+};
+
+DEFINE_TYPES(ivshmem_flat_types)
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1f1baa5dde9..8f9ce2f68c3 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -72,6 +72,11 @@ config IVSHMEM_DEVICE
     default y if PCI_DEVICES
     depends on PCI && LINUX && IVSHMEM && MSI_NONBROKEN
 
+config IVSHMEM_FLAT_DEVICE
+    bool
+    default y
+    depends on LINUX && IVSHMEM
+
 config ECCMEMCTL
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d02d96e403b..7a16ddb1dcc 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -37,7 +37,9 @@ system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
 
 subdir('macio')
 
+# ivshmem devices
 system_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
+system_ss.add(when: 'CONFIG_IVSHMEM_FLAT_DEVICE', if_true: files('ivshmem-flat.c'))
 
 system_ss.add(when: 'CONFIG_ALLWINNER_SRAMC', if_true: files('allwinner-sramc.c'))
 system_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index b9fbcb09249..0f5d2b56660 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -368,3 +368,19 @@ aspeed_sli_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx
 aspeed_sliio_write(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
 aspeed_sliio_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
 
+# ivshmem-flat.c
+ivshmem_flat_irq_handler(uint16_t vector_id) "Caught interrupt request: vector %d"
+ivshmem_flat_new_peer(uint16_t peer_id) "New peer ID: %d"
+ivshmem_flat_add_vector_failure(uint16_t vector_id, uint32_t vector_fd, uint16_t peer_id) "Failed to add vector %u (fd = %u) to peer ID %u, maximum number of vectors reached"
+ivshmem_flat_add_vector_success(uint16_t vector_id, uint32_t vector_fd, uint16_t peer_id) "Successful addition of vector %u (fd = %u) to peer ID %u"
+ivshmem_flat_irq_resolved(const char *irq_qompath) "IRQ QOM path '%s' correctly resolved"
+ivshmem_flat_proto_ver_own_id(uint64_t proto_ver, uint16_t peer_id) "Protocol Version = 0x%"PRIx64", Own Peer ID = %u"
+ivshmem_flat_shmem_size(int fd, uint64_t size) "Shmem fd (%d) total size is %"PRIu64" byte(s)"
+ivshmem_flat_shmem_map(uint64_t addr) "Mapping shmem @ 0x%"PRIx64
+ivshmem_flat_mmio_map(uint64_t addr) "Mapping MMRs @ 0x%"PRIx64
+ivshmem_flat_read_mmr(uint64_t addr_offset) "Read access at offset %"PRIu64
+ivshmem_flat_read_mmr_doorbell(void) "DOORBELL register is write-only!"
+ivshmem_flat_read_write_mmr_invalid(uint64_t addr_offset) "No ivshmem register mapped at offset %"PRIu64
+ivshmem_flat_interrupt_invalid_peer(uint16_t peer_id) "Can't interrupt non-existing peer %u"
+ivshmem_flat_write_mmr(uint64_t addr_offset) "Write access at offset %"PRIu64
+ivshmem_flat_interrupt_peer(uint16_t peer_id, uint16_t vector_id) "Interrupting peer ID %u, vector %u..."
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 03/29] hw/misc/ivshmem: Rename ivshmem to ivshmem-pci
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 01/29] hw/pci-host/gpex: Allow more than 4 legacy IRQs Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 02/29] hw/misc/ivshmem-flat: Add ivshmem-flat device Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 04/29] hw/usb/uhci: checkpatch cleanup Philippe Mathieu-Daudé
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gustavo Romero, Philippe Mathieu-Daudé

From: Gustavo Romero <gustavo.romero@linaro.org>

Because now there is also an MMIO ivshmem device (ivshmem-flat.c), and
ivshmem.c is a PCI specific implementation, rename it to ivshmem-pci.c.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Message-ID: <20241216141818.111255-5-gustavo.romero@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/misc/{ivshmem.c => ivshmem-pci.c} | 0
 hw/misc/meson.build                  | 2 +-
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename hw/misc/{ivshmem.c => ivshmem-pci.c} (100%)

diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem-pci.c
similarity index 100%
rename from hw/misc/ivshmem.c
rename to hw/misc/ivshmem-pci.c
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 7a16ddb1dcc..55f493521be 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -38,7 +38,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
 subdir('macio')
 
 # ivshmem devices
-system_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
+system_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem-pci.c'))
 system_ss.add(when: 'CONFIG_IVSHMEM_FLAT_DEVICE', if_true: files('ivshmem-flat.c'))
 
 system_ss.add(when: 'CONFIG_ALLWINNER_SRAMC', if_true: files('allwinner-sramc.c'))
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 04/29] hw/usb/uhci: checkpatch cleanup
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (2 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 03/29] hw/misc/ivshmem: Rename ivshmem to ivshmem-pci Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 05/29] hw/usb/uhci: Introduce and use register defines Philippe Mathieu-Daudé
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Guenter Roeck, Cédric Le Goater, Philippe Mathieu-Daudé

From: Guenter Roeck <linux@roeck-us.net>

Fix reported checkpatch issues to prepare for next patches
in the series.

No functional change.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20240906122542.3808997-2-linux@roeck-us.net>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/usb/hcd-uhci.c | 90 +++++++++++++++++++++++++++++------------------
 1 file changed, 56 insertions(+), 34 deletions(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 0559b3ae3e1..7c0cc694554 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -67,7 +67,7 @@ struct UHCIPCIDeviceClass {
     UHCIInfo       info;
 };
 
-/* 
+/*
  * Pending async transaction.
  * 'packet' must be the first field because completion
  * handler does "(UHCIAsync *) pkt" cast.
@@ -220,8 +220,9 @@ static void uhci_async_cancel(UHCIAsync *async)
     uhci_async_unlink(async);
     trace_usb_uhci_packet_cancel(async->queue->token, async->td_addr,
                                  async->done);
-    if (!async->done)
+    if (!async->done) {
         usb_cancel_packet(&async->packet);
+    }
     uhci_async_free(async);
 }
 
@@ -322,7 +323,7 @@ static void uhci_reset(DeviceState *dev)
     s->fl_base_addr = 0;
     s->sof_timing = 64;
 
-    for(i = 0; i < UHCI_PORTS; i++) {
+    for (i = 0; i < UHCI_PORTS; i++) {
         port = &s->ports[i];
         port->ctrl = 0x0080;
         if (port->port.dev && port->port.dev->attached) {
@@ -387,7 +388,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 
     trace_usb_uhci_mmio_writew(addr, val);
 
-    switch(addr) {
+    switch (addr) {
     case 0x00:
         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
             /* start frame processing */
@@ -404,7 +405,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
             int i;
 
             /* send reset on the USB bus */
-            for(i = 0; i < UHCI_PORTS; i++) {
+            for (i = 0; i < UHCI_PORTS; i++) {
                 port = &s->ports[i];
                 usb_device_reset(port->port.dev);
             }
@@ -425,10 +426,13 @@ static void uhci_port_write(void *opaque, hwaddr addr,
         break;
     case 0x02:
         s->status &= ~val;
-        /* XXX: the chip spec is not coherent, so we add a hidden
-           register to distinguish between IOC and SPD */
-        if (val & UHCI_STS_USBINT)
+        /*
+         * XXX: the chip spec is not coherent, so we add a hidden
+         * register to distinguish between IOC and SPD
+         */
+        if (val & UHCI_STS_USBINT) {
             s->status2 = 0;
+        }
         uhci_update_irq(s);
         break;
     case 0x04:
@@ -436,8 +440,9 @@ static void uhci_port_write(void *opaque, hwaddr addr,
         uhci_update_irq(s);
         break;
     case 0x06:
-        if (s->status & UHCI_STS_HCHALTED)
+        if (s->status & UHCI_STS_HCHALTED) {
             s->frnum = val & 0x7ff;
+        }
         break;
     case 0x08:
         s->fl_base_addr &= 0xffff0000;
@@ -464,8 +469,8 @@ static void uhci_port_write(void *opaque, hwaddr addr,
             dev = port->port.dev;
             if (dev && dev->attached) {
                 /* port reset */
-                if ( (val & UHCI_PORT_RESET) &&
-                     !(port->ctrl & UHCI_PORT_RESET) ) {
+                if ((val & UHCI_PORT_RESET) &&
+                     !(port->ctrl & UHCI_PORT_RESET)) {
                     usb_device_reset(dev);
                 }
             }
@@ -487,7 +492,7 @@ static uint64_t uhci_port_read(void *opaque, hwaddr addr, unsigned size)
     UHCIState *s = opaque;
     uint32_t val;
 
-    switch(addr) {
+    switch (addr) {
     case 0x00:
         val = s->cmd;
         break;
@@ -533,12 +538,13 @@ static uint64_t uhci_port_read(void *opaque, hwaddr addr, unsigned size)
 }
 
 /* signal resume if controller suspended */
-static void uhci_resume (void *opaque)
+static void uhci_resume(void *opaque)
 {
     UHCIState *s = (UHCIState *)opaque;
 
-    if (!s)
+    if (!s) {
         return;
+    }
 
     if (s->cmd & UHCI_CMD_EGSM) {
         s->cmd |= UHCI_CMD_FGR;
@@ -674,7 +680,8 @@ static int uhci_handle_td_error(UHCIState *s, UHCI_TD *td, uint32_t td_addr,
     return ret;
 }
 
-static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
+static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async,
+                            uint32_t *int_mask)
 {
     int len = 0, max_len;
     uint8_t pid;
@@ -682,8 +689,9 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
 
-    if (td->ctrl & TD_CTRL_IOS)
+    if (td->ctrl & TD_CTRL_IOS) {
         td->ctrl &= ~TD_CTRL_ACTIVE;
+    }
 
     if (async->packet.status != USB_RET_SUCCESS) {
         return uhci_handle_td_error(s, td, async->td_addr,
@@ -693,12 +701,15 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
     len = async->packet.actual_length;
     td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
 
-    /* The NAK bit may have been set by a previous frame, so clear it
-       here.  The docs are somewhat unclear, but win2k relies on this
-       behavior.  */
+    /*
+     * The NAK bit may have been set by a previous frame, so clear it
+     * here.  The docs are somewhat unclear, but win2k relies on this
+     * behavior.
+     */
     td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
-    if (td->ctrl & TD_CTRL_IOC)
+    if (td->ctrl & TD_CTRL_IOC) {
         *int_mask |= 0x01;
+    }
 
     if (pid == USB_TOKEN_IN) {
         pci_dma_write(&s->dev, td->buffer, async->buf, len);
@@ -780,9 +791,11 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
 
     if (async) {
         if (queuing) {
-            /* we are busy filling the queue, we are not prepared
-               to consume completed packages then, just leave them
-               in async state */
+            /*
+             * we are busy filling the queue, we are not prepared
+             * to consume completed packages then, just leave them
+             * in async state
+             */
             return TD_RESULT_ASYNC_CONT;
         }
         if (!async->done) {
@@ -832,7 +845,7 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
     }
     usb_packet_addbuf(&async->packet, async->buf, max_len);
 
-    switch(pid) {
+    switch (pid) {
     case USB_TOKEN_OUT:
     case USB_TOKEN_SETUP:
         pci_dma_read(&s->dev, td->buffer, async->buf, max_len);
@@ -911,12 +924,15 @@ static void qhdb_reset(QhDb *db)
 static int qhdb_insert(QhDb *db, uint32_t addr)
 {
     int i;
-    for (i = 0; i < db->count; i++)
-        if (db->addr[i] == addr)
+    for (i = 0; i < db->count; i++) {
+        if (db->addr[i] == addr) {
             return 1;
+        }
+    }
 
-    if (db->count >= UHCI_MAX_QUEUES)
+    if (db->count >= UHCI_MAX_QUEUES) {
         return 1;
+    }
 
     db->addr[db->count++] = addr;
     return 0;
@@ -970,8 +986,10 @@ static void uhci_process_frame(UHCIState *s)
 
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
         if (!s->completions_only && s->frame_bytes >= s->frame_bandwidth) {
-            /* We've reached the usb 1.1 bandwidth, which is
-               1280 bytes/frame, stop processing */
+            /*
+             * We've reached the usb 1.1 bandwidth, which is
+             * 1280 bytes/frame, stop processing
+             */
             trace_usb_uhci_frame_stop_bandwidth();
             break;
         }
@@ -1120,8 +1138,10 @@ static void uhci_frame_timer(void *opaque)
         uhci_async_validate_begin(s);
         uhci_process_frame(s);
         uhci_async_validate_end(s);
-        /* The spec says frnum is the frame currently being processed, and
-         * the guest must look at frnum - 1 on interrupt, so inc frnum now */
+        /*
+         * The spec says frnum is the frame currently being processed, and
+         * the guest must look at frnum - 1 on interrupt, so inc frnum now
+         */
         s->frnum = (s->frnum + 1) & 0x7ff;
         s->expire_time += frame_t;
     }
@@ -1174,7 +1194,7 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
 
     if (s->masterbus) {
         USBPort *ports[UHCI_PORTS];
-        for(i = 0; i < UHCI_PORTS; i++) {
+        for (i = 0; i < UHCI_PORTS; i++) {
             ports[i] = &s->ports[i].port;
         }
         usb_register_companion(s->masterbus, ports, UHCI_PORTS,
@@ -1200,8 +1220,10 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
     memory_region_init_io(&s->io_bar, OBJECT(s), &uhci_ioport_ops, s,
                           "uhci", 0x20);
 
-    /* Use region 4 for consistency with real hardware.  BSD guests seem
-       to rely on this.  */
+    /*
+     * Use region 4 for consistency with real hardware.  BSD guests seem
+     * to rely on this.
+     */
     pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
 }
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 05/29] hw/usb/uhci: Introduce and use register defines
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (3 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 04/29] hw/usb/uhci: checkpatch cleanup Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 06/29] hw/microblaze: Propagate CPU endianness to microblaze_load_kernel() Philippe Mathieu-Daudé
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Guenter Roeck, Cédric Le Goater, Philippe Mathieu-Daudé

From: Guenter Roeck <linux@roeck-us.net>

Introduce defines for UHCI registers to simplify adding register access
in subsequent patches of the series.

No functional change.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20240906122542.3808997-3-linux@roeck-us.net>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/usb/uhci-regs.h | 11 +++++++++++
 hw/usb/hcd-uhci.c          | 32 ++++++++++++++++----------------
 2 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/include/hw/usb/uhci-regs.h b/include/hw/usb/uhci-regs.h
index fd45d29db0f..5b81714e5c2 100644
--- a/include/hw/usb/uhci-regs.h
+++ b/include/hw/usb/uhci-regs.h
@@ -1,6 +1,17 @@
 #ifndef HW_USB_UHCI_REGS_H
 #define HW_USB_UHCI_REGS_H
 
+#define UHCI_USBCMD       0
+#define UHCI_USBSTS       2
+#define UHCI_USBINTR      4
+#define UHCI_USBFRNUM     6
+#define UHCI_USBFLBASEADD 8
+#define UHCI_USBSOF       0x0c
+#define UHCI_USBPORTSC1   0x10
+#define UHCI_USBPORTSC2   0x12
+#define UHCI_USBPORTSC3   0x14
+#define UHCI_USBPORTSC4   0x16
+
 #define UHCI_CMD_FGR      (1 << 4)
 #define UHCI_CMD_EGSM     (1 << 3)
 #define UHCI_CMD_GRESET   (1 << 2)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 7c0cc694554..8528d493d63 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -389,7 +389,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
     trace_usb_uhci_mmio_writew(addr, val);
 
     switch (addr) {
-    case 0x00:
+    case UHCI_USBCMD:
         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
             /* start frame processing */
             trace_usb_uhci_schedule_start();
@@ -424,7 +424,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
             }
         }
         break;
-    case 0x02:
+    case UHCI_USBSTS:
         s->status &= ~val;
         /*
          * XXX: the chip spec is not coherent, so we add a hidden
@@ -435,27 +435,27 @@ static void uhci_port_write(void *opaque, hwaddr addr,
         }
         uhci_update_irq(s);
         break;
-    case 0x04:
+    case UHCI_USBINTR:
         s->intr = val;
         uhci_update_irq(s);
         break;
-    case 0x06:
+    case UHCI_USBFRNUM:
         if (s->status & UHCI_STS_HCHALTED) {
             s->frnum = val & 0x7ff;
         }
         break;
-    case 0x08:
+    case UHCI_USBFLBASEADD:
         s->fl_base_addr &= 0xffff0000;
         s->fl_base_addr |= val & ~0xfff;
         break;
-    case 0x0a:
+    case UHCI_USBFLBASEADD + 2:
         s->fl_base_addr &= 0x0000ffff;
         s->fl_base_addr |= (val << 16);
         break;
-    case 0x0c:
+    case UHCI_USBSOF:
         s->sof_timing = val & 0xff;
         break;
-    case 0x10 ... 0x1f:
+    case UHCI_USBPORTSC1 ... UHCI_USBPORTSC4:
         {
             UHCIPort *port;
             USBDevice *dev;
@@ -493,28 +493,28 @@ static uint64_t uhci_port_read(void *opaque, hwaddr addr, unsigned size)
     uint32_t val;
 
     switch (addr) {
-    case 0x00:
+    case UHCI_USBCMD:
         val = s->cmd;
         break;
-    case 0x02:
+    case UHCI_USBSTS:
         val = s->status;
         break;
-    case 0x04:
+    case UHCI_USBINTR:
         val = s->intr;
         break;
-    case 0x06:
+    case UHCI_USBFRNUM:
         val = s->frnum;
         break;
-    case 0x08:
+    case UHCI_USBFLBASEADD:
         val = s->fl_base_addr & 0xffff;
         break;
-    case 0x0a:
+    case UHCI_USBFLBASEADD + 2:
         val = (s->fl_base_addr >> 16) & 0xffff;
         break;
-    case 0x0c:
+    case UHCI_USBSOF:
         val = s->sof_timing;
         break;
-    case 0x10 ... 0x1f:
+    case UHCI_USBPORTSC1 ... UHCI_USBPORTSC4:
         {
             UHCIPort *port;
             int n;
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 06/29] hw/microblaze: Propagate CPU endianness to microblaze_load_kernel()
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (4 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 05/29] hw/usb/uhci: Introduce and use register defines Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 07/29] hw/i386: Mark devices as little-endian Philippe Mathieu-Daudé
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Philippe Mathieu-Daudé, Anton Johansson, Alistair Francis,
	Edgar E. Iglesias, Richard Henderson

Pass vCPU endianness as argument so we can load kernels
with different endianness (different from the qemu-system-binary
builtin one).

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Anton Johansson <anjo@rev.ng>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20241107012223.94337-3-philmd@linaro.org>
---
 hw/microblaze/boot.h                     | 4 ++--
 hw/microblaze/boot.c                     | 8 ++++----
 hw/microblaze/petalogix_ml605_mmu.c      | 2 +-
 hw/microblaze/petalogix_s3adsp1800_mmu.c | 2 +-
 hw/microblaze/xlnx-zynqmp-pmu.c          | 2 +-
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/hw/microblaze/boot.h b/hw/microblaze/boot.h
index 5a8c2f79750..d179a551a69 100644
--- a/hw/microblaze/boot.h
+++ b/hw/microblaze/boot.h
@@ -2,8 +2,8 @@
 #define MICROBLAZE_BOOT_H
 
 
-void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize,
+void microblaze_load_kernel(MicroBlazeCPU *cpu, bool is_little_endian,
+                            hwaddr ddr_base, uint32_t ramsize,
                             const char *initrd_filename,
                             const char *dtb_filename,
                             void (*machine_cpu_reset)(MicroBlazeCPU *));
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 966fb2cb2a3..3854bc2291b 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -114,8 +114,8 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return addr - 0x30000000LL;
 }
 
-void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize,
+void microblaze_load_kernel(MicroBlazeCPU *cpu, bool is_little_endian,
+                            hwaddr ddr_base, uint32_t ramsize,
                             const char *initrd_filename,
                             const char *dtb_filename,
                             void (*machine_cpu_reset)(MicroBlazeCPU *))
@@ -144,13 +144,13 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
                                &entry, NULL, &high, NULL,
-                               TARGET_BIG_ENDIAN, EM_MICROBLAZE, 0, 0);
+                               !is_little_endian, EM_MICROBLAZE, 0, 0);
         base32 = entry;
         if (base32 == 0xc0000000) {
             kernel_size = load_elf(kernel_filename, NULL,
                                    translate_kernel_address, NULL,
                                    &entry, NULL, NULL, NULL,
-                                   TARGET_BIG_ENDIAN, EM_MICROBLAZE, 0, 0);
+                                   !is_little_endian, EM_MICROBLAZE, 0, 0);
         }
         /* Always boot into physical ram.  */
         boot_info.bootstrap_pc = (uint32_t)entry;
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index deab275495d..8b44be75a22 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -204,7 +204,7 @@ petalogix_ml605_init(MachineState *machine)
     cpu->cfg.pvr_regs[5] = 0xc56be000;
     cpu->cfg.pvr_regs[10] = 0x0e000000; /* virtex 6 */
 
-    microblaze_load_kernel(cpu, MEMORY_BASEADDR, ram_size,
+    microblaze_load_kernel(cpu, true, MEMORY_BASEADDR, ram_size,
                            machine->initrd_filename,
                            BINARY_DEVICE_TREE_FILE,
                            NULL);
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index 4a969af1a01..2c0d8c34cd2 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -129,7 +129,7 @@ petalogix_s3adsp1800_init(MachineState *machine)
 
     create_unimplemented_device("xps_gpio", GPIO_BASEADDR, 0x10000);
 
-    microblaze_load_kernel(cpu, ddr_base, ram_size,
+    microblaze_load_kernel(cpu, !TARGET_BIG_ENDIAN, ddr_base, ram_size,
                            machine->initrd_filename,
                            BINARY_DEVICE_TREE_FILE,
                            NULL);
diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c
index 567aad47bfc..bdbf7328bf4 100644
--- a/hw/microblaze/xlnx-zynqmp-pmu.c
+++ b/hw/microblaze/xlnx-zynqmp-pmu.c
@@ -172,7 +172,7 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine)
     qdev_realize(DEVICE(pmu), NULL, &error_fatal);
 
     /* Load the kernel */
-    microblaze_load_kernel(&pmu->cpu, XLNX_ZYNQMP_PMU_RAM_ADDR,
+    microblaze_load_kernel(&pmu->cpu, true, XLNX_ZYNQMP_PMU_RAM_ADDR,
                            machine->ram_size,
                            machine->initrd_filename,
                            machine->dtb,
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 07/29] hw/i386: Mark devices as little-endian
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (5 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 06/29] hw/microblaze: Propagate CPU endianness to microblaze_load_kernel() Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 08/29] hw/tricore: " Philippe Mathieu-Daudé
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Richard Henderson, Thomas Huth

These devices are only used by the X86 targets, which are only
built as little-endian. Therefore the DEVICE_NATIVE_ENDIAN
definition expand to DEVICE_LITTLE_ENDIAN (besides, the
DEVICE_BIG_ENDIAN case isn't tested). Simplify directly using
DEVICE_LITTLE_ENDIAN.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Thomas Huth <huth@tuxfamily.org>
Message-Id: <20241106184612.71897-2-philmd@linaro.org>
---
 hw/i386/kvm/apic.c         | 2 +-
 hw/i386/pc.c               | 4 ++--
 hw/i386/vapic.c            | 2 +-
 hw/i386/xen/xen_apic.c     | 2 +-
 hw/i386/xen/xen_platform.c | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 602c7696565..75751060009 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -214,7 +214,7 @@ static void kvm_apic_mem_write(void *opaque, hwaddr addr,
 static const MemoryRegionOps kvm_apic_io_ops = {
     .read = kvm_apic_mem_read,
     .write = kvm_apic_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void kvm_apic_reset(APICCommonState *s)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 53a2f226d03..71118765884 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1068,7 +1068,7 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
 static const MemoryRegionOps ioport80_io_ops = {
     .write = ioport80_write,
     .read = ioport80_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
     .impl = {
         .min_access_size = 1,
         .max_access_size = 1,
@@ -1078,7 +1078,7 @@ static const MemoryRegionOps ioport80_io_ops = {
 static const MemoryRegionOps ioportF0_io_ops = {
     .write = ioportF0_write,
     .read = ioportF0_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
     .impl = {
         .min_access_size = 1,
         .max_access_size = 1,
diff --git a/hw/i386/vapic.c b/hw/i386/vapic.c
index 0e6d058d063..14de9b7a820 100644
--- a/hw/i386/vapic.c
+++ b/hw/i386/vapic.c
@@ -718,7 +718,7 @@ static uint64_t vapic_read(void *opaque, hwaddr addr, unsigned size)
 static const MemoryRegionOps vapic_ops = {
     .write = vapic_write,
     .read = vapic_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void vapic_realize(DeviceState *dev, Error **errp)
diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c
index 101e16a7662..a94e9005cbe 100644
--- a/hw/i386/xen/xen_apic.c
+++ b/hw/i386/xen/xen_apic.c
@@ -36,7 +36,7 @@ static void xen_apic_mem_write(void *opaque, hwaddr addr,
 static const MemoryRegionOps xen_apic_io_ops = {
     .read = xen_apic_mem_read,
     .write = xen_apic_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void xen_apic_realize(DeviceState *dev, Error **errp)
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 0f68c3fe7b3..dd648a2ee94 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -514,7 +514,7 @@ static void platform_mmio_write(void *opaque, hwaddr addr,
 static const MemoryRegionOps platform_mmio_handler = {
     .read = &platform_mmio_read,
     .write = &platform_mmio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void platform_mmio_setup(PCIXenPlatformState *d)
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 08/29] hw/tricore: Mark devices as little-endian
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (6 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 07/29] hw/i386: Mark devices as little-endian Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 09/29] hw/openrisc: Mark devices as big-endian Philippe Mathieu-Daudé
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Richard Henderson, Thomas Huth

These devices are only used by the TriCore target, which is
only built as little-endian. Therefore the DEVICE_NATIVE_ENDIAN
definition expand to DEVICE_LITTLE_ENDIAN (besides, the
DEVICE_BIG_ENDIAN case isn't tested). Simplify directly using
DEVICE_LITTLE_ENDIAN.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Thomas Huth <huth@tuxfamily.org>
Message-Id: <20241106184612.71897-3-philmd@linaro.org>
---
 hw/tricore/tricore_testdevice.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/tricore/tricore_testdevice.c b/hw/tricore/tricore_testdevice.c
index e60866d76fa..d2da74e3846 100644
--- a/hw/tricore/tricore_testdevice.c
+++ b/hw/tricore/tricore_testdevice.c
@@ -47,7 +47,7 @@ static const MemoryRegionOps tricore_testdevice_ops = {
         .min_access_size = 4,
         .max_access_size = 4,
     },
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void tricore_testdevice_init(Object *obj)
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 09/29] hw/openrisc: Mark devices as big-endian
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (7 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 08/29] hw/tricore: " Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 10/29] hw/sparc: " Philippe Mathieu-Daudé
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Richard Henderson, Thomas Huth

The openrisc little-endian control is in a control register:
SR[LEE] (which we do not implement at present).

These devices are only used by the OpenRISC target, which is
only built as big-endian. Therefore the DEVICE_NATIVE_ENDIAN
definition expand to DEVICE_BIG_ENDIAN (besides, the
DEVICE_LITTLE_ENDIAN case isn't tested). Simplify directly
using DEVICE_BIG_ENDIAN.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Thomas Huth <huth@tuxfamily.org>
Message-Id: <20241106184612.71897-5-philmd@linaro.org>
---
 hw/openrisc/openrisc_sim.c | 2 +-
 hw/openrisc/virt.c         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 87f9cbc3001..e0da4067ba3 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -266,7 +266,7 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base,
     }
     serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200,
                    serial_hd(uart_idx),
-                   DEVICE_NATIVE_ENDIAN);
+                   DEVICE_BIG_ENDIAN);
 
     /* Add device tree node for serial. */
     nodename = g_strdup_printf("/serial@%" HWADDR_PRIx, base);
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index 22ae057992e..7b60bf85094 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -236,7 +236,7 @@ static void openrisc_virt_serial_init(OR1KVirtState *state, hwaddr base,
     qemu_irq serial_irq = get_per_cpu_irq(cpus, num_cpus, irq_pin);
 
     serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200,
-                   serial_hd(0), DEVICE_NATIVE_ENDIAN);
+                   serial_hd(0), DEVICE_BIG_ENDIAN);
 
     /* Add device tree node for serial. */
     nodename = g_strdup_printf("/serial@%" HWADDR_PRIx, base);
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 10/29] hw/sparc: Mark devices as big-endian
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (8 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 09/29] hw/openrisc: Mark devices as big-endian Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 11/29] hw/net/xilinx_ethlite: Convert some debug logs to trace events Philippe Mathieu-Daudé
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Philippe Mathieu-Daudé, Mark Cave-Ayland, Richard Henderson

These devices are only used by the SPARC targets, which are
only built as big-endian. Therefore the DEVICE_NATIVE_ENDIAN
definition expand to DEVICE_BIG_ENDIAN (besides, the
DEVICE_LITTLE_ENDIAN case isn't tested). Simplify directly
using DEVICE_BIG_ENDIAN.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20241106184612.71897-6-philmd@linaro.org>
---
 hw/sparc/sun4m_iommu.c | 2 +-
 hw/sparc64/sun4u.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c
index 8c1fc82534f..5a4c1f5e3bd 100644
--- a/hw/sparc/sun4m_iommu.c
+++ b/hw/sparc/sun4m_iommu.c
@@ -238,7 +238,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr,
 static const MemoryRegionOps iommu_mem_ops = {
     .read = iommu_mem_read,
     .write = iommu_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_BIG_ENDIAN,
     .valid = {
         .min_access_size = 4,
         .max_access_size = 4,
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 5778709b412..0980b446593 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -254,7 +254,7 @@ static void power_mem_write(void *opaque, hwaddr addr,
 static const MemoryRegionOps power_mem_ops = {
     .read = power_mem_read,
     .write = power_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_BIG_ENDIAN,
     .valid = {
         .min_access_size = 4,
         .max_access_size = 4,
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 11/29] hw/net/xilinx_ethlite: Convert some debug logs to trace events
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (9 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 10/29] hw/sparc: " Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 12/29] hw/net/xilinx_ethlite: Remove unuseful debug logs Philippe Mathieu-Daudé
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Edgar E. Iglesias

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Message-Id: <20241112181044.92193-3-philmd@linaro.org>
---
 hw/net/xilinx_ethlite.c | 5 +++--
 hw/net/trace-events     | 4 ++++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index f3eb2af1934..c38a71c71be 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -30,6 +30,7 @@
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "net/net.h"
+#include "trace.h"
 
 #define D(x)
 #define R_TX_BUF0     0
@@ -194,13 +195,13 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
         return size;
 
     if (s->regs[rxbase + R_RX_CTRL0] & CTRL_S) {
-        D(qemu_log("ethlite lost packet %x\n", s->regs[R_RX_CTRL0]));
+        trace_ethlite_pkt_lost(s->regs[R_RX_CTRL0]);
         return -1;
     }
 
     D(qemu_log("%s %zd rxbase=%x\n", __func__, size, rxbase));
     if (size > (R_MAX - R_RX_BUF0 - rxbase) * 4) {
-        D(qemu_log("ethlite packet is too big, size=%x\n", size));
+        trace_ethlite_pkt_size_too_big(size);
         return -1;
     }
     memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 6100ec324a7..c35bfb2eb8d 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -513,3 +513,7 @@ xen_netdev_connect(int dev, unsigned int tx, unsigned int rx, int port) "vif%u t
 xen_netdev_frontend_changed(const char *dev, int state) "vif%s state %d"
 xen_netdev_tx(int dev, int ref, int off, int len, unsigned int flags, const char *c, const char *d, const char *m, const char *e) "vif%u ref %u off %u len %u flags 0x%x%s%s%s%s"
 xen_netdev_rx(int dev, int idx, int status, int flags) "vif%u idx %d status %d flags 0x%x"
+
+# xilinx_ethlite.c
+ethlite_pkt_lost(uint32_t rx_ctrl) "rx_ctrl:0x%" PRIx32
+ethlite_pkt_size_too_big(uint64_t size) "size:0x%" PRIx64
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 12/29] hw/net/xilinx_ethlite: Remove unuseful debug logs
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (10 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 11/29] hw/net/xilinx_ethlite: Convert some debug logs to trace events Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 13/29] hw/net/xilinx_ethlite: Update QOM style Philippe Mathieu-Daudé
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Edgar E. Iglesias

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Message-Id: <20241112181044.92193-4-philmd@linaro.org>
---
 hw/net/xilinx_ethlite.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index c38a71c71be..4626a55b069 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -32,7 +32,6 @@
 #include "net/net.h"
 #include "trace.h"
 
-#define D(x)
 #define R_TX_BUF0     0
 #define R_TX_LEN0     (0x07f4 / 4)
 #define R_TX_GIE0     (0x07f8 / 4)
@@ -100,7 +99,6 @@ eth_read(void *opaque, hwaddr addr, unsigned int size)
         case R_RX_CTRL1:
         case R_RX_CTRL0:
             r = s->regs[addr];
-            D(qemu_log("%s " HWADDR_FMT_plx "=%x\n", __func__, addr * 4, r));
             break;
 
         default:
@@ -126,13 +124,10 @@ eth_write(void *opaque, hwaddr addr,
             if (addr == R_TX_CTRL1)
                 base = 0x800 / 4;
 
-            D(qemu_log("%s addr=" HWADDR_FMT_plx " val=%x\n",
-                       __func__, addr * 4, value));
             if ((value & (CTRL_P | CTRL_S)) == CTRL_S) {
                 qemu_send_packet(qemu_get_queue(s->nic),
                                  (void *) &s->regs[base],
                                  s->regs[base + R_TX_LEN0]);
-                D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0]));
                 if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                     eth_pulse_irq(s);
             } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) {
@@ -156,8 +151,6 @@ eth_write(void *opaque, hwaddr addr,
         case R_TX_LEN0:
         case R_TX_LEN1:
         case R_TX_GIE0:
-            D(qemu_log("%s addr=" HWADDR_FMT_plx " val=%x\n",
-                       __func__, addr * 4, value));
             s->regs[addr] = value;
             break;
 
@@ -199,7 +192,6 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
         return -1;
     }
 
-    D(qemu_log("%s %zd rxbase=%x\n", __func__, size, rxbase));
     if (size > (R_MAX - R_RX_BUF0 - rxbase) * 4) {
         trace_ethlite_pkt_size_too_big(size);
         return -1;
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 13/29] hw/net/xilinx_ethlite: Update QOM style
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (11 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 12/29] hw/net/xilinx_ethlite: Remove unuseful debug logs Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 14/29] hw/net/xilinx_ethlite: Correct maximum RX buffer size Philippe Mathieu-Daudé
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Edgar E. Iglesias

Use XlnxXpsEthLite typedef, OBJECT_DECLARE_SIMPLE_TYPE macro;
convert type_init() to DEFINE_TYPES().

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Message-Id: <20241112181044.92193-5-philmd@linaro.org>
---
 hw/net/xilinx_ethlite.c | 48 +++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 26 deletions(-)

diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 4626a55b069..330dccb83df 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -53,10 +53,9 @@
 #define CTRL_S     0x1
 
 #define TYPE_XILINX_ETHLITE "xlnx.xps-ethernetlite"
-DECLARE_INSTANCE_CHECKER(struct xlx_ethlite, XILINX_ETHLITE,
-                         TYPE_XILINX_ETHLITE)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxXpsEthLite, XILINX_ETHLITE)
 
-struct xlx_ethlite
+struct XlnxXpsEthLite
 {
     SysBusDevice parent_obj;
 
@@ -73,7 +72,7 @@ struct xlx_ethlite
     uint32_t regs[R_MAX];
 };
 
-static inline void eth_pulse_irq(struct xlx_ethlite *s)
+static inline void eth_pulse_irq(XlnxXpsEthLite *s)
 {
     /* Only the first gie reg is active.  */
     if (s->regs[R_TX_GIE0] & GIE_GIE) {
@@ -84,7 +83,7 @@ static inline void eth_pulse_irq(struct xlx_ethlite *s)
 static uint64_t
 eth_read(void *opaque, hwaddr addr, unsigned int size)
 {
-    struct xlx_ethlite *s = opaque;
+    XlnxXpsEthLite *s = opaque;
     uint32_t r = 0;
 
     addr >>= 2;
@@ -112,7 +111,7 @@ static void
 eth_write(void *opaque, hwaddr addr,
           uint64_t val64, unsigned int size)
 {
-    struct xlx_ethlite *s = opaque;
+    XlnxXpsEthLite *s = opaque;
     unsigned int base = 0;
     uint32_t value = val64;
 
@@ -172,7 +171,7 @@ static const MemoryRegionOps eth_ops = {
 
 static bool eth_can_rx(NetClientState *nc)
 {
-    struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
+    XlnxXpsEthLite *s = qemu_get_nic_opaque(nc);
     unsigned int rxbase = s->rxbuf * (0x800 / 4);
 
     return !(s->regs[rxbase + R_RX_CTRL0] & CTRL_S);
@@ -180,7 +179,7 @@ static bool eth_can_rx(NetClientState *nc)
 
 static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
 {
-    struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
+    XlnxXpsEthLite *s = qemu_get_nic_opaque(nc);
     unsigned int rxbase = s->rxbuf * (0x800 / 4);
 
     /* DA filter.  */
@@ -210,7 +209,7 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
 
 static void xilinx_ethlite_reset(DeviceState *dev)
 {
-    struct xlx_ethlite *s = XILINX_ETHLITE(dev);
+    XlnxXpsEthLite *s = XILINX_ETHLITE(dev);
 
     s->rxbuf = 0;
 }
@@ -224,7 +223,7 @@ static NetClientInfo net_xilinx_ethlite_info = {
 
 static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
 {
-    struct xlx_ethlite *s = XILINX_ETHLITE(dev);
+    XlnxXpsEthLite *s = XILINX_ETHLITE(dev);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
@@ -235,7 +234,7 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
 
 static void xilinx_ethlite_init(Object *obj)
 {
-    struct xlx_ethlite *s = XILINX_ETHLITE(obj);
+    XlnxXpsEthLite *s = XILINX_ETHLITE(obj);
 
     sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
 
@@ -245,9 +244,9 @@ static void xilinx_ethlite_init(Object *obj)
 }
 
 static const Property xilinx_ethlite_properties[] = {
-    DEFINE_PROP_UINT32("tx-ping-pong", struct xlx_ethlite, c_tx_pingpong, 1),
-    DEFINE_PROP_UINT32("rx-ping-pong", struct xlx_ethlite, c_rx_pingpong, 1),
-    DEFINE_NIC_PROPERTIES(struct xlx_ethlite, conf),
+    DEFINE_PROP_UINT32("tx-ping-pong", XlnxXpsEthLite, c_tx_pingpong, 1),
+    DEFINE_PROP_UINT32("rx-ping-pong", XlnxXpsEthLite, c_rx_pingpong, 1),
+    DEFINE_NIC_PROPERTIES(XlnxXpsEthLite, conf),
 };
 
 static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
@@ -259,17 +258,14 @@ static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
     device_class_set_props(dc, xilinx_ethlite_properties);
 }
 
-static const TypeInfo xilinx_ethlite_info = {
-    .name          = TYPE_XILINX_ETHLITE,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(struct xlx_ethlite),
-    .instance_init = xilinx_ethlite_init,
-    .class_init    = xilinx_ethlite_class_init,
+static const TypeInfo xilinx_ethlite_types[] = {
+    {
+        .name          = TYPE_XILINX_ETHLITE,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(XlnxXpsEthLite),
+        .instance_init = xilinx_ethlite_init,
+        .class_init    = xilinx_ethlite_class_init,
+    },
 };
 
-static void xilinx_ethlite_register_types(void)
-{
-    type_register_static(&xilinx_ethlite_info);
-}
-
-type_init(xilinx_ethlite_register_types)
+DEFINE_TYPES(xilinx_ethlite_types)
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 14/29] hw/net/xilinx_ethlite: Correct maximum RX buffer size
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (12 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 13/29] hw/net/xilinx_ethlite: Update QOM style Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 15/29] hw/net/xilinx_ethlite: Rename rxbuf -> port_index Philippe Mathieu-Daudé
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Edgar E. Iglesias

The current max RX bufsize is set to 0x800. This is
invalid, since it contains the MMIO registers region.
Add the correct definition (valid for both TX & RX,
see datasheet p. 20, Table 11 "XPS Ethernet Lite MAC
Memory Map") and use it.

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20241112181044.92193-6-philmd@linaro.org>
---
 hw/net/xilinx_ethlite.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 330dccb83df..d54f96df243 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -3,6 +3,9 @@
  *
  * Copyright (c) 2009 Edgar E. Iglesias.
  *
+ * DS580: https://docs.amd.com/v/u/en-US/xps_ethernetlite
+ * LogiCORE IP XPS Ethernet Lite Media Access Controller
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -33,6 +36,7 @@
 #include "trace.h"
 
 #define R_TX_BUF0     0
+#define BUFSZ_MAX      0x07e4
 #define R_TX_LEN0     (0x07f4 / 4)
 #define R_TX_GIE0     (0x07f8 / 4)
 #define R_TX_CTRL0    (0x07fc / 4)
@@ -191,7 +195,7 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
         return -1;
     }
 
-    if (size > (R_MAX - R_RX_BUF0 - rxbase) * 4) {
+    if (size >= BUFSZ_MAX) {
         trace_ethlite_pkt_size_too_big(size);
         return -1;
     }
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 15/29] hw/net/xilinx_ethlite: Rename rxbuf -> port_index
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (13 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 14/29] hw/net/xilinx_ethlite: Correct maximum RX buffer size Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 16/29] fw_cfg: Don't set callback_opaque NULL in fw_cfg_modify_bytes_read() Philippe Mathieu-Daudé
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Edgar E. Iglesias

'rxbuf' is the index of the dual port RAM used.
Rename it as 'port_index'.

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20241112181044.92193-8-philmd@linaro.org>
---
 hw/net/xilinx_ethlite.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index d54f96df243..4c0c7fcae3e 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -70,8 +70,7 @@ struct XlnxXpsEthLite
 
     uint32_t c_tx_pingpong;
     uint32_t c_rx_pingpong;
-    unsigned int txbuf;
-    unsigned int rxbuf;
+    unsigned int port_index; /* dual port RAM index */
 
     uint32_t regs[R_MAX];
 };
@@ -176,7 +175,7 @@ static const MemoryRegionOps eth_ops = {
 static bool eth_can_rx(NetClientState *nc)
 {
     XlnxXpsEthLite *s = qemu_get_nic_opaque(nc);
-    unsigned int rxbase = s->rxbuf * (0x800 / 4);
+    unsigned int rxbase = s->port_index * (0x800 / 4);
 
     return !(s->regs[rxbase + R_RX_CTRL0] & CTRL_S);
 }
@@ -184,7 +183,7 @@ static bool eth_can_rx(NetClientState *nc)
 static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
 {
     XlnxXpsEthLite *s = qemu_get_nic_opaque(nc);
-    unsigned int rxbase = s->rxbuf * (0x800 / 4);
+    unsigned int rxbase = s->port_index * (0x800 / 4);
 
     /* DA filter.  */
     if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6))
@@ -207,7 +206,7 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
     }
 
     /* If c_rx_pingpong was set flip buffers.  */
-    s->rxbuf ^= s->c_rx_pingpong;
+    s->port_index ^= s->c_rx_pingpong;
     return size;
 }
 
@@ -215,7 +214,7 @@ static void xilinx_ethlite_reset(DeviceState *dev)
 {
     XlnxXpsEthLite *s = XILINX_ETHLITE(dev);
 
-    s->rxbuf = 0;
+    s->port_index = 0;
 }
 
 static NetClientInfo net_xilinx_ethlite_info = {
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 16/29] fw_cfg: Don't set callback_opaque NULL in fw_cfg_modify_bytes_read()
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (14 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 15/29] hw/net/xilinx_ethlite: Rename rxbuf -> port_index Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 17/29] hw/misc/vmcoreinfo: Declare QOM type using DEFINE_TYPES macro Philippe Mathieu-Daudé
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Shameer Kolothum, chenxiang, Igor Mammedov, Gerd Hoffmann,
	Philippe Mathieu-Daudé

From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>

On arm/virt platform, Chen Xiang reported a Guest crash while
attempting the below steps,

1. Launch the Guest with nvdimm=on
2. Hot-add a NVDIMM dev
3. Reboot
4. Guest boots fine.
5. Reboot again.
6. Guest boot fails.

QEMU_EFI reports the below error:
ProcessCmdAddPointer: invalid pointer value in "etc/acpi/tables"
OnRootBridgesConnected: InstallAcpiTables: Protocol Error

Debugging shows that on first reboot(after hot adding NVDIMM),
Qemu updates the etc/table-loader len,

qemu_ram_resize()
  fw_cfg_modify_file()
     fw_cfg_modify_bytes_read()

And in fw_cfg_modify_bytes_read() we set the "callback_opaque" for
the key entry to NULL. Because of this, on the second reboot,
virt_acpi_build_update() is called with a NULL "build_state" and
returns without updating the ACPI tables. This seems to be
upsetting the firmware.

To fix this, don't change the callback_opaque in fw_cfg_modify_bytes_read().

Fixes: bdbb5b1706d165 ("fw_cfg: add fw_cfg_machine_reset function")
Reported-by: chenxiang <chenxiang66@hisilicon.com>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Message-ID: <20241203131806.37548-1-shameerali.kolothum.thodi@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/nvram/fw_cfg.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index c5537166d97..a757939cfb7 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -729,7 +729,6 @@ static void *fw_cfg_modify_bytes_read(FWCfgState *s, uint16_t key,
     ptr = s->entries[arch][key].data;
     s->entries[arch][key].data = data;
     s->entries[arch][key].len = len;
-    s->entries[arch][key].callback_opaque = NULL;
     s->entries[arch][key].allow_write = false;
 
     return ptr;
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 17/29] hw/misc/vmcoreinfo: Declare QOM type using DEFINE_TYPES macro
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (15 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 16/29] fw_cfg: Don't set callback_opaque NULL in fw_cfg_modify_bytes_read() Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 18/29] hw/misc/vmcoreinfo: Rename opaque pointer as 'opaque' Philippe Mathieu-Daudé
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Daniel P. Berrangé

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20241219153857.57450-2-philmd@linaro.org>
---
 hw/misc/vmcoreinfo.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c
index 0910c64866f..31073c8de2a 100644
--- a/hw/misc/vmcoreinfo.c
+++ b/hw/misc/vmcoreinfo.c
@@ -93,16 +93,13 @@ static void vmcoreinfo_device_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
-static const TypeInfo vmcoreinfo_device_info = {
-    .name          = VMCOREINFO_DEVICE,
-    .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(VMCoreInfoState),
-    .class_init    = vmcoreinfo_device_class_init,
+static const TypeInfo vmcoreinfo_types[] = {
+    {
+        .name           = VMCOREINFO_DEVICE,
+        .parent         = TYPE_DEVICE,
+        .instance_size  = sizeof(VMCoreInfoState),
+        .class_init     = vmcoreinfo_device_class_init,
+    }
 };
 
-static void vmcoreinfo_register_types(void)
-{
-    type_register_static(&vmcoreinfo_device_info);
-}
-
-type_init(vmcoreinfo_register_types)
+DEFINE_TYPES(vmcoreinfo_types)
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 18/29] hw/misc/vmcoreinfo: Rename opaque pointer as 'opaque'
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (16 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 17/29] hw/misc/vmcoreinfo: Declare QOM type using DEFINE_TYPES macro Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 19/29] hw/i386/amd_iommu: Simplify non-KVM checks on XTSup feature Philippe Mathieu-Daudé
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Daniel P. Berrangé

Both QEMUResetHandler and FWCfgWriteCallback take an opaque
pointer argument, no need to cast.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20241219153857.57450-3-philmd@linaro.org>
---
 hw/misc/vmcoreinfo.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c
index 31073c8de2a..b1fcc22e92b 100644
--- a/hw/misc/vmcoreinfo.c
+++ b/hw/misc/vmcoreinfo.c
@@ -18,17 +18,17 @@
 #include "migration/vmstate.h"
 #include "hw/misc/vmcoreinfo.h"
 
-static void fw_cfg_vmci_write(void *dev, off_t offset, size_t len)
+static void fw_cfg_vmci_write(void *opaque, off_t offset, size_t len)
 {
-    VMCoreInfoState *s = VMCOREINFO(dev);
+    VMCoreInfoState *s = opaque;
 
     s->has_vmcoreinfo = offset == 0 && len == sizeof(s->vmcoreinfo)
         && s->vmcoreinfo.guest_format != FW_CFG_VMCOREINFO_FORMAT_NONE;
 }
 
-static void vmcoreinfo_reset(void *dev)
+static void vmcoreinfo_reset(void *opaque)
 {
-    VMCoreInfoState *s = VMCOREINFO(dev);
+    VMCoreInfoState *s = opaque;
 
     s->has_vmcoreinfo = false;
     memset(&s->vmcoreinfo, 0, sizeof(s->vmcoreinfo));
@@ -65,7 +65,7 @@ static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
      * This device requires to register a global reset because it is
      * not plugged to a bus (which, as its QOM parent, would reset it).
      */
-    qemu_register_reset(vmcoreinfo_reset, dev);
+    qemu_register_reset(vmcoreinfo_reset, s);
     vmcoreinfo_state = s;
 }
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 19/29] hw/i386/amd_iommu: Simplify non-KVM checks on XTSup feature
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (17 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 18/29] hw/misc/vmcoreinfo: Rename opaque pointer as 'opaque' Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 20/29] hw/block/virtio-blk: Replaces request free function with g_free Philippe Mathieu-Daudé
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Vasant Hegde

Generic code wanting to access KVM specific methods should
do so being protected by the 'kvm_enabled()' helper.

Doing so avoid link failures when optimization is disabled
(using --enable-debug), see for example commits c04cfb4596a
("hw/i386: fix short-circuit logic with non-optimizing builds")
and 0266aef8cd6 ("amd_iommu: Fix kvm_enable_x2apic link error
with clang in non-KVM builds").

XTSup feature depends on KVM, so protect the whole block
checking the XTSup feature with a check on whether KVM is
enabled.

Since x86_cpus_init() already checks APIC ID > 255 imply
kernel support for irqchip and X2APIC, remove the confuse
and unlikely reachable "AMD IOMMU xtsup=on requires support
on the KVM side" message.

Fix a type in "configuration" in error message.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Message-Id: <20241129155802.35534-1-philmd@linaro.org>
---
 hw/i386/amd_iommu.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index be522b5d7dc..6b13ce894b1 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1652,17 +1652,10 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion_overlap(&s->mr_sys, AMDVI_INT_ADDR_FIRST,
                                         &s->mr_ir, 1);
 
-    /* AMD IOMMU with x2APIC mode requires xtsup=on */
-    if (x86ms->apic_id_limit > 255 && !s->xtsup) {
-        error_report("AMD IOMMU with x2APIC confguration requires xtsup=on");
+    if (kvm_enabled() && x86ms->apic_id_limit > 255 && !s->xtsup) {
+        error_report("AMD IOMMU with x2APIC configuration requires xtsup=on");
         exit(EXIT_FAILURE);
     }
-    if (s->xtsup) {
-        if (kvm_irqchip_is_split() && !kvm_enable_x2apic()) {
-            error_report("AMD IOMMU xtsup=on requires support on the KVM side");
-            exit(EXIT_FAILURE);
-        }
-    }
 
     pci_setup_iommu(bus, &amdvi_iommu_ops, s);
     amdvi_init(s);
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 20/29] hw/block/virtio-blk: Replaces request free function with g_free
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (18 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 19/29] hw/i386/amd_iommu: Simplify non-KVM checks on XTSup feature Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 21/29] hw/usb/hcd-xhci-pci: Move msi/msix properties from NEC to superclass Philippe Mathieu-Daudé
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

The virtio_blk_free_request() function has been a 1-liner forwarding
to g_free() for a while now. We may as well call g_free on the request
pointer directly.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Tested-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-ID: <20241223221645.29911-14-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/block/virtio-blk.c | 43 +++++++++++++++++++------------------------
 1 file changed, 19 insertions(+), 24 deletions(-)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 8806c03f7c6..e0acce89e1e 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -50,11 +50,6 @@ static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
     req->mr_next = NULL;
 }
 
-static void virtio_blk_free_request(VirtIOBlockReq *req)
-{
-    g_free(req);
-}
-
 static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
 {
     VirtIOBlock *s = req->dev;
@@ -93,7 +88,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
         if (acct_failed) {
             block_acct_failed(blk_get_stats(s->blk), &req->acct);
         }
-        virtio_blk_free_request(req);
+        g_free(req);
     }
 
     blk_error_action(s->blk, action, is_read, error);
@@ -136,7 +131,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
 
         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
         block_acct_done(blk_get_stats(s->blk), &req->acct);
-        virtio_blk_free_request(req);
+        g_free(req);
     }
 }
 
@@ -151,7 +146,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
 
     virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
     block_acct_done(blk_get_stats(s->blk), &req->acct);
-    virtio_blk_free_request(req);
+    g_free(req);
 }
 
 static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
@@ -169,7 +164,7 @@ static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
     if (is_write_zeroes) {
         block_acct_done(blk_get_stats(s->blk), &req->acct);
     }
-    virtio_blk_free_request(req);
+    g_free(req);
 }
 
 static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s, VirtQueue *vq)
@@ -214,7 +209,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 
 fail:
     virtio_blk_req_complete(req, status);
-    virtio_blk_free_request(req);
+    g_free(req);
 }
 
 static inline void submit_requests(VirtIOBlock *s, MultiReqBuffer *mrb,
@@ -612,7 +607,7 @@ static void virtio_blk_zone_report_complete(void *opaque, int ret)
 
 out:
     virtio_blk_req_complete(req, err_status);
-    virtio_blk_free_request(req);
+    g_free(req);
     g_free(data->zone_report_data.zones);
     g_free(data);
 }
@@ -661,7 +656,7 @@ static void virtio_blk_handle_zone_report(VirtIOBlockReq *req,
     return;
 out:
     virtio_blk_req_complete(req, err_status);
-    virtio_blk_free_request(req);
+    g_free(req);
 }
 
 static void virtio_blk_zone_mgmt_complete(void *opaque, int ret)
@@ -677,7 +672,7 @@ static void virtio_blk_zone_mgmt_complete(void *opaque, int ret)
     }
 
     virtio_blk_req_complete(req, err_status);
-    virtio_blk_free_request(req);
+    g_free(req);
 }
 
 static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
@@ -719,7 +714,7 @@ static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
     return 0;
 out:
     virtio_blk_req_complete(req, err_status);
-    virtio_blk_free_request(req);
+    g_free(req);
     return err_status;
 }
 
@@ -750,7 +745,7 @@ static void virtio_blk_zone_append_complete(void *opaque, int ret)
 
 out:
     virtio_blk_req_complete(req, err_status);
-    virtio_blk_free_request(req);
+    g_free(req);
     g_free(data);
 }
 
@@ -788,7 +783,7 @@ static int virtio_blk_handle_zone_append(VirtIOBlockReq *req,
 
 out:
     virtio_blk_req_complete(req, err_status);
-    virtio_blk_free_request(req);
+    g_free(req);
     return err_status;
 }
 
@@ -855,7 +850,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
             virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
             block_acct_invalid(blk_get_stats(s->blk),
                                is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
-            virtio_blk_free_request(req);
+            g_free(req);
             return 0;
         }
 
@@ -911,7 +906,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
                               VIRTIO_BLK_ID_BYTES));
         iov_from_buf(in_iov, in_num, 0, serial, size);
         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
-        virtio_blk_free_request(req);
+        g_free(req);
         break;
     }
     case VIRTIO_BLK_T_ZONE_APPEND & ~VIRTIO_BLK_T_OUT:
@@ -943,7 +938,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
         if (unlikely(!(type & VIRTIO_BLK_T_OUT) ||
                      out_len > sizeof(dwz_hdr))) {
             virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
-            virtio_blk_free_request(req);
+            g_free(req);
             return 0;
         }
 
@@ -960,14 +955,14 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
                                                             is_write_zeroes);
         if (err_status != VIRTIO_BLK_S_OK) {
             virtio_blk_req_complete(req, err_status);
-            virtio_blk_free_request(req);
+            g_free(req);
         }
 
         break;
     }
     default:
         virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
-        virtio_blk_free_request(req);
+        g_free(req);
     }
     return 0;
 }
@@ -988,7 +983,7 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
         while ((req = virtio_blk_get_request(s, vq))) {
             if (virtio_blk_handle_request(req, &mrb)) {
                 virtqueue_detach_element(req->vq, &req->elem, 0);
-                virtio_blk_free_request(req);
+                g_free(req);
                 break;
             }
         }
@@ -1038,7 +1033,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
             while (req) {
                 next = req->next;
                 virtqueue_detach_element(req->vq, &req->elem, 0);
-                virtio_blk_free_request(req);
+                g_free(req);
                 req = next;
             }
             break;
@@ -1121,7 +1116,7 @@ static void virtio_blk_reset(VirtIODevice *vdev)
             /* No other threads can access req->vq here */
             virtqueue_detach_element(req->vq, &req->elem, 0);
 
-            virtio_blk_free_request(req);
+            g_free(req);
         }
     }
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 21/29] hw/usb/hcd-xhci-pci: Move msi/msix properties from NEC to superclass
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (19 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 20/29] hw/block/virtio-blk: Replaces request free function with g_free Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 22/29] hw/usb/hcd-xhci: Unimplemented/guest error logging for port MMIO Philippe Mathieu-Daudé
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Phil Dennis-Jordan, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

The NEC XHCI controller exposes the underlying PCI device's msi and
msix properties, but the superclass and thus the qemu-xhci device do
not. There does not seem to be any obvious reason for this limitation.
This change moves these properties to the superclass so they are
exposed by both PCI XHCI device variants.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241227121336.25838-3-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/usb/hcd-xhci-nec.c | 2 --
 hw/usb/hcd-xhci-pci.c | 6 ++++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/usb/hcd-xhci-nec.c b/hw/usb/hcd-xhci-nec.c
index b1df95b52a5..1df518baf59 100644
--- a/hw/usb/hcd-xhci-nec.c
+++ b/hw/usb/hcd-xhci-nec.c
@@ -37,8 +37,6 @@ struct XHCINecState {
 };
 
 static const Property nec_xhci_properties[] = {
-    DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
-    DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO),
     DEFINE_PROP_UINT32("intrs", XHCINecState, intrs, XHCI_MAXINTRS),
     DEFINE_PROP_UINT32("slots", XHCINecState, slots, XHCI_MAXSLOTS),
 };
diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
index e110840c7a0..a069b423388 100644
--- a/hw/usb/hcd-xhci-pci.c
+++ b/hw/usb/hcd-xhci-pci.c
@@ -197,6 +197,11 @@ static void xhci_instance_init(Object *obj)
     qdev_alias_all_properties(DEVICE(&s->xhci), obj);
 }
 
+static const Property xhci_pci_properties[] = {
+    DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
+    DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO),
+};
+
 static void xhci_class_init(ObjectClass *klass, void *data)
 {
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@@ -208,6 +213,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
     k->realize      = usb_xhci_pci_realize;
     k->exit         = usb_xhci_pci_exit;
     k->class_id     = PCI_CLASS_SERIAL_USB;
+    device_class_set_props(dc, xhci_pci_properties);
 }
 
 static const TypeInfo xhci_pci_info = {
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 22/29] hw/usb/hcd-xhci: Unimplemented/guest error logging for port MMIO
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (20 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 21/29] hw/usb/hcd-xhci-pci: Move msi/msix properties from NEC to superclass Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling Philippe Mathieu-Daudé
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Phil Dennis-Jordan, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

The XHCI device code uses tracing rather than logging on various code
paths that are so far unimplemented. In some cases, these code paths
actually indicate faulty guest software. This patch switches instances
in the read and write handlers for the port MMIO region to use
qemu_log_mask() with LOG_UNIMP or LOG_GUEST_ERROR, as appropriate in
each case.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241227121336.25838-5-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/usb/hcd-xhci.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 3719c0f190d..7dc0994c89c 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2810,9 +2810,15 @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size)
     case 0x08: /* PORTLI */
         ret = 0;
         break;
-    case 0x0c: /* reserved */
+    case 0x0c: /* PORTHLPMC */
+        ret = 0;
+        qemu_log_mask(LOG_UNIMP, "%s: read from port register PORTHLPMC",
+                      __func__);
+        break;
     default:
-        trace_usb_xhci_unimplemented("port read", reg);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: read from port offset 0x%" HWADDR_PRIx,
+                      __func__, reg);
         ret = 0;
     }
 
@@ -2881,9 +2887,22 @@ static void xhci_port_write(void *ptr, hwaddr reg,
         }
         break;
     case 0x04: /* PORTPMSC */
+    case 0x0c: /* PORTHLPMC */
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: write 0x%" PRIx64
+                      " (%u bytes) to port register at offset 0x%" HWADDR_PRIx,
+                      __func__, val, size, reg);
+        break;
     case 0x08: /* PORTLI */
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Write to read-only PORTLI register",
+                      __func__);
+        break;
     default:
-        trace_usb_xhci_unimplemented("port write", reg);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: write 0x%" PRIx64 " (%u bytes) to unknown port "
+                      "register at offset 0x%" HWADDR_PRIx,
+                      __func__, val, size, reg);
+        break;
     }
 }
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (21 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 22/29] hw/usb/hcd-xhci: Unimplemented/guest error logging for port MMIO Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2025-01-08 13:51   ` David Woodhouse
  2024-12-31 20:22 ` [PULL 24/29] hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework support Philippe Mathieu-Daudé
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

macOS's Cocoa event handling must be done on the initial (main) thread
of the process. Furthermore, if library or application code uses
libdispatch, the main dispatch queue must be handling events on the main
thread as well.

So far, this has affected Qemu in both the Cocoa and SDL UIs, although
in different ways: the Cocoa UI replaces the default qemu_main function
with one that spins Qemu's internal main event loop off onto a
background thread. SDL (which uses Cocoa internally) on the other hand
uses a polling approach within Qemu's main event loop. Events are
polled during the SDL UI's dpy_refresh callback, which happens to run
on the main thread by default.

As UIs are mutually exclusive, this works OK as long as nothing else
needs platform-native event handling. In the next patch, a new device is
introduced based on the ParavirtualizedGraphics.framework in macOS.
This uses libdispatch internally, and only works when events are being
handled on the main runloop. With the current system, it works when
using either the Cocoa or the SDL UI. However, it does not when running
headless. Moreover, any attempt to install a similar scheme to the
Cocoa UI's main thread replacement fails when combined with the SDL
UI.

This change tidies up main thread management to be more flexible.

 * The qemu_main global function pointer is a custom function for the
   main thread, and it may now be NULL. When it is, the main thread
   runs the main Qemu loop. This represents the traditional setup.
 * When non-null, spawning the main Qemu event loop on a separate
   thread is now done centrally rather than inside the Cocoa UI code.
 * For most platforms, qemu_main is indeed NULL by default, but on
   Darwin, it defaults to a function that runs the CFRunLoop.
 * The Cocoa UI sets qemu_main to a function which runs the
   NSApplication event handling runloop, as is usual for a Cocoa app.
 * The SDL UI overrides the qemu_main function to NULL, thus
   specifying that Qemu's main loop must run on the main
   thread.
 * The GTK UI also overrides the qemu_main function to NULL.
 * For other UIs, or in the absence of UIs, the platform's default
   behaviour is followed.

This means that on macOS, the platform's runloop events are always
handled, regardless of chosen UI. The new PV graphics device will
thus work in all configurations. There is no functional change on other
operating systems.

Implementing this via a global function pointer variable is a bit
ugly, but it's probably worth investigating the existing UI thread rule
violations in the SDL (e.g. #2537) and GTK+ back-ends. Fixing those
issues might precipitate requirements similar but not identical to those
of the Cocoa UI; hopefully we'll see some kind of pattern emerge, which
can then be used as a basis for an overhaul. (In fact, it may turn
out to be simplest to split the UI/native platform event thread from the
QEMU main event loop on all platforms, with any UI or even none at all.)

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Tested-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-ID: <20241223221645.29911-2-phil@philjordan.eu>
[PMD: Declare 'qemu_main' symbol in tests/qtest/fuzz/fuzz.c,
      add missing g_assert_not_reached() call in main()]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/qemu-main.h     | 14 ++++++++++-
 system/main.c           | 38 ++++++++++++++++++++++++++---
 tests/qtest/fuzz/fuzz.c |  1 +
 ui/gtk.c                |  4 +++
 ui/sdl2.c               |  4 +++
 ui/cocoa.m              | 54 ++++++++++-------------------------------
 6 files changed, 69 insertions(+), 46 deletions(-)

diff --git a/include/qemu-main.h b/include/qemu-main.h
index 940960a7dbc..2ee83bedff3 100644
--- a/include/qemu-main.h
+++ b/include/qemu-main.h
@@ -5,7 +5,19 @@
 #ifndef QEMU_MAIN_H
 #define QEMU_MAIN_H
 
-int qemu_default_main(void);
+/*
+ * The function to run on the main (initial) thread of the process.
+ * NULL means QEMU's main event loop.
+ * When non-NULL, QEMU's main event loop will run on a purposely created
+ * thread, after which the provided function pointer will be invoked on
+ * the initial thread.
+ * This is useful on platforms which treat the main thread as special
+ * (macOS/Darwin) and/or require all UI API calls to occur from the main
+ * thread. Those platforms can initialise it to a specific function,
+ * while UI implementations may reset it to NULL during their init if they
+ * will handle system and UI events on the main thread via QEMU's own main
+ * event loop.
+ */
 extern int (*qemu_main)(void);
 
 #endif /* QEMU_MAIN_H */
diff --git a/system/main.c b/system/main.c
index 4923520741c..ecb12fd397c 100644
--- a/system/main.c
+++ b/system/main.c
@@ -24,26 +24,56 @@
 
 #include "qemu/osdep.h"
 #include "qemu-main.h"
+#include "qemu/main-loop.h"
 #include "system/system.h"
 
 #ifdef CONFIG_SDL
+/*
+ * SDL insists on wrapping the main() function with its own implementation on
+ * some platforms; it does so via a macro that renames our main function, so
+ * <SDL.h> must be #included here even with no SDL code called from this file.
+ */
 #include <SDL.h>
 #endif
 
-int qemu_default_main(void)
+#ifdef CONFIG_DARWIN
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+static void *qemu_default_main(void *opaque)
 {
     int status;
 
+    bql_lock();
     status = qemu_main_loop();
     qemu_cleanup(status);
+    bql_unlock();
 
-    return status;
+    exit(status);
 }
 
-int (*qemu_main)(void) = qemu_default_main;
+int (*qemu_main)(void);
+
+#ifdef CONFIG_DARWIN
+static int os_darwin_cfrunloop_main(void)
+{
+    CFRunLoopRun();
+    g_assert_not_reached();
+}
+int (*qemu_main)(void) = os_darwin_cfrunloop_main;
+#endif
 
 int main(int argc, char **argv)
 {
     qemu_init(argc, argv);
-    return qemu_main();
+    bql_unlock();
+    if (qemu_main) {
+        QemuThread main_loop_thread;
+        qemu_thread_create(&main_loop_thread, "qemu_main",
+                           qemu_default_main, NULL, QEMU_THREAD_DETACHED);
+        return qemu_main();
+    } else {
+        qemu_default_main(NULL);
+        g_assert_not_reached();
+    }
 }
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index 8274000bd55..ca248a51a6c 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -41,6 +41,7 @@ static FuzzTargetList *fuzz_target_list;
 static FuzzTarget *fuzz_target;
 static QTestState *fuzz_qts;
 
+int (*qemu_main)(void);
 
 
 void flush_events(QTestState *s)
diff --git a/ui/gtk.c b/ui/gtk.c
index 0d38c070e40..c0237431489 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -38,6 +38,7 @@
 #include "qemu/cutils.h"
 #include "qemu/error-report.h"
 #include "qemu/main-loop.h"
+#include "qemu-main.h"
 
 #include "ui/console.h"
 #include "ui/gtk.h"
@@ -2485,6 +2486,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
 #ifdef CONFIG_GTK_CLIPBOARD
     gd_clipboard_init(s);
 #endif /* CONFIG_GTK_CLIPBOARD */
+
+    /* GTK's event polling must happen on the main thread. */
+    qemu_main = NULL;
 }
 
 static void early_gtk_display_init(DisplayOptions *opts)
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 1fb72f67a6f..445eb1dd9f9 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -34,6 +34,7 @@
 #include "system/system.h"
 #include "ui/win32-kbd-hook.h"
 #include "qemu/log.h"
+#include "qemu-main.h"
 
 static int sdl2_num_outputs;
 static struct sdl2_console *sdl2_console;
@@ -965,6 +966,9 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
     }
 
     atexit(sdl_cleanup);
+
+    /* SDL's event polling (in dpy_refresh) must happen on the main thread. */
+    qemu_main = NULL;
 }
 
 static QemuDisplay qemu_display_sdl2 = {
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 3a88535374d..23b7a736d70 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -73,6 +73,8 @@
     int height;
 } QEMUScreen;
 
+@class QemuCocoaPasteboardTypeOwner;
+
 static void cocoa_update(DisplayChangeListener *dcl,
                          int x, int y, int w, int h);
 
@@ -107,6 +109,7 @@ static void cocoa_switch(DisplayChangeListener *dcl,
 static NSInteger cbchangecount = -1;
 static QemuClipboardInfo *cbinfo;
 static QemuEvent cbevent;
+static QemuCocoaPasteboardTypeOwner *cbowner;
 
 // Utility functions to run specified code block with the BQL held
 typedef void (^CodeBlock)(void);
@@ -1326,8 +1329,10 @@ - (void) dealloc
 {
     COCOA_DEBUG("QemuCocoaAppController: dealloc\n");
 
-    if (cocoaView)
-        [cocoaView release];
+    [cocoaView release];
+    [cbowner release];
+    cbowner = nil;
+
     [super dealloc];
 }
 
@@ -1943,8 +1948,6 @@ - (void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSPasteboardType)t
 
 @end
 
-static QemuCocoaPasteboardTypeOwner *cbowner;
-
 static void cocoa_clipboard_notify(Notifier *notifier, void *data);
 static void cocoa_clipboard_request(QemuClipboardInfo *info,
                                     QemuClipboardType type);
@@ -2007,43 +2010,8 @@ static void cocoa_clipboard_request(QemuClipboardInfo *info,
     }
 }
 
-/*
- * The startup process for the OSX/Cocoa UI is complicated, because
- * OSX insists that the UI runs on the initial main thread, and so we
- * need to start a second thread which runs the qemu_default_main():
- * in main():
- *  in cocoa_display_init():
- *   assign cocoa_main to qemu_main
- *   create application, menus, etc
- *  in cocoa_main():
- *   create qemu-main thread
- *   enter OSX run loop
- */
-
-static void *call_qemu_main(void *opaque)
-{
-    int status;
-
-    COCOA_DEBUG("Second thread: calling qemu_default_main()\n");
-    bql_lock();
-    status = qemu_default_main();
-    bql_unlock();
-    COCOA_DEBUG("Second thread: qemu_default_main() returned, exiting\n");
-    [cbowner release];
-    exit(status);
-}
-
 static int cocoa_main(void)
 {
-    QemuThread thread;
-
-    COCOA_DEBUG("Entered %s()\n", __func__);
-
-    bql_unlock();
-    qemu_thread_create(&thread, "qemu_main", call_qemu_main,
-                       NULL, QEMU_THREAD_DETACHED);
-
-    // Start the main event loop
     COCOA_DEBUG("Main thread: entering OSX run loop\n");
     [NSApp run];
     COCOA_DEBUG("Main thread: left OSX run loop, which should never happen\n");
@@ -2125,8 +2093,6 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
 
     COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
 
-    qemu_main = cocoa_main;
-
     // Pull this console process up to being a fully-fledged graphical
     // app with a menubar and Dock icon
     ProcessSerialNumber psn = { 0, kCurrentProcess };
@@ -2190,6 +2156,12 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
     qemu_clipboard_peer_register(&cbpeer);
 
     [pool release];
+
+    /*
+     * The Cocoa UI will run the NSApplication runloop on the main thread
+     * rather than the default Core Foundation one.
+     */
+    qemu_main = cocoa_main;
 }
 
 static QemuDisplay qemu_display_cocoa = {
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 24/29] hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework support
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (22 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 25/29] hw/display/apple-gfx: Adds PCI implementation Philippe Mathieu-Daudé
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Phil Dennis-Jordan, Alexander Graf, Akihiko Odaki,
	Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

MacOS provides a framework (library) that allows any vmm to implement a
paravirtualized 3d graphics passthrough to the host metal stack called
ParavirtualizedGraphics.Framework (PVG). The library abstracts away
almost every aspect of the paravirtualized device model and only provides
and receives callbacks on MMIO access as well as to share memory address
space between the VM and PVG.

This patch implements a QEMU device that drives PVG for the VMApple
variant of it.

Signed-off-by: Alexander Graf <graf@amazon.com>
Co-authored-by: Alexander Graf <graf@amazon.com>

Subsequent changes:

 * Cherry-pick/rebase conflict fixes, API use updates.
 * Moved from hw/vmapple/ (useful outside that machine type)
 * Overhaul of threading model, many thread safety improvements.
 * Asynchronous rendering.
 * Memory and object lifetime fixes.
 * Refactoring to split generic and (vmapple) MMIO variant specific
   code.

Implementation wise, most of the complexity lies in the differing threading
models of ParavirtualizedGraphics.framework, which uses libdispatch and
internal locks, versus QEMU, which heavily uses the BQL, especially during
memory-mapped device I/O. Great care has therefore been taken to prevent
deadlocks by never calling into PVG methods while holding the BQL, and
similarly never acquiring the BQL in a callback from PVG. Different strategies
have been used (libdispatch, blocking and non-blocking BHs, RCU, etc.)
depending on the specific requirements at each framework entry and exit point.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Tested-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-ID: <20241223221645.29911-3-phil@philjordan.eu>
[PMD: Re-ordered imported headers, style fixups]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 meson.build                 |   4 +
 hw/display/apple-gfx.h      |  63 +++
 hw/display/Kconfig          |   9 +
 hw/display/apple-gfx-mmio.m | 278 +++++++++++++
 hw/display/apple-gfx.m      | 783 ++++++++++++++++++++++++++++++++++++
 hw/display/meson.build      |   6 +
 hw/display/trace-events     |  28 ++
 7 files changed, 1171 insertions(+)
 create mode 100644 hw/display/apple-gfx.h
 create mode 100644 hw/display/apple-gfx-mmio.m
 create mode 100644 hw/display/apple-gfx.m

diff --git a/meson.build b/meson.build
index f4109cd3cae..e62251c7ca3 100644
--- a/meson.build
+++ b/meson.build
@@ -817,6 +817,8 @@ socket = []
 version_res = []
 coref = []
 iokit = []
+pvg = not_found
+metal = []
 emulator_link_args = []
 midl = not_found
 widl = not_found
@@ -838,6 +840,8 @@ elif host_os == 'darwin'
   coref = dependency('appleframeworks', modules: 'CoreFoundation')
   iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
   host_dsosuf = '.dylib'
+  pvg = dependency('appleframeworks', modules: 'ParavirtualizedGraphics')
+  metal = dependency('appleframeworks', modules: 'Metal')
 elif host_os == 'sunos'
   socket = [cc.find_library('socket'),
             cc.find_library('nsl'),
diff --git a/hw/display/apple-gfx.h b/hw/display/apple-gfx.h
new file mode 100644
index 00000000000..4cd4163f223
--- /dev/null
+++ b/hw/display/apple-gfx.h
@@ -0,0 +1,63 @@
+/*
+ * Data structures and functions shared between variants of the macOS
+ * ParavirtualizedGraphics.framework based apple-gfx display adapter.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_APPLE_GFX_H
+#define QEMU_APPLE_GFX_H
+
+#include "qemu/queue.h"
+#include "exec/memory.h"
+#include "hw/qdev-properties.h"
+#include "ui/surface.h"
+
+#define TYPE_APPLE_GFX_MMIO         "apple-gfx-mmio"
+
+@class PGDeviceDescriptor;
+@protocol PGDevice;
+@protocol PGDisplay;
+@protocol MTLDevice;
+@protocol MTLTexture;
+@protocol MTLCommandQueue;
+
+typedef QTAILQ_HEAD(, PGTask_s) PGTaskList;
+
+typedef struct AppleGFXState {
+    /* Initialised on init/realize() */
+    MemoryRegion iomem_gfx;
+    id<PGDevice> pgdev;
+    id<PGDisplay> pgdisp;
+    QemuConsole *con;
+    id<MTLDevice> mtl;
+    id<MTLCommandQueue> mtl_queue;
+
+    /* List `tasks` is protected by task_mutex */
+    QemuMutex task_mutex;
+    PGTaskList tasks;
+
+    /* Mutable state (BQL protected) */
+    QEMUCursor *cursor;
+    DisplaySurface *surface;
+    id<MTLTexture> texture;
+    int8_t pending_frames; /* # guest frames in the rendering pipeline */
+    bool gfx_update_requested; /* QEMU display system wants a new frame */
+    bool new_frame_ready; /* Guest has rendered a frame, ready to be used */
+    bool using_managed_texture_storage;
+    uint32_t rendering_frame_width;
+    uint32_t rendering_frame_height;
+
+    /* Mutable state (atomic) */
+    bool cursor_show;
+} AppleGFXState;
+
+void apple_gfx_common_init(Object *obj, AppleGFXState *s, const char* obj_name);
+bool apple_gfx_common_realize(AppleGFXState *s, DeviceState *dev,
+                              PGDeviceDescriptor *desc, Error **errp);
+void *apple_gfx_host_ptr_for_gpa_range(uint64_t guest_physical,
+                                       uint64_t length, bool read_only,
+                                       MemoryRegion **mapping_in_region);
+
+#endif
+
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index 2250c740078..6a9b7b19ada 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -140,3 +140,12 @@ config XLNX_DISPLAYPORT
 
 config DM163
     bool
+
+config MAC_PVG
+    bool
+    default y
+
+config MAC_PVG_MMIO
+    bool
+    depends on MAC_PVG && AARCH64
+
diff --git a/hw/display/apple-gfx-mmio.m b/hw/display/apple-gfx-mmio.m
new file mode 100644
index 00000000000..5a489d2d44f
--- /dev/null
+++ b/hw/display/apple-gfx-mmio.m
@@ -0,0 +1,278 @@
+/*
+ * QEMU Apple ParavirtualizedGraphics.framework device, MMIO (arm64) variant
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
+ * which implements 3d graphics passthrough to the host as well as a
+ * proprietary guest communication channel to drive it. This device model
+ * implements support to drive that library from within QEMU as an MMIO-based
+ * system device for macOS on arm64 VMs.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "block/aio-wait.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "apple-gfx.h"
+#include "trace.h"
+
+#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
+
+OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXMMIOState, APPLE_GFX_MMIO)
+
+/*
+ * ParavirtualizedGraphics.Framework only ships header files for the PCI
+ * variant which does not include IOSFC descriptors and host devices. We add
+ * their definitions here so that we can also work with the ARM version.
+ */
+typedef bool(^IOSFCRaiseInterrupt)(uint32_t vector);
+typedef bool(^IOSFCUnmapMemory)(void *, void *, void *, void *, void *, void *);
+typedef bool(^IOSFCMapMemory)(uint64_t phys, uint64_t len, bool ro, void **va,
+                              void *, void *);
+
+@interface PGDeviceDescriptor (IOSurfaceMapper)
+@property (readwrite, nonatomic) bool usingIOSurfaceMapper;
+@end
+
+@interface PGIOSurfaceHostDeviceDescriptor : NSObject
+-(PGIOSurfaceHostDeviceDescriptor *)init;
+@property (readwrite, nonatomic, copy, nullable) IOSFCMapMemory mapMemory;
+@property (readwrite, nonatomic, copy, nullable) IOSFCUnmapMemory unmapMemory;
+@property (readwrite, nonatomic, copy, nullable) IOSFCRaiseInterrupt raiseInterrupt;
+@end
+
+@interface PGIOSurfaceHostDevice : NSObject
+-(instancetype)initWithDescriptor:(PGIOSurfaceHostDeviceDescriptor *)desc;
+-(uint32_t)mmioReadAtOffset:(size_t)offset;
+-(void)mmioWriteAtOffset:(size_t)offset value:(uint32_t)value;
+@end
+
+struct AppleGFXMapSurfaceMemoryJob;
+struct AppleGFXMMIOState {
+    SysBusDevice parent_obj;
+
+    AppleGFXState common;
+
+    qemu_irq irq_gfx;
+    qemu_irq irq_iosfc;
+    MemoryRegion iomem_iosfc;
+    PGIOSurfaceHostDevice *pgiosfc;
+};
+
+typedef struct AppleGFXMMIOJob {
+    AppleGFXMMIOState *state;
+    uint64_t offset;
+    uint64_t value;
+    bool completed;
+} AppleGFXMMIOJob;
+
+static void iosfc_do_read(void *opaque)
+{
+    AppleGFXMMIOJob *job = opaque;
+    job->value = [job->state->pgiosfc mmioReadAtOffset:job->offset];
+    qatomic_set(&job->completed, true);
+    aio_wait_kick();
+}
+
+static uint64_t iosfc_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AppleGFXMMIOJob job = {
+        .state = opaque,
+        .offset = offset,
+        .completed = false,
+    };
+    dispatch_queue_t queue =
+        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+
+    dispatch_async_f(queue, &job, iosfc_do_read);
+    AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));
+
+    trace_apple_gfx_mmio_iosfc_read(offset, job.value);
+    return job.value;
+}
+
+static void iosfc_do_write(void *opaque)
+{
+    AppleGFXMMIOJob *job = opaque;
+    [job->state->pgiosfc mmioWriteAtOffset:job->offset value:job->value];
+    qatomic_set(&job->completed, true);
+    aio_wait_kick();
+}
+
+static void iosfc_write(void *opaque, hwaddr offset, uint64_t val,
+                        unsigned size)
+{
+    AppleGFXMMIOJob job = {
+        .state = opaque,
+        .offset = offset,
+        .value = val,
+        .completed = false,
+    };
+    dispatch_queue_t queue =
+        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+
+    dispatch_async_f(queue, &job, iosfc_do_write);
+    AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));
+
+    trace_apple_gfx_mmio_iosfc_write(offset, val);
+}
+
+static const MemoryRegionOps apple_iosfc_ops = {
+    .read = iosfc_read,
+    .write = iosfc_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+};
+
+static void raise_irq_bh(void *opaque)
+{
+    qemu_irq *irq = opaque;
+
+    qemu_irq_pulse(*irq);
+}
+
+static void *apple_gfx_mmio_map_surface_memory(uint64_t guest_physical_address,
+                                               uint64_t length, bool read_only)
+{
+    void *mem;
+    MemoryRegion *region = NULL;
+
+    RCU_READ_LOCK_GUARD();
+    mem = apple_gfx_host_ptr_for_gpa_range(guest_physical_address,
+                                           length, read_only, &region);
+    if (mem) {
+        memory_region_ref(region);
+    }
+    return mem;
+}
+
+static bool apple_gfx_mmio_unmap_surface_memory(void *ptr)
+{
+    MemoryRegion *region;
+    ram_addr_t offset = 0;
+
+    RCU_READ_LOCK_GUARD();
+    region = memory_region_from_host(ptr, &offset);
+    if (!region) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: memory at %p to be unmapped not found.\n",
+                      __func__, ptr);
+        return false;
+    }
+
+    trace_apple_gfx_iosfc_unmap_memory_region(ptr, region);
+    memory_region_unref(region);
+    return true;
+}
+
+static PGIOSurfaceHostDevice *apple_gfx_prepare_iosurface_host_device(
+    AppleGFXMMIOState *s)
+{
+    PGIOSurfaceHostDeviceDescriptor *iosfc_desc =
+        [PGIOSurfaceHostDeviceDescriptor new];
+    PGIOSurfaceHostDevice *iosfc_host_dev;
+
+    iosfc_desc.mapMemory =
+        ^bool(uint64_t phys, uint64_t len, bool ro, void **va, void *e, void *f) {
+            *va = apple_gfx_mmio_map_surface_memory(phys, len, ro);
+
+            trace_apple_gfx_iosfc_map_memory(phys, len, ro, va, e, f, *va);
+
+            return *va != NULL;
+        };
+
+    iosfc_desc.unmapMemory =
+        ^bool(void *va, void *b, void *c, void *d, void *e, void *f) {
+            return apple_gfx_mmio_unmap_surface_memory(va);
+        };
+
+    iosfc_desc.raiseInterrupt = ^bool(uint32_t vector) {
+        trace_apple_gfx_iosfc_raise_irq(vector);
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                raise_irq_bh, &s->irq_iosfc);
+        return true;
+    };
+
+    iosfc_host_dev =
+        [[PGIOSurfaceHostDevice alloc] initWithDescriptor:iosfc_desc];
+    [iosfc_desc release];
+    return iosfc_host_dev;
+}
+
+static void apple_gfx_mmio_realize(DeviceState *dev, Error **errp)
+{
+    @autoreleasepool {
+        AppleGFXMMIOState *s = APPLE_GFX_MMIO(dev);
+        PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
+
+        desc.raiseInterrupt = ^(uint32_t vector) {
+            trace_apple_gfx_raise_irq(vector);
+            aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                    raise_irq_bh, &s->irq_gfx);
+        };
+
+        desc.usingIOSurfaceMapper = true;
+        s->pgiosfc = apple_gfx_prepare_iosurface_host_device(s);
+
+        if (!apple_gfx_common_realize(&s->common, dev, desc, errp)) {
+            [s->pgiosfc release];
+            s->pgiosfc = nil;
+        }
+
+        [desc release];
+        desc = nil;
+    }
+}
+
+static void apple_gfx_mmio_init(Object *obj)
+{
+    AppleGFXMMIOState *s = APPLE_GFX_MMIO(obj);
+
+    apple_gfx_common_init(obj, &s->common, TYPE_APPLE_GFX_MMIO);
+
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->common.iomem_gfx);
+    memory_region_init_io(&s->iomem_iosfc, obj, &apple_iosfc_ops, s,
+                          TYPE_APPLE_GFX_MMIO, 0x10000);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem_iosfc);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_gfx);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_iosfc);
+}
+
+static void apple_gfx_mmio_reset(Object *obj, ResetType type)
+{
+    AppleGFXMMIOState *s = APPLE_GFX_MMIO(obj);
+    [s->common.pgdev reset];
+}
+
+
+static void apple_gfx_mmio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.hold = apple_gfx_mmio_reset;
+    dc->hotpluggable = false;
+    dc->realize = apple_gfx_mmio_realize;
+}
+
+static const TypeInfo apple_gfx_mmio_types[] = {
+    {
+        .name          = TYPE_APPLE_GFX_MMIO,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(AppleGFXMMIOState),
+        .class_init    = apple_gfx_mmio_class_init,
+        .instance_init = apple_gfx_mmio_init,
+    }
+};
+DEFINE_TYPES(apple_gfx_mmio_types)
diff --git a/hw/display/apple-gfx.m b/hw/display/apple-gfx.m
new file mode 100644
index 00000000000..59299e339d4
--- /dev/null
+++ b/hw/display/apple-gfx.m
@@ -0,0 +1,783 @@
+/*
+ * QEMU Apple ParavirtualizedGraphics.framework device
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
+ * which implements 3d graphics passthrough to the host as well as a
+ * proprietary guest communication channel to drive it. This device model
+ * implements support to drive that library from within QEMU.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/lockable.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
+#include "block/aio-wait.h"
+#include "exec/address-spaces.h"
+#include "system/dma.h"
+#include "migration/blocker.h"
+#include "ui/console.h"
+#include "apple-gfx.h"
+#include "trace.h"
+
+#include <mach/mach.h>
+#include <mach/mach_vm.h>
+#include <dispatch/dispatch.h>
+
+#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
+
+static const PGDisplayCoord_t apple_gfx_modes[] = {
+    { .x = 1440, .y = 1080 },
+    { .x = 1280, .y = 1024 },
+};
+
+static Error *apple_gfx_mig_blocker;
+static uint32_t next_pgdisplay_serial_num = 1;
+
+static dispatch_queue_t get_background_queue(void)
+{
+    return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+}
+
+/* ------ PGTask and task operations: new/destroy/map/unmap ------ */
+
+/*
+ * This implements the type declared in <ParavirtualizedGraphics/PGDevice.h>
+ * which is opaque from the framework's point of view. It is used in callbacks
+ * in the form of its typedef PGTask_t, which also already exists in the
+ * framework headers.
+ *
+ * A "task" in PVG terminology represents a host-virtual contiguous address
+ * range which is reserved in a large chunk on task creation. The mapMemory
+ * callback then requests ranges of guest system memory (identified by their
+ * GPA) to be mapped into subranges of this reserved address space.
+ * This type of operation isn't well-supported by QEMU's memory subsystem,
+ * but it is fortunately trivial to achieve with Darwin's mach_vm_remap() call,
+ * which allows us to refer to the same backing memory via multiple virtual
+ * address ranges. The Mach VM APIs are therefore used throughout for managing
+ * task memory.
+ */
+struct PGTask_s {
+    QTAILQ_ENTRY(PGTask_s) node;
+    AppleGFXState *s;
+    mach_vm_address_t address;
+    uint64_t len;
+    /*
+     * All unique MemoryRegions for which a mapping has been created in in this
+     * task, and on which we have thus called memory_region_ref(). There are
+     * usually very few regions of system RAM in total, so we expect this array
+     * to be very short. Therefore, no need for sorting or fancy search
+     * algorithms, linear search will do.
+     * Protected by AppleGFXState's task_mutex.
+     */
+    GPtrArray *mapped_regions;
+};
+
+static PGTask_t *apple_gfx_new_task(AppleGFXState *s, uint64_t len)
+{
+    mach_vm_address_t task_mem;
+    PGTask_t *task;
+    kern_return_t r;
+
+    r = mach_vm_allocate(mach_task_self(), &task_mem, len, VM_FLAGS_ANYWHERE);
+    if (r != KERN_SUCCESS) {
+        return NULL;
+    }
+
+    task = g_new0(PGTask_t, 1);
+    task->s = s;
+    task->address = task_mem;
+    task->len = len;
+    task->mapped_regions = g_ptr_array_sized_new(2 /* Usually enough */);
+
+    QEMU_LOCK_GUARD(&s->task_mutex);
+    QTAILQ_INSERT_TAIL(&s->tasks, task, node);
+
+    return task;
+}
+
+static void apple_gfx_destroy_task(AppleGFXState *s, PGTask_t *task)
+{
+    GPtrArray *regions = task->mapped_regions;
+    MemoryRegion *region;
+    size_t i;
+
+    for (i = 0; i < regions->len; ++i) {
+        region = g_ptr_array_index(regions, i);
+        memory_region_unref(region);
+    }
+    g_ptr_array_unref(regions);
+
+    mach_vm_deallocate(mach_task_self(), task->address, task->len);
+
+    QEMU_LOCK_GUARD(&s->task_mutex);
+    QTAILQ_REMOVE(&s->tasks, task, node);
+    g_free(task);
+}
+
+void *apple_gfx_host_ptr_for_gpa_range(uint64_t guest_physical,
+                                       uint64_t length, bool read_only,
+                                       MemoryRegion **mapping_in_region)
+{
+    MemoryRegion *ram_region;
+    char *host_ptr;
+    hwaddr ram_region_offset = 0;
+    hwaddr ram_region_length = length;
+
+    ram_region = address_space_translate(&address_space_memory,
+                                         guest_physical,
+                                         &ram_region_offset,
+                                         &ram_region_length, !read_only,
+                                         MEMTXATTRS_UNSPECIFIED);
+
+    if (!ram_region || ram_region_length < length ||
+        !memory_access_is_direct(ram_region, !read_only)) {
+        return NULL;
+    }
+
+    host_ptr = memory_region_get_ram_ptr(ram_region);
+    if (!host_ptr) {
+        return NULL;
+    }
+    host_ptr += ram_region_offset;
+    *mapping_in_region = ram_region;
+    return host_ptr;
+}
+
+static bool apple_gfx_task_map_memory(AppleGFXState *s, PGTask_t *task,
+                                      uint64_t virtual_offset,
+                                      PGPhysicalMemoryRange_t *ranges,
+                                      uint32_t range_count, bool read_only)
+{
+    kern_return_t r;
+    void *source_ptr;
+    mach_vm_address_t target;
+    vm_prot_t cur_protection, max_protection;
+    bool success = true;
+    MemoryRegion *region;
+
+    RCU_READ_LOCK_GUARD();
+    QEMU_LOCK_GUARD(&s->task_mutex);
+
+    trace_apple_gfx_map_memory(task, range_count, virtual_offset, read_only);
+    for (int i = 0; i < range_count; i++) {
+        PGPhysicalMemoryRange_t *range = &ranges[i];
+
+        target = task->address + virtual_offset;
+        virtual_offset += range->physicalLength;
+
+        trace_apple_gfx_map_memory_range(i, range->physicalAddress,
+                                         range->physicalLength);
+
+        region = NULL;
+        source_ptr = apple_gfx_host_ptr_for_gpa_range(range->physicalAddress,
+                                                      range->physicalLength,
+                                                      read_only, &region);
+        if (!source_ptr) {
+            success = false;
+            continue;
+        }
+
+        if (!g_ptr_array_find(task->mapped_regions, region, NULL)) {
+            g_ptr_array_add(task->mapped_regions, region);
+            memory_region_ref(region);
+        }
+
+        cur_protection = 0;
+        max_protection = 0;
+        /* Map guest RAM at range->physicalAddress into PG task memory range */
+        r = mach_vm_remap(mach_task_self(),
+                          &target, range->physicalLength, vm_page_size - 1,
+                          VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
+                          mach_task_self(), (mach_vm_address_t)source_ptr,
+                          false /* shared mapping, no copy */,
+                          &cur_protection, &max_protection,
+                          VM_INHERIT_COPY);
+        trace_apple_gfx_remap(r, source_ptr, target);
+        g_assert(r == KERN_SUCCESS);
+    }
+
+    return success;
+}
+
+static void apple_gfx_task_unmap_memory(AppleGFXState *s, PGTask_t *task,
+                                        uint64_t virtual_offset, uint64_t length)
+{
+    kern_return_t r;
+    mach_vm_address_t range_address;
+
+    trace_apple_gfx_unmap_memory(task, virtual_offset, length);
+
+    /*
+     * Replace task memory range with fresh 0 pages, undoing the mapping
+     * from guest RAM.
+     */
+    range_address = task->address + virtual_offset;
+    r = mach_vm_allocate(mach_task_self(), &range_address, length,
+                         VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE);
+    g_assert(r == KERN_SUCCESS);
+}
+
+/* ------ Rendering and frame management ------ */
+
+static void apple_gfx_render_frame_completed_bh(void *opaque);
+
+static void apple_gfx_render_new_frame(AppleGFXState *s)
+{
+    bool managed_texture = s->using_managed_texture_storage;
+    uint32_t width = surface_width(s->surface);
+    uint32_t height = surface_height(s->surface);
+    MTLRegion region = MTLRegionMake2D(0, 0, width, height);
+    id<MTLCommandBuffer> command_buffer = [s->mtl_queue commandBuffer];
+    id<MTLTexture> texture = s->texture;
+
+    assert(bql_locked());
+    [texture retain];
+    [command_buffer retain];
+
+    s->rendering_frame_width = width;
+    s->rendering_frame_height = height;
+
+    dispatch_async(get_background_queue(), ^{
+        /*
+         * This is not safe to call from the BQL/BH due to PVG-internal locks
+         * causing deadlocks.
+         */
+        bool r = [s->pgdisp encodeCurrentFrameToCommandBuffer:command_buffer
+                                                 texture:texture
+                                                  region:region];
+        if (!r) {
+            [texture release];
+            [command_buffer release];
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: encodeCurrentFrameToCommandBuffer:texture:region: "
+                          "failed\n", __func__);
+            bql_lock();
+            --s->pending_frames;
+            if (s->pending_frames > 0) {
+                apple_gfx_render_new_frame(s);
+            }
+            bql_unlock();
+            return;
+        }
+
+        if (managed_texture) {
+            /* "Managed" textures exist in both VRAM and RAM and must be synced. */
+            id<MTLBlitCommandEncoder> blit = [command_buffer blitCommandEncoder];
+            [blit synchronizeResource:texture];
+            [blit endEncoding];
+        }
+        [texture release];
+        [command_buffer addCompletedHandler:
+            ^(id<MTLCommandBuffer> cb)
+            {
+                aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                        apple_gfx_render_frame_completed_bh, s);
+            }];
+        [command_buffer commit];
+        [command_buffer release];
+    });
+}
+
+static void copy_mtl_texture_to_surface_mem(id<MTLTexture> texture, void *vram)
+{
+    /*
+     * TODO: Skip this entirely on a pure Metal or headless/guest-only
+     * rendering path, else use a blit command encoder? Needs careful
+     * (double?) buffering design.
+     */
+    size_t width = texture.width, height = texture.height;
+    MTLRegion region = MTLRegionMake2D(0, 0, width, height);
+    [texture getBytes:vram
+          bytesPerRow:(width * 4)
+        bytesPerImage:(width * height * 4)
+           fromRegion:region
+          mipmapLevel:0
+                slice:0];
+}
+
+static void apple_gfx_render_frame_completed_bh(void *opaque)
+{
+    AppleGFXState *s = opaque;
+
+    @autoreleasepool {
+        --s->pending_frames;
+        assert(s->pending_frames >= 0);
+
+        /* Only update display if mode hasn't changed since we started rendering. */
+        if (s->rendering_frame_width == surface_width(s->surface) &&
+            s->rendering_frame_height == surface_height(s->surface)) {
+            copy_mtl_texture_to_surface_mem(s->texture, surface_data(s->surface));
+            if (s->gfx_update_requested) {
+                s->gfx_update_requested = false;
+                dpy_gfx_update_full(s->con);
+                graphic_hw_update_done(s->con);
+                s->new_frame_ready = false;
+            } else {
+                s->new_frame_ready = true;
+            }
+        }
+        if (s->pending_frames > 0) {
+            apple_gfx_render_new_frame(s);
+        }
+    }
+}
+
+static void apple_gfx_fb_update_display(void *opaque)
+{
+    AppleGFXState *s = opaque;
+
+    assert(bql_locked());
+    if (s->new_frame_ready) {
+        dpy_gfx_update_full(s->con);
+        s->new_frame_ready = false;
+        graphic_hw_update_done(s->con);
+    } else if (s->pending_frames > 0) {
+        s->gfx_update_requested = true;
+    } else {
+        graphic_hw_update_done(s->con);
+    }
+}
+
+static const GraphicHwOps apple_gfx_fb_ops = {
+    .gfx_update = apple_gfx_fb_update_display,
+    .gfx_update_async = true,
+};
+
+/* ------ Mouse cursor and display mode setting ------ */
+
+static void set_mode(AppleGFXState *s, uint32_t width, uint32_t height)
+{
+    MTLTextureDescriptor *textureDescriptor;
+
+    if (s->surface &&
+        width == surface_width(s->surface) &&
+        height == surface_height(s->surface)) {
+        return;
+    }
+
+    [s->texture release];
+
+    s->surface = qemu_create_displaysurface(width, height);
+
+    @autoreleasepool {
+        textureDescriptor =
+            [MTLTextureDescriptor
+                texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
+                                             width:width
+                                            height:height
+                                         mipmapped:NO];
+        textureDescriptor.usage = s->pgdisp.minimumTextureUsage;
+        s->texture = [s->mtl newTextureWithDescriptor:textureDescriptor];
+        s->using_managed_texture_storage =
+            (s->texture.storageMode == MTLStorageModeManaged);
+    }
+
+    dpy_gfx_replace_surface(s->con, s->surface);
+}
+
+static void update_cursor(AppleGFXState *s)
+{
+    assert(bql_locked());
+    dpy_mouse_set(s->con, s->pgdisp.cursorPosition.x,
+                  s->pgdisp.cursorPosition.y, qatomic_read(&s->cursor_show));
+}
+
+static void update_cursor_bh(void *opaque)
+{
+    AppleGFXState *s = opaque;
+    update_cursor(s);
+}
+
+typedef struct AppleGFXSetCursorGlyphJob {
+    AppleGFXState *s;
+    NSBitmapImageRep *glyph;
+    PGDisplayCoord_t hotspot;
+} AppleGFXSetCursorGlyphJob;
+
+static void set_cursor_glyph(void *opaque)
+{
+    AppleGFXSetCursorGlyphJob *job = opaque;
+    AppleGFXState *s = job->s;
+    NSBitmapImageRep *glyph = job->glyph;
+    uint32_t bpp = glyph.bitsPerPixel;
+    size_t width = glyph.pixelsWide;
+    size_t height = glyph.pixelsHigh;
+    size_t padding_bytes_per_row = glyph.bytesPerRow - width * 4;
+    const uint8_t* px_data = glyph.bitmapData;
+
+    trace_apple_gfx_cursor_set(bpp, width, height);
+
+    if (s->cursor) {
+        cursor_unref(s->cursor);
+        s->cursor = NULL;
+    }
+
+    if (bpp == 32) { /* Shouldn't be anything else, but just to be safe... */
+        s->cursor = cursor_alloc(width, height);
+        s->cursor->hot_x = job->hotspot.x;
+        s->cursor->hot_y = job->hotspot.y;
+
+        uint32_t *dest_px = s->cursor->data;
+
+        for (size_t y = 0; y < height; ++y) {
+            for (size_t x = 0; x < width; ++x) {
+                /*
+                 * NSBitmapImageRep's red & blue channels are swapped
+                 * compared to QEMUCursor's.
+                 */
+                *dest_px =
+                    (px_data[0] << 16u) |
+                    (px_data[1] <<  8u) |
+                    (px_data[2] <<  0u) |
+                    (px_data[3] << 24u);
+                ++dest_px;
+                px_data += 4;
+            }
+            px_data += padding_bytes_per_row;
+        }
+        dpy_cursor_define(s->con, s->cursor);
+        update_cursor(s);
+    }
+    [glyph release];
+
+    g_free(job);
+}
+
+/* ------ DMA (device reading system memory) ------ */
+
+typedef struct AppleGFXReadMemoryJob {
+    QemuSemaphore sem;
+    hwaddr physical_address;
+    uint64_t length;
+    void *dst;
+    bool success;
+} AppleGFXReadMemoryJob;
+
+static void apple_gfx_do_read_memory(void *opaque)
+{
+    AppleGFXReadMemoryJob *job = opaque;
+    MemTxResult r;
+
+    r = dma_memory_read(&address_space_memory, job->physical_address,
+                        job->dst, job->length, MEMTXATTRS_UNSPECIFIED);
+    job->success = (r == MEMTX_OK);
+
+    qemu_sem_post(&job->sem);
+}
+
+static bool apple_gfx_read_memory(AppleGFXState *s, hwaddr physical_address,
+                                  uint64_t length, void *dst)
+{
+    AppleGFXReadMemoryJob job = {
+        .physical_address = physical_address, .length = length, .dst = dst
+    };
+
+    trace_apple_gfx_read_memory(physical_address, length, dst);
+
+    /* Performing DMA requires BQL, so do it in a BH. */
+    qemu_sem_init(&job.sem, 0);
+    aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                            apple_gfx_do_read_memory, &job);
+    qemu_sem_wait(&job.sem);
+    qemu_sem_destroy(&job.sem);
+    return job.success;
+}
+
+/* ------ Memory-mapped device I/O operations ------ */
+
+typedef struct AppleGFXIOJob {
+    AppleGFXState *state;
+    uint64_t offset;
+    uint64_t value;
+    bool completed;
+} AppleGFXIOJob;
+
+static void apple_gfx_do_read(void *opaque)
+{
+    AppleGFXIOJob *job = opaque;
+    job->value = [job->state->pgdev mmioReadAtOffset:job->offset];
+    qatomic_set(&job->completed, true);
+    aio_wait_kick();
+}
+
+static uint64_t apple_gfx_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AppleGFXIOJob job = {
+        .state = opaque,
+        .offset = offset,
+        .completed = false,
+    };
+    dispatch_queue_t queue = get_background_queue();
+
+    dispatch_async_f(queue, &job, apple_gfx_do_read);
+    AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));
+
+    trace_apple_gfx_read(offset, job.value);
+    return job.value;
+}
+
+static void apple_gfx_do_write(void *opaque)
+{
+    AppleGFXIOJob *job = opaque;
+    [job->state->pgdev mmioWriteAtOffset:job->offset value:job->value];
+    qatomic_set(&job->completed, true);
+    aio_wait_kick();
+}
+
+static void apple_gfx_write(void *opaque, hwaddr offset, uint64_t val,
+                            unsigned size)
+{
+    /*
+     * The methods mmioReadAtOffset: and especially mmioWriteAtOffset: can
+     * trigger synchronous operations on other dispatch queues, which in turn
+     * may call back out on one or more of the callback blocks. For this reason,
+     * and as we are holding the BQL, we invoke the I/O methods on a pool
+     * thread and handle AIO tasks while we wait. Any work in the callbacks
+     * requiring the BQL will in turn schedule BHs which this thread will
+     * process while waiting.
+     */
+    AppleGFXIOJob job = {
+        .state = opaque,
+        .offset = offset,
+        .value = val,
+        .completed = false,
+    };
+    dispatch_queue_t queue = get_background_queue();
+
+    dispatch_async_f(queue, &job, apple_gfx_do_write);
+    AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));
+
+    trace_apple_gfx_write(offset, val);
+}
+
+static const MemoryRegionOps apple_gfx_ops = {
+    .read = apple_gfx_read,
+    .write = apple_gfx_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static size_t apple_gfx_get_default_mmio_range_size(void)
+{
+    size_t mmio_range_size;
+    @autoreleasepool {
+        PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
+        mmio_range_size = desc.mmioLength;
+        [desc release];
+    }
+    return mmio_range_size;
+}
+
+/* ------ Initialisation and startup ------ */
+
+void apple_gfx_common_init(Object *obj, AppleGFXState *s, const char* obj_name)
+{
+    size_t mmio_range_size = apple_gfx_get_default_mmio_range_size();
+
+    trace_apple_gfx_common_init(obj_name, mmio_range_size);
+    memory_region_init_io(&s->iomem_gfx, obj, &apple_gfx_ops, s, obj_name,
+                          mmio_range_size);
+
+    /* TODO: PVG framework supports serialising device state: integrate it! */
+}
+
+static void apple_gfx_register_task_mapping_handlers(AppleGFXState *s,
+                                                     PGDeviceDescriptor *desc)
+{
+    desc.createTask = ^(uint64_t vmSize, void * _Nullable * _Nonnull baseAddress) {
+        PGTask_t *task = apple_gfx_new_task(s, vmSize);
+        *baseAddress = (void *)task->address;
+        trace_apple_gfx_create_task(vmSize, *baseAddress);
+        return task;
+    };
+
+    desc.destroyTask = ^(PGTask_t * _Nonnull task) {
+        trace_apple_gfx_destroy_task(task, task->mapped_regions->len);
+
+        apple_gfx_destroy_task(s, task);
+    };
+
+    desc.mapMemory = ^bool(PGTask_t * _Nonnull task, uint32_t range_count,
+                           uint64_t virtual_offset, bool read_only,
+                           PGPhysicalMemoryRange_t * _Nonnull ranges) {
+        return apple_gfx_task_map_memory(s, task, virtual_offset,
+                                         ranges, range_count, read_only);
+    };
+
+    desc.unmapMemory = ^bool(PGTask_t * _Nonnull task, uint64_t virtual_offset,
+                             uint64_t length) {
+        apple_gfx_task_unmap_memory(s, task, virtual_offset, length);
+        return true;
+    };
+
+    desc.readMemory = ^bool(uint64_t physical_address, uint64_t length,
+                            void * _Nonnull dst) {
+        return apple_gfx_read_memory(s, physical_address, length, dst);
+    };
+}
+
+static void new_frame_handler_bh(void *opaque)
+{
+    AppleGFXState *s = opaque;
+
+    /* Drop frames if guest gets too far ahead. */
+    if (s->pending_frames >= 2) {
+        return;
+    }
+    ++s->pending_frames;
+    if (s->pending_frames > 1) {
+        return;
+    }
+
+    @autoreleasepool {
+        apple_gfx_render_new_frame(s);
+    }
+}
+
+static PGDisplayDescriptor *apple_gfx_prepare_display_descriptor(AppleGFXState *s)
+{
+    PGDisplayDescriptor *disp_desc = [PGDisplayDescriptor new];
+
+    disp_desc.name = @"QEMU display";
+    disp_desc.sizeInMillimeters = NSMakeSize(400., 300.); /* A 20" display */
+    disp_desc.queue = dispatch_get_main_queue();
+    disp_desc.newFrameEventHandler = ^(void) {
+        trace_apple_gfx_new_frame();
+        aio_bh_schedule_oneshot(qemu_get_aio_context(), new_frame_handler_bh, s);
+    };
+    disp_desc.modeChangeHandler = ^(PGDisplayCoord_t sizeInPixels,
+                                    OSType pixelFormat) {
+        trace_apple_gfx_mode_change(sizeInPixels.x, sizeInPixels.y);
+
+        BQL_LOCK_GUARD();
+        set_mode(s, sizeInPixels.x, sizeInPixels.y);
+    };
+    disp_desc.cursorGlyphHandler = ^(NSBitmapImageRep *glyph,
+                                     PGDisplayCoord_t hotspot) {
+        AppleGFXSetCursorGlyphJob *job = g_malloc0(sizeof(*job));
+        job->s = s;
+        job->glyph = glyph;
+        job->hotspot = hotspot;
+        [glyph retain];
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                set_cursor_glyph, job);
+    };
+    disp_desc.cursorShowHandler = ^(BOOL show) {
+        trace_apple_gfx_cursor_show(show);
+        qatomic_set(&s->cursor_show, show);
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                update_cursor_bh, s);
+    };
+    disp_desc.cursorMoveHandler = ^(void) {
+        trace_apple_gfx_cursor_move();
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                update_cursor_bh, s);
+    };
+
+    return disp_desc;
+}
+
+static NSArray<PGDisplayMode*>* apple_gfx_prepare_display_mode_array(void)
+{
+    PGDisplayMode *modes[ARRAY_SIZE(apple_gfx_modes)];
+    NSArray<PGDisplayMode*>* mode_array;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(apple_gfx_modes); i++) {
+        modes[i] =
+            [[PGDisplayMode alloc] initWithSizeInPixels:apple_gfx_modes[i] refreshRateInHz:60.];
+    }
+
+    mode_array = [NSArray arrayWithObjects:modes count:ARRAY_SIZE(apple_gfx_modes)];
+
+    for (i = 0; i < ARRAY_SIZE(apple_gfx_modes); i++) {
+        [modes[i] release];
+        modes[i] = nil;
+    }
+
+    return mode_array;
+}
+
+static id<MTLDevice> copy_suitable_metal_device(void)
+{
+    id<MTLDevice> dev = nil;
+    NSArray<id<MTLDevice>> *devs = MTLCopyAllDevices();
+
+    /* Prefer a unified memory GPU. Failing that, pick a non-removable GPU. */
+    for (size_t i = 0; i < devs.count; ++i) {
+        if (devs[i].hasUnifiedMemory) {
+            dev = devs[i];
+            break;
+        }
+        if (!devs[i].removable) {
+            dev = devs[i];
+        }
+    }
+
+    if (dev != nil) {
+        [dev retain];
+    } else {
+        dev = MTLCreateSystemDefaultDevice();
+    }
+    [devs release];
+
+    return dev;
+}
+
+bool apple_gfx_common_realize(AppleGFXState *s, DeviceState *dev,
+                              PGDeviceDescriptor *desc, Error **errp)
+{
+    PGDisplayDescriptor *disp_desc;
+
+    if (apple_gfx_mig_blocker == NULL) {
+        error_setg(&apple_gfx_mig_blocker,
+                  "Migration state blocked by apple-gfx display device");
+        if (migrate_add_blocker(&apple_gfx_mig_blocker, errp) < 0) {
+            return false;
+        }
+    }
+
+    qemu_mutex_init(&s->task_mutex);
+    QTAILQ_INIT(&s->tasks);
+    s->mtl = copy_suitable_metal_device();
+    s->mtl_queue = [s->mtl newCommandQueue];
+
+    desc.device = s->mtl;
+
+    apple_gfx_register_task_mapping_handlers(s, desc);
+
+    s->cursor_show = true;
+
+    s->pgdev = PGNewDeviceWithDescriptor(desc);
+
+    disp_desc = apple_gfx_prepare_display_descriptor(s);
+    /*
+     * Although the framework does, this integration currently does not support
+     * multiple virtual displays connected to a single PV graphics device.
+     * It is however possible to create
+     * more than one instance of the device, each with one display. The macOS
+     * guest will ignore these displays if they share the same serial number,
+     * so ensure each instance gets a unique one.
+     */
+    s->pgdisp = [s->pgdev newDisplayWithDescriptor:disp_desc
+                                              port:0
+                                         serialNum:next_pgdisplay_serial_num++];
+    [disp_desc release];
+    s->pgdisp.modeList = apple_gfx_prepare_display_mode_array();
+
+    s->con = graphic_console_init(dev, 0, &apple_gfx_fb_ops, s);
+    return true;
+}
diff --git a/hw/display/meson.build b/hw/display/meson.build
index 20a94973fa2..cf9e6dd35d2 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -61,6 +61,12 @@ system_ss.add(when: 'CONFIG_ARTIST', if_true: files('artist.c'))
 
 system_ss.add(when: 'CONFIG_ATI_VGA', if_true: [files('ati.c', 'ati_2d.c', 'ati_dbg.c'), pixman])
 
+if host_os == 'darwin'
+  system_ss.add(when: 'CONFIG_MAC_PVG',         if_true: [files('apple-gfx.m'), pvg, metal])
+  if cpu == 'aarch64'
+    system_ss.add(when: 'CONFIG_MAC_PVG_MMIO',  if_true: [files('apple-gfx-mmio.m'), pvg, metal])
+  endif
+endif
 
 if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
   virtio_gpu_ss = ss.source_set()
diff --git a/hw/display/trace-events b/hw/display/trace-events
index d26d663f963..a50e4eea0c0 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -194,3 +194,31 @@ dm163_bits_ppi(unsigned dest_width) "dest_width : %u"
 dm163_leds(int led, uint32_t value) "led %d: 0x%x"
 dm163_channels(int channel, uint8_t value) "channel %d: 0x%x"
 dm163_refresh_rate(uint32_t rr) "refresh rate %d"
+
+# apple-gfx.m
+apple_gfx_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
+apple_gfx_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
+apple_gfx_create_task(uint32_t vm_size, void *va) "vm_size=0x%x base_addr=%p"
+apple_gfx_destroy_task(void *task, unsigned int num_mapped_regions) "task=%p, task->mapped_regions->len=%u"
+apple_gfx_map_memory(void *task, uint32_t range_count, uint64_t virtual_offset, uint32_t read_only) "task=%p range_count=0x%x virtual_offset=0x%"PRIx64" read_only=%d"
+apple_gfx_map_memory_range(uint32_t i, uint64_t phys_addr, uint64_t phys_len) "[%d] phys_addr=0x%"PRIx64" phys_len=0x%"PRIx64
+apple_gfx_remap(uint64_t retval, void *source_ptr, uint64_t target) "retval=%"PRId64" source=%p target=0x%"PRIx64
+apple_gfx_unmap_memory(void *task, uint64_t virtual_offset, uint64_t length) "task=%p virtual_offset=0x%"PRIx64" length=0x%"PRIx64
+apple_gfx_read_memory(uint64_t phys_address, uint64_t length, void *dst) "phys_addr=0x%"PRIx64" length=0x%"PRIx64" dest=%p"
+apple_gfx_raise_irq(uint32_t vector) "vector=0x%x"
+apple_gfx_new_frame(void) ""
+apple_gfx_mode_change(uint64_t x, uint64_t y) "x=%"PRId64" y=%"PRId64
+apple_gfx_cursor_set(uint32_t bpp, uint64_t width, uint64_t height) "bpp=%d width=%"PRId64" height=0x%"PRId64
+apple_gfx_cursor_show(uint32_t show) "show=%d"
+apple_gfx_cursor_move(void) ""
+apple_gfx_common_init(const char *device_name, size_t mmio_size) "device: %s; MMIO size: %zu bytes"
+
+# apple-gfx-mmio.m
+apple_gfx_mmio_iosfc_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
+apple_gfx_mmio_iosfc_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
+apple_gfx_iosfc_map_memory(uint64_t phys, uint64_t len, uint32_t ro, void *va, void *e, void *f, void* va_result) "phys=0x%"PRIx64" len=0x%"PRIx64" ro=%d va=%p e=%p f=%p -> *va=%p"
+apple_gfx_iosfc_map_memory_new_region(size_t i, void *region, uint64_t start, uint64_t end) "index=%zu, region=%p, 0x%"PRIx64"-0x%"PRIx64
+apple_gfx_iosfc_unmap_memory(void *a, void *b, void *c, void *d, void *e, void *f) "a=%p b=%p c=%p d=%p e=%p f=%p"
+apple_gfx_iosfc_unmap_memory_region(void* mem, void *region) "unmapping @ %p from memory region %p"
+apple_gfx_iosfc_raise_irq(uint32_t vector) "vector=0x%x"
+
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 25/29] hw/display/apple-gfx: Adds PCI implementation
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (23 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 24/29] hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework support Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 26/29] hw/display/apple-gfx: Adds configurable mode list Philippe Mathieu-Daudé
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

This change wires up the PCI variant of the paravirtualised
graphics device, mainly useful for x86-64 macOS guests, implemented
by macOS's ParavirtualizedGraphics.framework. It builds on code
shared with the vmapple/mmio variant of the PVG device.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-ID: <20241223221645.29911-4-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/display/apple-gfx.h     |   1 +
 hw/display/Kconfig         |   4 +
 hw/display/apple-gfx-pci.m | 151 +++++++++++++++++++++++++++++++++++++
 hw/display/meson.build     |   1 +
 4 files changed, 157 insertions(+)
 create mode 100644 hw/display/apple-gfx-pci.m

diff --git a/hw/display/apple-gfx.h b/hw/display/apple-gfx.h
index 4cd4163f223..6c74209b361 100644
--- a/hw/display/apple-gfx.h
+++ b/hw/display/apple-gfx.h
@@ -14,6 +14,7 @@
 #include "ui/surface.h"
 
 #define TYPE_APPLE_GFX_MMIO         "apple-gfx-mmio"
+#define TYPE_APPLE_GFX_PCI          "apple-gfx-pci"
 
 @class PGDeviceDescriptor;
 @protocol PGDevice;
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index 6a9b7b19ada..2b53dfd7d26 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -149,3 +149,7 @@ config MAC_PVG_MMIO
     bool
     depends on MAC_PVG && AARCH64
 
+config MAC_PVG_PCI
+    bool
+    depends on MAC_PVG && PCI
+    default y if PCI_DEVICES
diff --git a/hw/display/apple-gfx-pci.m b/hw/display/apple-gfx-pci.m
new file mode 100644
index 00000000000..35a3c7a7ce6
--- /dev/null
+++ b/hw/display/apple-gfx-pci.m
@@ -0,0 +1,151 @@
+/*
+ * QEMU Apple ParavirtualizedGraphics.framework device, PCI variant
+ *
+ * Copyright © 2023-2024 Phil Dennis-Jordan
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
+ * which implements 3d graphics passthrough to the host as well as a
+ * proprietary guest communication channel to drive it. This device model
+ * implements support to drive that library from within QEMU as a PCI device
+ * aimed primarily at x86-64 macOS VMs.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/pci/pci_device.h"
+#include "hw/pci/msi.h"
+#include "apple-gfx.h"
+#include "trace.h"
+
+#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
+
+OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXPCIState, APPLE_GFX_PCI)
+
+struct AppleGFXPCIState {
+    PCIDevice parent_obj;
+
+    AppleGFXState common;
+};
+
+static const char *apple_gfx_pci_option_rom_path = NULL;
+
+static void apple_gfx_init_option_rom_path(void)
+{
+    NSURL *option_rom_url = PGCopyOptionROMURL();
+    const char *option_rom_path = option_rom_url.fileSystemRepresentation;
+    apple_gfx_pci_option_rom_path = g_strdup(option_rom_path);
+    [option_rom_url release];
+}
+
+static void apple_gfx_pci_init(Object *obj)
+{
+    AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
+
+    if (!apple_gfx_pci_option_rom_path) {
+        /*
+         * The following is done on device not class init to avoid running
+         * ObjC code before fork() in -daemonize mode.
+         */
+        PCIDeviceClass *pci = PCI_DEVICE_CLASS(object_get_class(obj));
+        apple_gfx_init_option_rom_path();
+        pci->romfile = apple_gfx_pci_option_rom_path;
+    }
+
+    apple_gfx_common_init(obj, &s->common, TYPE_APPLE_GFX_PCI);
+}
+
+typedef struct AppleGFXPCIInterruptJob {
+    PCIDevice *device;
+    uint32_t vector;
+} AppleGFXPCIInterruptJob;
+
+static void apple_gfx_pci_raise_interrupt(void *opaque)
+{
+    AppleGFXPCIInterruptJob *job = opaque;
+
+    if (msi_enabled(job->device)) {
+        msi_notify(job->device, job->vector);
+    }
+    g_free(job);
+}
+
+static void apple_gfx_pci_interrupt(PCIDevice *dev, uint32_t vector)
+{
+    AppleGFXPCIInterruptJob *job;
+
+    trace_apple_gfx_raise_irq(vector);
+    job = g_malloc0(sizeof(*job));
+    job->device = dev;
+    job->vector = vector;
+    aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                            apple_gfx_pci_raise_interrupt, job);
+}
+
+static void apple_gfx_pci_realize(PCIDevice *dev, Error **errp)
+{
+    AppleGFXPCIState *s = APPLE_GFX_PCI(dev);
+    int ret;
+
+    pci_register_bar(dev, PG_PCI_BAR_MMIO,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->common.iomem_gfx);
+
+    ret = msi_init(dev, 0x0 /* config offset; 0 = find space */,
+                   PG_PCI_MAX_MSI_VECTORS, true /* msi64bit */,
+                   false /* msi_per_vector_mask */, errp);
+    if (ret != 0) {
+        return;
+    }
+
+    @autoreleasepool {
+        PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
+        desc.raiseInterrupt = ^(uint32_t vector) {
+            apple_gfx_pci_interrupt(dev, vector);
+        };
+
+        apple_gfx_common_realize(&s->common, DEVICE(dev), desc, errp);
+        [desc release];
+        desc = nil;
+    }
+}
+
+static void apple_gfx_pci_reset(Object *obj, ResetType type)
+{
+    AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
+    [s->common.pgdev reset];
+}
+
+static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *pci = PCI_DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.hold = apple_gfx_pci_reset;
+    dc->desc = "macOS Paravirtualized Graphics PCI Display Controller";
+    dc->hotpluggable = false;
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+
+    pci->vendor_id = PG_PCI_VENDOR_ID;
+    pci->device_id = PG_PCI_DEVICE_ID;
+    pci->class_id = PCI_CLASS_DISPLAY_OTHER;
+    pci->realize = apple_gfx_pci_realize;
+
+    /* TODO: Property for setting mode list */
+}
+
+static const TypeInfo apple_gfx_pci_types[] = {
+    {
+        .name          = TYPE_APPLE_GFX_PCI,
+        .parent        = TYPE_PCI_DEVICE,
+        .instance_size = sizeof(AppleGFXPCIState),
+        .class_init    = apple_gfx_pci_class_init,
+        .instance_init = apple_gfx_pci_init,
+        .interfaces = (InterfaceInfo[]) {
+            { INTERFACE_PCIE_DEVICE },
+            { },
+        },
+    }
+};
+DEFINE_TYPES(apple_gfx_pci_types)
+
diff --git a/hw/display/meson.build b/hw/display/meson.build
index cf9e6dd35d2..94f4f05d36f 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -63,6 +63,7 @@ system_ss.add(when: 'CONFIG_ATI_VGA', if_true: [files('ati.c', 'ati_2d.c', 'ati_
 
 if host_os == 'darwin'
   system_ss.add(when: 'CONFIG_MAC_PVG',         if_true: [files('apple-gfx.m'), pvg, metal])
+  system_ss.add(when: 'CONFIG_MAC_PVG_PCI',     if_true: [files('apple-gfx-pci.m'), pvg, metal])
   if cpu == 'aarch64'
     system_ss.add(when: 'CONFIG_MAC_PVG_MMIO',  if_true: [files('apple-gfx-mmio.m'), pvg, metal])
   endif
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 26/29] hw/display/apple-gfx: Adds configurable mode list
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (24 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 25/29] hw/display/apple-gfx: Adds PCI implementation Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 27/29] MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF Philippe Mathieu-Daudé
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

This change adds a property 'display_modes' on the graphics device
which permits specifying a list of display modes. (screen resolution
and refresh rate)

The property is an array of a custom type to make the syntax slightly
less awkward to use, for example:

-device '{"driver":"apple-gfx-pci", "display-modes":["1920x1080@60", "3840x2160@60"]}'

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Tested-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-ID: <20241223221645.29911-5-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/display/apple-gfx.h      |  10 +++
 hw/display/apple-gfx-mmio.m |   7 ++
 hw/display/apple-gfx-pci.m  |   8 ++-
 hw/display/apple-gfx.m      | 130 +++++++++++++++++++++++++++++++-----
 hw/display/trace-events     |   2 +
 5 files changed, 139 insertions(+), 18 deletions(-)

diff --git a/hw/display/apple-gfx.h b/hw/display/apple-gfx.h
index 6c74209b361..3900cdbabbb 100644
--- a/hw/display/apple-gfx.h
+++ b/hw/display/apple-gfx.h
@@ -25,6 +25,12 @@
 
 typedef QTAILQ_HEAD(, PGTask_s) PGTaskList;
 
+typedef struct AppleGFXDisplayMode {
+    uint16_t width_px;
+    uint16_t height_px;
+    uint16_t refresh_rate_hz;
+} AppleGFXDisplayMode;
+
 typedef struct AppleGFXState {
     /* Initialised on init/realize() */
     MemoryRegion iomem_gfx;
@@ -33,6 +39,8 @@ typedef struct AppleGFXState {
     QemuConsole *con;
     id<MTLDevice> mtl;
     id<MTLCommandQueue> mtl_queue;
+    AppleGFXDisplayMode *display_modes;
+    uint32_t num_display_modes;
 
     /* List `tasks` is protected by task_mutex */
     QemuMutex task_mutex;
@@ -60,5 +68,7 @@ void *apple_gfx_host_ptr_for_gpa_range(uint64_t guest_physical,
                                        uint64_t length, bool read_only,
                                        MemoryRegion **mapping_in_region);
 
+extern const PropertyInfo qdev_prop_apple_gfx_display_mode;
+
 #endif
 
diff --git a/hw/display/apple-gfx-mmio.m b/hw/display/apple-gfx-mmio.m
index 5a489d2d44f..b2e0e7a30fa 100644
--- a/hw/display/apple-gfx-mmio.m
+++ b/hw/display/apple-gfx-mmio.m
@@ -255,6 +255,11 @@ static void apple_gfx_mmio_reset(Object *obj, ResetType type)
     [s->common.pgdev reset];
 }
 
+static const Property apple_gfx_mmio_properties[] = {
+    DEFINE_PROP_ARRAY("display-modes", AppleGFXMMIOState,
+                      common.num_display_modes, common.display_modes,
+                      qdev_prop_apple_gfx_display_mode, AppleGFXDisplayMode),
+};
 
 static void apple_gfx_mmio_class_init(ObjectClass *klass, void *data)
 {
@@ -264,6 +269,8 @@ static void apple_gfx_mmio_class_init(ObjectClass *klass, void *data)
     rc->phases.hold = apple_gfx_mmio_reset;
     dc->hotpluggable = false;
     dc->realize = apple_gfx_mmio_realize;
+
+    device_class_set_props(dc, apple_gfx_mmio_properties);
 }
 
 static const TypeInfo apple_gfx_mmio_types[] = {
diff --git a/hw/display/apple-gfx-pci.m b/hw/display/apple-gfx-pci.m
index 35a3c7a7ce6..b939bb9b233 100644
--- a/hw/display/apple-gfx-pci.m
+++ b/hw/display/apple-gfx-pci.m
@@ -115,6 +115,12 @@ static void apple_gfx_pci_reset(Object *obj, ResetType type)
     [s->common.pgdev reset];
 }
 
+static const Property apple_gfx_pci_properties[] = {
+    DEFINE_PROP_ARRAY("display-modes", AppleGFXPCIState,
+                      common.num_display_modes, common.display_modes,
+                      qdev_prop_apple_gfx_display_mode, AppleGFXDisplayMode),
+};
+
 static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -131,7 +137,7 @@ static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
     pci->class_id = PCI_CLASS_DISPLAY_OTHER;
     pci->realize = apple_gfx_pci_realize;
 
-    /* TODO: Property for setting mode list */
+    device_class_set_props(dc, apple_gfx_pci_properties);
 }
 
 static const TypeInfo apple_gfx_pci_types[] = {
diff --git a/hw/display/apple-gfx.m b/hw/display/apple-gfx.m
index 59299e339d4..aa1455b6295 100644
--- a/hw/display/apple-gfx.m
+++ b/hw/display/apple-gfx.m
@@ -31,9 +31,10 @@
 
 #import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
 
-static const PGDisplayCoord_t apple_gfx_modes[] = {
-    { .x = 1440, .y = 1080 },
-    { .x = 1280, .y = 1024 },
+static const AppleGFXDisplayMode apple_gfx_default_modes[] = {
+    { 1920, 1080, 60 },
+    { 1440, 1080, 60 },
+    { 1280, 1024, 60 },
 };
 
 static Error *apple_gfx_mig_blocker;
@@ -690,22 +691,23 @@ static void new_frame_handler_bh(void *opaque)
     return disp_desc;
 }
 
-static NSArray<PGDisplayMode*>* apple_gfx_prepare_display_mode_array(void)
+static NSArray<PGDisplayMode *> *apple_gfx_create_display_mode_array(
+    const AppleGFXDisplayMode display_modes[], uint32_t display_mode_count)
 {
-    PGDisplayMode *modes[ARRAY_SIZE(apple_gfx_modes)];
-    NSArray<PGDisplayMode*>* mode_array;
-    int i;
+    PGDisplayMode *mode_obj;
+    NSMutableArray<PGDisplayMode *> *mode_array =
+        [[NSMutableArray alloc] initWithCapacity:display_mode_count];
 
-    for (i = 0; i < ARRAY_SIZE(apple_gfx_modes); i++) {
-        modes[i] =
-            [[PGDisplayMode alloc] initWithSizeInPixels:apple_gfx_modes[i] refreshRateInHz:60.];
-    }
+    for (unsigned i = 0; i < display_mode_count; i++) {
+        const AppleGFXDisplayMode *mode = &display_modes[i];
+        trace_apple_gfx_display_mode(i, mode->width_px, mode->height_px);
+        PGDisplayCoord_t mode_size = { mode->width_px, mode->height_px };
 
-    mode_array = [NSArray arrayWithObjects:modes count:ARRAY_SIZE(apple_gfx_modes)];
-
-    for (i = 0; i < ARRAY_SIZE(apple_gfx_modes); i++) {
-        [modes[i] release];
-        modes[i] = nil;
+        mode_obj =
+            [[PGDisplayMode alloc] initWithSizeInPixels:mode_size
+                                        refreshRateInHz:mode->refresh_rate_hz];
+        [mode_array addObject:mode_obj];
+        [mode_obj release];
     }
 
     return mode_array;
@@ -741,6 +743,9 @@ bool apple_gfx_common_realize(AppleGFXState *s, DeviceState *dev,
                               PGDeviceDescriptor *desc, Error **errp)
 {
     PGDisplayDescriptor *disp_desc;
+    const AppleGFXDisplayMode *display_modes = apple_gfx_default_modes;
+    uint32_t num_display_modes = ARRAY_SIZE(apple_gfx_default_modes);
+    NSArray<PGDisplayMode *> *mode_array;
 
     if (apple_gfx_mig_blocker == NULL) {
         error_setg(&apple_gfx_mig_blocker,
@@ -776,8 +781,99 @@ bool apple_gfx_common_realize(AppleGFXState *s, DeviceState *dev,
                                               port:0
                                          serialNum:next_pgdisplay_serial_num++];
     [disp_desc release];
-    s->pgdisp.modeList = apple_gfx_prepare_display_mode_array();
+
+    if (s->display_modes != NULL && s->num_display_modes > 0) {
+        trace_apple_gfx_common_realize_modes_property(s->num_display_modes);
+        display_modes = s->display_modes;
+        num_display_modes = s->num_display_modes;
+    }
+    s->pgdisp.modeList = mode_array =
+        apple_gfx_create_display_mode_array(display_modes, num_display_modes);
+    [mode_array release];
 
     s->con = graphic_console_init(dev, 0, &apple_gfx_fb_ops, s);
     return true;
 }
+
+/* ------ Display mode list device property ------ */
+
+static void apple_gfx_get_display_mode(Object *obj, Visitor *v,
+                                       const char *name, void *opaque,
+                                       Error **errp)
+{
+    Property *prop = opaque;
+    AppleGFXDisplayMode *mode = object_field_prop_ptr(obj, prop);
+    /* 3 uint16s (max 5 digits) + 2 separator characters + nul. */
+    char buffer[5 * 3 + 2 + 1];
+    char *pos = buffer;
+
+    int rc = snprintf(buffer, sizeof(buffer),
+                      "%"PRIu16"x%"PRIu16"@%"PRIu16,
+                      mode->width_px, mode->height_px,
+                      mode->refresh_rate_hz);
+    assert(rc < sizeof(buffer));
+
+    visit_type_str(v, name, &pos, errp);
+}
+
+static void apple_gfx_set_display_mode(Object *obj, Visitor *v,
+                                       const char *name, void *opaque,
+                                       Error **errp)
+{
+    Property *prop = opaque;
+    AppleGFXDisplayMode *mode = object_field_prop_ptr(obj, prop);
+    const char *endptr;
+    g_autofree char *str = NULL;
+    int ret;
+    int val;
+
+    if (!visit_type_str(v, name, &str, errp)) {
+        return;
+    }
+
+    endptr = str;
+
+    ret = qemu_strtoi(endptr, &endptr, 10, &val);
+    if (ret || val > UINT16_MAX || val <= 0) {
+        error_setg(errp, "width in '%s' must be a decimal integer number"
+                         " of pixels in the range 1..65535", name);
+        return;
+    }
+    mode->width_px = val;
+    if (*endptr != 'x') {
+        goto separator_error;
+    }
+
+    ret = qemu_strtoi(endptr + 1, &endptr, 10, &val);
+    if (ret || val > UINT16_MAX || val <= 0) {
+        error_setg(errp, "height in '%s' must be a decimal integer number"
+                         " of pixels in the range 1..65535", name);
+        return;
+    }
+    mode->height_px = val;
+    if (*endptr != '@') {
+        goto separator_error;
+    }
+
+    ret = qemu_strtoi(endptr + 1, &endptr, 10, &val);
+    if (ret || val > UINT16_MAX || val <= 0) {
+        error_setg(errp, "refresh rate in '%s'"
+                         " must be a positive decimal integer (Hertz)", name);
+        return;
+    }
+    mode->refresh_rate_hz = val;
+    return;
+
+separator_error:
+    error_setg(errp,
+               "Each display mode takes the format '<width>x<height>@<rate>'");
+}
+
+const PropertyInfo qdev_prop_apple_gfx_display_mode = {
+    .name  = "display_mode",
+    .description =
+        "Display mode in pixels and Hertz, as <width>x<height>@<refresh-rate> "
+        "Example: 3840x2160@60",
+    .get   = apple_gfx_get_display_mode,
+    .set   = apple_gfx_set_display_mode,
+};
diff --git a/hw/display/trace-events b/hw/display/trace-events
index a50e4eea0c0..52786e6e184 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -212,6 +212,8 @@ apple_gfx_cursor_set(uint32_t bpp, uint64_t width, uint64_t height) "bpp=%d widt
 apple_gfx_cursor_show(uint32_t show) "show=%d"
 apple_gfx_cursor_move(void) ""
 apple_gfx_common_init(const char *device_name, size_t mmio_size) "device: %s; MMIO size: %zu bytes"
+apple_gfx_common_realize_modes_property(uint32_t num_modes) "using %u modes supplied by 'display-modes' device property"
+apple_gfx_display_mode(uint32_t mode_idx, uint16_t width_px, uint16_t height_px) "mode %2"PRIu32": %4"PRIu16"x%4"PRIu16
 
 # apple-gfx-mmio.m
 apple_gfx_mmio_iosfc_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 27/29] MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (25 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 26/29] hw/display/apple-gfx: Adds configurable mode list Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 28/29] net/vmnet: Pad short Ethernet frames Philippe Mathieu-Daudé
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Phil Dennis-Jordan, Roman Bolshakov, Philippe Mathieu-Daudé

From: Phil Dennis-Jordan <phil@philjordan.eu>

I'm happy to take responsibility for the macOS PV graphics code. As
HVF patches don't seem to get much attention at the moment, I'm also
adding myself as designated reviewer for HVF and x86 HVF to try and
improve that.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Roman Bolshakov <rbolshakov@ddn.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241223221645.29911-6-phil@philjordan.eu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 38a290e9c2c..2101b512175 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -509,6 +509,7 @@ F: target/arm/hvf/
 X86 HVF CPUs
 M: Cameron Esfahani <dirty@apple.com>
 M: Roman Bolshakov <rbolshakov@ddn.com>
+R: Phil Dennis-Jordan <phil@philjordan.eu>
 W: https://wiki.qemu.org/Features/HVF
 S: Maintained
 F: target/i386/hvf/
@@ -516,6 +517,7 @@ F: target/i386/hvf/
 HVF
 M: Cameron Esfahani <dirty@apple.com>
 M: Roman Bolshakov <rbolshakov@ddn.com>
+R: Phil Dennis-Jordan <phil@philjordan.eu>
 W: https://wiki.qemu.org/Features/HVF
 S: Maintained
 F: accel/hvf/
@@ -2631,6 +2633,11 @@ F: hw/display/edid*
 F: include/hw/display/edid.h
 F: qemu-edid.c
 
+macOS PV Graphics (apple-gfx)
+M: Phil Dennis-Jordan <phil@philjordan.eu>
+S: Maintained
+F: hw/display/apple-gfx*
+
 PIIX4 South Bridge (i82371AB)
 M: Hervé Poussineau <hpoussin@reactos.org>
 M: Philippe Mathieu-Daudé <philmd@linaro.org>
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 28/29] net/vmnet: Pad short Ethernet frames
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (26 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 27/29] MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2024-12-31 20:22 ` [PULL 29/29] hw/display/qxl: Do not use C99 // comments Philippe Mathieu-Daudé
  2025-01-01 23:41 ` [PULL 00/29] Misc HW patches for 2024-12-31 Stefan Hajnoczi
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: William Hooper, Phil Dennis-Jordan, Philippe Mathieu-Daudé

From: William Hooper <wsh@wshooper.org>

At least on macOS 12.7.2, vmnet doesn't pad Ethernet frames, such as the
host's ARP replies, to the minimum size (60 bytes before the frame check
sequence) defined in IEEE Std 802.3-2022, so guests' Ethernet device
drivers may drop them with "frame too short" errors.

This patch calls eth_pad_short_frame() to add padding, as in net/tap.c
and net/slirp.c. Thanks to Bin Meng, Philippe Mathieu-Daudé, and Phil
Dennis-Jordan for reviewing earlier versions.

Signed-off-by: William Hooper <wsh@wshooper.org>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2058
Reviewed-by: Phil Dennis-Jordan <phil@philjordan.eu>
Message-ID: <20241102205653.30476-1-wsh@wshooper.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 net/vmnet-common.m | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/net/vmnet-common.m b/net/vmnet-common.m
index dba5b5bab13..54d900ba679 100644
--- a/net/vmnet-common.m
+++ b/net/vmnet-common.m
@@ -18,6 +18,7 @@
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "system/runstate.h"
+#include "net/eth.h"
 
 #include <vmnet/vmnet.h>
 #include <dispatch/dispatch.h>
@@ -147,10 +148,26 @@ static int vmnet_read_packets(VmnetState *s)
  */
 static void vmnet_write_packets_to_qemu(VmnetState *s)
 {
+    uint8_t *pkt;
+    size_t pktsz;
+    uint8_t min_pkt[ETH_ZLEN];
+    size_t min_pktsz;
+    ssize_t size;
+
     while (s->packets_send_current_pos < s->packets_send_end_pos) {
-        ssize_t size = qemu_send_packet_async(&s->nc,
-                                      s->iov_buf[s->packets_send_current_pos].iov_base,
-                                      s->packets_buf[s->packets_send_current_pos].vm_pkt_size,
+        pkt = s->iov_buf[s->packets_send_current_pos].iov_base;
+        pktsz = s->packets_buf[s->packets_send_current_pos].vm_pkt_size;
+
+        if (net_peer_needs_padding(&s->nc)) {
+            min_pktsz = sizeof(min_pkt);
+
+            if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pktsz)) {
+                pkt = min_pkt;
+                pktsz = min_pktsz;
+            }
+        }
+
+        size = qemu_send_packet_async(&s->nc, pkt, pktsz,
                                       vmnet_send_completed);
 
         if (size == 0) {
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PULL 29/29] hw/display/qxl: Do not use C99 // comments
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (27 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 28/29] net/vmnet: Pad short Ethernet frames Philippe Mathieu-Daudé
@ 2024-12-31 20:22 ` Philippe Mathieu-Daudé
  2025-01-01 23:41 ` [PULL 00/29] Misc HW patches for 2024-12-31 Stefan Hajnoczi
  29 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-12-31 20:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hyman Huang, Philippe Mathieu-Daudé

From: Hyman Huang <yong.huang@smartx.com>

Do not use C99 // comments to fix the checkpatch.pl error

Signed-off-by: Hyman Huang <yong.huang@smartx.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <7d287eaf00e0b52b600431efd350b15a0b5b3544.1734633496.git.yong.huang@smartx.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/display/qxl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index f54a15e7404..2efdc77e613 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -50,7 +50,7 @@
 #undef ALIGN
 #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
 
-#define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9" 
+#define PIXEL_SIZE 0.2936875 /* 1280x1024 is 14.8" x 11.9" */
 
 #define QXL_MODE(_x, _y, _b, _o)                  \
     {   .x_res = _x,                              \
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PULL 00/29] Misc HW patches for 2024-12-31
  2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
                   ` (28 preceding siblings ...)
  2024-12-31 20:22 ` [PULL 29/29] hw/display/qxl: Do not use C99 // comments Philippe Mathieu-Daudé
@ 2025-01-01 23:41 ` Stefan Hajnoczi
  29 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2025-01-01 23:41 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: qemu-devel, Philippe Mathieu-Daudé

[-- Attachment #1: Type: text/plain, Size: 116 bytes --]

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any user-visible changes.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 02/29] hw/misc/ivshmem-flat: Add ivshmem-flat device
  2024-12-31 20:22 ` [PULL 02/29] hw/misc/ivshmem-flat: Add ivshmem-flat device Philippe Mathieu-Daudé
@ 2025-01-02 21:19   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-01-02 21:19 UTC (permalink / raw)
  To: Gustavo Romero; +Cc: qemu-devel

Hi Gustavo,

On 31/12/24 21:22, Philippe Mathieu-Daudé wrote:
> From: Gustavo Romero <gustavo.romero@linaro.org>
> 
> Add a new device, ivshmem-flat, which is similar to the ivshmem PCI but
> does not require a PCI bus. It's meant to be used on machines like those
> with Cortex-M MCUs, which usually lack a PCI/PCIe bus, e.g. lm3s6965evb
> and mps2-an385.
> 
> The device currently only supports the sysbus bus.
> 
> The new device, just like the ivshmem PCI device, supports both peer
> notification via hardware interrupts and shared memory.
> 
> The device shared memory size can be set using the 'shmem-size' option
> and it defaults to 4 MiB, which is the default size of shmem allocated
> by the ivshmem server.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1134
> Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
> [PMD: Rebased updating Property and using DEFINE_TYPES macro]
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Message-ID: <20241216141818.111255-2-gustavo.romero@linaro.org>
> ---
>   docs/system/device-emulation.rst     |   1 +
>   docs/system/devices/ivshmem-flat.rst |  33 ++
>   include/hw/misc/ivshmem-flat.h       |  85 +++++
>   hw/misc/ivshmem-flat.c               | 459 +++++++++++++++++++++++++++
>   hw/misc/Kconfig                      |   5 +
>   hw/misc/meson.build                  |   2 +
>   hw/misc/trace-events                 |  16 +
>   7 files changed, 601 insertions(+)
>   create mode 100644 docs/system/devices/ivshmem-flat.rst
>   create mode 100644 include/hw/misc/ivshmem-flat.h
>   create mode 100644 hw/misc/ivshmem-flat.c


> diff --git a/hw/misc/ivshmem-flat.c b/hw/misc/ivshmem-flat.c
> new file mode 100644
> index 00000000000..33fc9425d20
> --- /dev/null
> +++ b/hw/misc/ivshmem-flat.c
> @@ -0,0 +1,459 @@
> +/*
> + * Inter-VM Shared Memory Flat Device
> + *
> + * SPDX-FileCopyrightText: 2023 Linaro Ltd.
> + * SPDX-FileContributor: Gustavo Romero <gustavo.romero@linaro.org>
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qemu/error-report.h"
> +#include "qemu/module.h"
> +#include "qapi/error.h"
> +#include "hw/irq.h"
> +#include "hw/qdev-properties-system.h"
> +#include "hw/sysbus.h"
> +#include "chardev/char-fe.h"
> +#include "exec/address-spaces.h"
> +#include "trace.h"
> +
> +#include "hw/misc/ivshmem-flat.h"
> +
> +static int64_t ivshmem_flat_recv_msg(IvshmemFTState *s, int *pfd)
> +{
> +    int64_t msg;
> +    int n, ret;
> +
> +    n = 0;
> +    do {
> +        ret = qemu_chr_fe_read_all(&s->server_chr, (uint8_t *)&msg + n,
> +                                   sizeof(msg) - n);

Coverity reported:

 >>>     CID 1586089:  Insecure data handling  (INTEGER_OVERFLOW)
 >>>     "8UL - n", which might have underflowed, is passed to 
"qemu_chr_fe_read_all(&s->server_chr, (uint8_t *)&msg + n, 8UL - n)".

Could you have a look?

> +        if (ret < 0) {
> +            if (ret == -EINTR) {
> +                continue;

Also as a future cleanup consider using the RETRY_ON_EINTR macro.

> +            }
> +            exit(1);
> +        }
> +        n += ret;
> +    } while (n < sizeof(msg));
> +
> +    if (pfd) {
> +        *pfd = qemu_chr_fe_get_msgfd(&s->server_chr);
> +    }
> +    return le64_to_cpu(msg);
> +}

Thanks!

Phil.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2024-12-31 20:22 ` [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling Philippe Mathieu-Daudé
@ 2025-01-08 13:51   ` David Woodhouse
  2025-04-01 11:18     ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2025-01-08 13:51 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki

[-- Attachment #1: Type: text/plain, Size: 3793 bytes --]

On Tue, 2024-12-31 at 21:22 +0100, Philippe Mathieu-Daudé wrote:
> 
> This change tidies up main thread management to be more flexible.
> 
>  * The qemu_main global function pointer is a custom function for the
>    main thread, and it may now be NULL. When it is, the main thread
>    runs the main Qemu loop. This represents the traditional setup.
>  * When non-null, spawning the main Qemu event loop on a separate
>    thread is now done centrally rather than inside the Cocoa UI code.
>  * For most platforms, qemu_main is indeed NULL by default, but on
>    Darwin, it defaults to a function that runs the CFRunLoop.
>  * The Cocoa UI sets qemu_main to a function which runs the
>    NSApplication event handling runloop, as is usual for a Cocoa app.
>  * The SDL UI overrides the qemu_main function to NULL, thus
>    specifying that Qemu's main loop must run on the main
>    thread.
>  * The GTK UI also overrides the qemu_main function to NULL.
>  * For other UIs, or in the absence of UIs, the platform's default
>    behaviour is followed.

When exiting an emulated Xen guest with <Ctrl-a x> on the console, I
now see:

(gdb) run
Starting program: /home/dwmw2/git/qemu/ball/qemu-system-x86_64 -display none -vga none -serial mon:stdio -machine q35 -accel kvm,xen-version=0x4000a,kernel-irqchip=split -smp 2 -kernel /home/dwmw2/avocado/data/cache/by_name/bzImage -append printk.time=0\ root=/dev/xvda\ console=ttyS0\ xen_emul_unplug=ide-disks\ xen_no_vector_callback\ noapic\ loglevel=0 -drive file=/home/dwmw2/avocado/data/cache/by_name/rootfs.ext4,if=none,snapshot=on,format=raw,id=drv0 -device xen-disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -netdev user,id=unet,hostfwd=:127.0.0.1:0-:22

Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Saving 256 bits of non-creditable seed for next boot
Starting network: OK
Starting dhcpcd...
no such user dhcpcd
dhcpcd-9.4.1 starting
no interfaces have a carrier
forked to background, child pid 111
Starting dropbear sshd: OK
# 
QEMU: Terminated
qemu-system-x86_64: ../block/block-backend.c:1290: blk_in_drain: Assertion `qemu_in_main_thread()' failed.

Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted.
0x00007ffff5ffc724 in __pthread_kill_implementation () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff5ffc724 in __pthread_kill_implementation () at /lib64/libc.so.6
#1  0x00007ffff5fa3d1e in raise () at /lib64/libc.so.6
#2  0x00007ffff5f8b942 in abort () at /lib64/libc.so.6
#3  0x00007ffff5f8b85e in __assert_fail_base.cold () at /lib64/libc.so.6
#4  0x00007ffff5f9be47 in __assert_fail () at /lib64/libc.so.6
#5  0x0000555555abf911 in blk_in_drain (blk=0x555557ca6680)
    at ../block/block-backend.c:1290
#6  0x000055555593410c in xen_block_dataplane_stop (dataplane=0x555558982950)
    at ../hw/block/dataplane/xen-block.c:695
#7  0x000055555593441a in xen_block_dataplane_stop (dataplane=<optimized out>)
    at ../hw/block/dataplane/xen-block.c:689
#8  0x00005555555dfd5e in xen_block_disconnect
    (xendev=xendev@entry=0x55555880aa60, errp=<optimized out>)
    at ../hw/block/xen-block.c:172
#9  0x00005555555dfeca in xen_block_unrealize (xendev=0x55555880aa60)
    at ../hw/block/xen-block.c:282
#10 0x000055555578ef71 in xen_device_unrealize (dev=<optimized out>)
    at ../hw/xen/xen-bus.c:978
#11 0x0000555555bfe65f in notifier_list_notify (list=<optimized out>, data=0x0)
    at ../util/notify.c:39
#12 0x00007ffff5fa6461 in __run_exit_handlers () at /lib64/libc.so.6
#13 0x00007ffff5fa652e in exit () at /lib64/libc.so.6
#14 0x0000555555b523dc in qemu_default_main (opaque=opaque@entry=0x0)
#15 0x00005555555609c0 in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:76


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2025-01-08 13:51   ` David Woodhouse
@ 2025-04-01 11:18     ` Philippe Mathieu-Daudé
  2025-04-01 11:30       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-04-01 11:18 UTC (permalink / raw)
  To: David Woodhouse, qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki

Hi David,

On 8/1/25 14:51, David Woodhouse wrote:
> On Tue, 2024-12-31 at 21:22 +0100, Philippe Mathieu-Daudé wrote:
>>
>> This change tidies up main thread management to be more flexible.
>>
>>   * The qemu_main global function pointer is a custom function for the
>>     main thread, and it may now be NULL. When it is, the main thread
>>     runs the main Qemu loop. This represents the traditional setup.
>>   * When non-null, spawning the main Qemu event loop on a separate
>>     thread is now done centrally rather than inside the Cocoa UI code.
>>   * For most platforms, qemu_main is indeed NULL by default, but on
>>     Darwin, it defaults to a function that runs the CFRunLoop.
>>   * The Cocoa UI sets qemu_main to a function which runs the
>>     NSApplication event handling runloop, as is usual for a Cocoa app.
>>   * The SDL UI overrides the qemu_main function to NULL, thus
>>     specifying that Qemu's main loop must run on the main
>>     thread.
>>   * The GTK UI also overrides the qemu_main function to NULL.
>>   * For other UIs, or in the absence of UIs, the platform's default
>>     behaviour is followed.
> 
> When exiting an emulated Xen guest with <Ctrl-a x> on the console, I
> now see:
> 
> (gdb) run
> Starting program: /home/dwmw2/git/qemu/ball/qemu-system-x86_64 -display none -vga none -serial mon:stdio -machine q35 -accel kvm,xen-version=0x4000a,kernel-irqchip=split -smp 2 -kernel /home/dwmw2/avocado/data/cache/by_name/bzImage -append printk.time=0\ root=/dev/xvda\ console=ttyS0\ xen_emul_unplug=ide-disks\ xen_no_vector_callback\ noapic\ loglevel=0 -drive file=/home/dwmw2/avocado/data/cache/by_name/rootfs.ext4,if=none,snapshot=on,format=raw,id=drv0 -device xen-disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -netdev user,id=unet,hostfwd=:127.0.0.1:0-:22
> 
> Starting syslogd: OK
> Starting klogd: OK
> Running sysctl: OK
> Saving 256 bits of non-creditable seed for next boot
> Starting network: OK
> Starting dhcpcd...
> no such user dhcpcd
> dhcpcd-9.4.1 starting
> no interfaces have a carrier
> forked to background, child pid 111
> Starting dropbear sshd: OK
> #
> QEMU: Terminated
> qemu-system-x86_64: ../block/block-backend.c:1290: blk_in_drain: Assertion `qemu_in_main_thread()' failed.
> 
> Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted.
> 0x00007ffff5ffc724 in __pthread_kill_implementation () from /lib64/libc.so.6
> (gdb) bt
> #0  0x00007ffff5ffc724 in __pthread_kill_implementation () at /lib64/libc.so.6
> #1  0x00007ffff5fa3d1e in raise () at /lib64/libc.so.6
> #2  0x00007ffff5f8b942 in abort () at /lib64/libc.so.6
> #3  0x00007ffff5f8b85e in __assert_fail_base.cold () at /lib64/libc.so.6
> #4  0x00007ffff5f9be47 in __assert_fail () at /lib64/libc.so.6
> #5  0x0000555555abf911 in blk_in_drain (blk=0x555557ca6680)
>      at ../block/block-backend.c:1290
> #6  0x000055555593410c in xen_block_dataplane_stop (dataplane=0x555558982950)
>      at ../hw/block/dataplane/xen-block.c:695
> #7  0x000055555593441a in xen_block_dataplane_stop (dataplane=<optimized out>)
>      at ../hw/block/dataplane/xen-block.c:689
> #8  0x00005555555dfd5e in xen_block_disconnect
>      (xendev=xendev@entry=0x55555880aa60, errp=<optimized out>)
>      at ../hw/block/xen-block.c:172
> #9  0x00005555555dfeca in xen_block_unrealize (xendev=0x55555880aa60)
>      at ../hw/block/xen-block.c:282
> #10 0x000055555578ef71 in xen_device_unrealize (dev=<optimized out>)
>      at ../hw/xen/xen-bus.c:978
> #11 0x0000555555bfe65f in notifier_list_notify (list=<optimized out>, data=0x0)
>      at ../util/notify.c:39
> #12 0x00007ffff5fa6461 in __run_exit_handlers () at /lib64/libc.so.6
> #13 0x00007ffff5fa652e in exit () at /lib64/libc.so.6
> #14 0x0000555555b523dc in qemu_default_main (opaque=opaque@entry=0x0)
> #15 0x00005555555609c0 in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:76
> 

Is this still an issue?


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2025-04-01 11:18     ` Philippe Mathieu-Daudé
@ 2025-04-01 11:30       ` Philippe Mathieu-Daudé
  2025-04-01 11:43         ` David Woodhouse
  0 siblings, 1 reply; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-04-01 11:30 UTC (permalink / raw)
  To: David Woodhouse, qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki

On 1/4/25 13:18, Philippe Mathieu-Daudé wrote:
> Hi David,
> 
> On 8/1/25 14:51, David Woodhouse wrote:
>> On Tue, 2024-12-31 at 21:22 +0100, Philippe Mathieu-Daudé wrote:
>>>
>>> This change tidies up main thread management to be more flexible.
>>>
>>>   * The qemu_main global function pointer is a custom function for the
>>>     main thread, and it may now be NULL. When it is, the main thread
>>>     runs the main Qemu loop. This represents the traditional setup.
>>>   * When non-null, spawning the main Qemu event loop on a separate
>>>     thread is now done centrally rather than inside the Cocoa UI code.
>>>   * For most platforms, qemu_main is indeed NULL by default, but on
>>>     Darwin, it defaults to a function that runs the CFRunLoop.
>>>   * The Cocoa UI sets qemu_main to a function which runs the
>>>     NSApplication event handling runloop, as is usual for a Cocoa app.
>>>   * The SDL UI overrides the qemu_main function to NULL, thus
>>>     specifying that Qemu's main loop must run on the main
>>>     thread.
>>>   * The GTK UI also overrides the qemu_main function to NULL.
>>>   * For other UIs, or in the absence of UIs, the platform's default
>>>     behaviour is followed.
>>
>> When exiting an emulated Xen guest with <Ctrl-a x> on the console, I
>> now see:
>>
>> (gdb) run
>> Starting program: /home/dwmw2/git/qemu/ball/qemu-system-x86_64 - 
>> display none -vga none -serial mon:stdio -machine q35 -accel kvm,xen- 
>> version=0x4000a,kernel-irqchip=split -smp 2 -kernel /home/dwmw2/ 
>> avocado/data/cache/by_name/bzImage -append printk.time=0\ root=/dev/ 
>> xvda\ console=ttyS0\ xen_emul_unplug=ide-disks\ 
>> xen_no_vector_callback\ noapic\ loglevel=0 -drive file=/home/dwmw2/ 
>> avocado/data/cache/by_name/ 
>> rootfs.ext4,if=none,snapshot=on,format=raw,id=drv0 -device xen- 
>> disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -netdev 
>> user,id=unet,hostfwd=:127.0.0.1:0-:22
>>
>> Starting syslogd: OK
>> Starting klogd: OK
>> Running sysctl: OK
>> Saving 256 bits of non-creditable seed for next boot
>> Starting network: OK
>> Starting dhcpcd...
>> no such user dhcpcd
>> dhcpcd-9.4.1 starting
>> no interfaces have a carrier
>> forked to background, child pid 111
>> Starting dropbear sshd: OK
>> #
>> QEMU: Terminated
>> qemu-system-x86_64: ../block/block-backend.c:1290: blk_in_drain: 
>> Assertion `qemu_in_main_thread()' failed.
>>
>> Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted.
>> 0x00007ffff5ffc724 in __pthread_kill_implementation () from /lib64/ 
>> libc.so.6
>> (gdb) bt
>> #0  0x00007ffff5ffc724 in __pthread_kill_implementation () at /lib64/ 
>> libc.so.6
>> #1  0x00007ffff5fa3d1e in raise () at /lib64/libc.so.6
>> #2  0x00007ffff5f8b942 in abort () at /lib64/libc.so.6
>> #3  0x00007ffff5f8b85e in __assert_fail_base.cold () at /lib64/libc.so.6
>> #4  0x00007ffff5f9be47 in __assert_fail () at /lib64/libc.so.6
>> #5  0x0000555555abf911 in blk_in_drain (blk=0x555557ca6680)
>>      at ../block/block-backend.c:1290
>> #6  0x000055555593410c in xen_block_dataplane_stop 
>> (dataplane=0x555558982950)
>>      at ../hw/block/dataplane/xen-block.c:695
>> #7  0x000055555593441a in xen_block_dataplane_stop 
>> (dataplane=<optimized out>)
>>      at ../hw/block/dataplane/xen-block.c:689
>> #8  0x00005555555dfd5e in xen_block_disconnect
>>      (xendev=xendev@entry=0x55555880aa60, errp=<optimized out>)
>>      at ../hw/block/xen-block.c:172
>> #9  0x00005555555dfeca in xen_block_unrealize (xendev=0x55555880aa60)
>>      at ../hw/block/xen-block.c:282
>> #10 0x000055555578ef71 in xen_device_unrealize (dev=<optimized out>)
>>      at ../hw/xen/xen-bus.c:978
>> #11 0x0000555555bfe65f in notifier_list_notify (list=<optimized out>, 
>> data=0x0)
>>      at ../util/notify.c:39
>> #12 0x00007ffff5fa6461 in __run_exit_handlers () at /lib64/libc.so.6
>> #13 0x00007ffff5fa652e in exit () at /lib64/libc.so.6
>> #14 0x0000555555b523dc in qemu_default_main (opaque=opaque@entry=0x0)
>> #15 0x00005555555609c0 in main (argc=<optimized out>, argv=<optimized 
>> out>) at ../system/main.c:76
>>
> 
> Is this still an issue?

Likely fixed by commit e7bc0204 ("system/runstate:
Fix regression, clarify BQL status of exit notifiers"), so
I'm closing https://gitlab.com/qemu-project/qemu/-/issues/2771.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2025-04-01 11:30       ` Philippe Mathieu-Daudé
@ 2025-04-01 11:43         ` David Woodhouse
  2025-04-01 11:58           ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2025-04-01 11:43 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki

[-- Attachment #1: Type: text/plain, Size: 5182 bytes --]

On Tue, 2025-04-01 at 13:30 +0200, Philippe Mathieu-Daudé wrote:
> On 1/4/25 13:18, Philippe Mathieu-Daudé wrote:
> > Hi David,
> > 
> > On 8/1/25 14:51, David Woodhouse wrote:
> > > On Tue, 2024-12-31 at 21:22 +0100, Philippe Mathieu-Daudé wrote:
> > > > 
> > > > This change tidies up main thread management to be more
> > > > flexible.
> > > > 
> > > >   * The qemu_main global function pointer is a custom function
> > > > for the
> > > >     main thread, and it may now be NULL. When it is, the main
> > > > thread
> > > >     runs the main Qemu loop. This represents the traditional
> > > > setup.
> > > >   * When non-null, spawning the main Qemu event loop on a
> > > > separate
> > > >     thread is now done centrally rather than inside the Cocoa
> > > > UI code.
> > > >   * For most platforms, qemu_main is indeed NULL by default,
> > > > but on
> > > >     Darwin, it defaults to a function that runs the CFRunLoop.
> > > >   * The Cocoa UI sets qemu_main to a function which runs the
> > > >     NSApplication event handling runloop, as is usual for a
> > > > Cocoa app.
> > > >   * The SDL UI overrides the qemu_main function to NULL, thus
> > > >     specifying that Qemu's main loop must run on the main
> > > >     thread.
> > > >   * The GTK UI also overrides the qemu_main function to NULL.
> > > >   * For other UIs, or in the absence of UIs, the platform's
> > > > default
> > > >     behaviour is followed.
> > > 
> > > When exiting an emulated Xen guest with <Ctrl-a x> on the
> > > console, I
> > > now see:
> > > 
> > > (gdb) run
> > > Starting program: /home/dwmw2/git/qemu/ball/qemu-system-x86_64 - 
> > > display none -vga none -serial mon:stdio -machine q35 -accel
> > > kvm,xen- 
> > > version=0x4000a,kernel-irqchip=split -smp 2 -kernel /home/dwmw2/ 
> > > avocado/data/cache/by_name/bzImage -append printk.time=0\
> > > root=/dev/ 
> > > xvda\ console=ttyS0\ xen_emul_unplug=ide-disks\ 
> > > xen_no_vector_callback\ noapic\ loglevel=0 -drive
> > > file=/home/dwmw2/ 
> > > avocado/data/cache/by_name/ 
> > > rootfs.ext4,if=none,snapshot=on,format=raw,id=drv0 -device xen- 
> > > disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -
> > > netdev 
> > > user,id=unet,hostfwd=:127.0.0.1:0-:22
> > > 
> > > Starting syslogd: OK
> > > Starting klogd: OK
> > > Running sysctl: OK
> > > Saving 256 bits of non-creditable seed for next boot
> > > Starting network: OK
> > > Starting dhcpcd...
> > > no such user dhcpcd
> > > dhcpcd-9.4.1 starting
> > > no interfaces have a carrier
> > > forked to background, child pid 111
> > > Starting dropbear sshd: OK
> > > #
> > > QEMU: Terminated
> > > qemu-system-x86_64: ../block/block-backend.c:1290: blk_in_drain: 
> > > Assertion `qemu_in_main_thread()' failed.
> > > 
> > > Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted.
> > > 0x00007ffff5ffc724 in __pthread_kill_implementation () from
> > > /lib64/ 
> > > libc.so.6
> > > (gdb) bt
> > > #0  0x00007ffff5ffc724 in __pthread_kill_implementation () at
> > > /lib64/ 
> > > libc.so.6
> > > #1  0x00007ffff5fa3d1e in raise () at /lib64/libc.so.6
> > > #2  0x00007ffff5f8b942 in abort () at /lib64/libc.so.6
> > > #3  0x00007ffff5f8b85e in __assert_fail_base.cold () at
> > > /lib64/libc.so.6
> > > #4  0x00007ffff5f9be47 in __assert_fail () at /lib64/libc.so.6
> > > #5  0x0000555555abf911 in blk_in_drain (blk=0x555557ca6680)
> > >      at ../block/block-backend.c:1290
> > > #6  0x000055555593410c in xen_block_dataplane_stop 
> > > (dataplane=0x555558982950)
> > >      at ../hw/block/dataplane/xen-block.c:695
> > > #7  0x000055555593441a in xen_block_dataplane_stop 
> > > (dataplane=<optimized out>)
> > >      at ../hw/block/dataplane/xen-block.c:689
> > > #8  0x00005555555dfd5e in xen_block_disconnect
> > >      (xendev=xendev@entry=0x55555880aa60, errp=<optimized out>)
> > >      at ../hw/block/xen-block.c:172
> > > #9  0x00005555555dfeca in xen_block_unrealize
> > > (xendev=0x55555880aa60)
> > >      at ../hw/block/xen-block.c:282
> > > #10 0x000055555578ef71 in xen_device_unrealize (dev=<optimized
> > > out>)
> > >      at ../hw/xen/xen-bus.c:978
> > > #11 0x0000555555bfe65f in notifier_list_notify (list=<optimized
> > > out>, 
> > > data=0x0)
> > >      at ../util/notify.c:39
> > > #12 0x00007ffff5fa6461 in __run_exit_handlers () at
> > > /lib64/libc.so.6
> > > #13 0x00007ffff5fa652e in exit () at /lib64/libc.so.6
> > > #14 0x0000555555b523dc in qemu_default_main
> > > (opaque=opaque@entry=0x0)
> > > #15 0x00005555555609c0 in main (argc=<optimized out>,
> > > argv=<optimized 
> > > out>) at ../system/main.c:76
> > > 
> > 
> > Is this still an issue?
> 
> Likely fixed by commit e7bc0204 ("system/runstate:
> Fix regression, clarify BQL status of exit notifiers"), so
> I'm closing https://gitlab.com/qemu-project/qemu/-/issues/2771.

Indeed. I think I was assuming the explicit Resolves: tag in that
commit was going to magically close the issue when it was merged.
Should I have closed it manually?


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2025-04-01 11:43         ` David Woodhouse
@ 2025-04-01 11:58           ` Philippe Mathieu-Daudé
  2025-04-01 12:00             ` David Woodhouse
  0 siblings, 1 reply; 38+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-04-01 11:58 UTC (permalink / raw)
  To: David Woodhouse, qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki

On 1/4/25 13:43, David Woodhouse wrote:
> On Tue, 2025-04-01 at 13:30 +0200, Philippe Mathieu-Daudé wrote:
>> On 1/4/25 13:18, Philippe Mathieu-Daudé wrote:
>>> Hi David,
>>>
>>> On 8/1/25 14:51, David Woodhouse wrote:
>>>> On Tue, 2024-12-31 at 21:22 +0100, Philippe Mathieu-Daudé wrote:
>>>>>
>>>>> This change tidies up main thread management to be more
>>>>> flexible.
>>>>>
>>>>>    * The qemu_main global function pointer is a custom function
>>>>> for the
>>>>>      main thread, and it may now be NULL. When it is, the main
>>>>> thread
>>>>>      runs the main Qemu loop. This represents the traditional
>>>>> setup.
>>>>>    * When non-null, spawning the main Qemu event loop on a
>>>>> separate
>>>>>      thread is now done centrally rather than inside the Cocoa
>>>>> UI code.
>>>>>    * For most platforms, qemu_main is indeed NULL by default,
>>>>> but on
>>>>>      Darwin, it defaults to a function that runs the CFRunLoop.
>>>>>    * The Cocoa UI sets qemu_main to a function which runs the
>>>>>      NSApplication event handling runloop, as is usual for a
>>>>> Cocoa app.
>>>>>    * The SDL UI overrides the qemu_main function to NULL, thus
>>>>>      specifying that Qemu's main loop must run on the main
>>>>>      thread.
>>>>>    * The GTK UI also overrides the qemu_main function to NULL.
>>>>>    * For other UIs, or in the absence of UIs, the platform's
>>>>> default
>>>>>      behaviour is followed.
>>>>
>>>> When exiting an emulated Xen guest with <Ctrl-a x> on the
>>>> console, I
>>>> now see:
>>>>
>>>> (gdb) run
>>>> Starting program: /home/dwmw2/git/qemu/ball/qemu-system-x86_64 -
>>>> display none -vga none -serial mon:stdio -machine q35 -accel
>>>> kvm,xen-
>>>> version=0x4000a,kernel-irqchip=split -smp 2 -kernel /home/dwmw2/
>>>> avocado/data/cache/by_name/bzImage -append printk.time=0\
>>>> root=/dev/
>>>> xvda\ console=ttyS0\ xen_emul_unplug=ide-disks\
>>>> xen_no_vector_callback\ noapic\ loglevel=0 -drive
>>>> file=/home/dwmw2/
>>>> avocado/data/cache/by_name/
>>>> rootfs.ext4,if=none,snapshot=on,format=raw,id=drv0 -device xen-
>>>> disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -
>>>> netdev
>>>> user,id=unet,hostfwd=:127.0.0.1:0-:22
>>>>
>>>> Starting syslogd: OK
>>>> Starting klogd: OK
>>>> Running sysctl: OK
>>>> Saving 256 bits of non-creditable seed for next boot
>>>> Starting network: OK
>>>> Starting dhcpcd...
>>>> no such user dhcpcd
>>>> dhcpcd-9.4.1 starting
>>>> no interfaces have a carrier
>>>> forked to background, child pid 111
>>>> Starting dropbear sshd: OK
>>>> #
>>>> QEMU: Terminated
>>>> qemu-system-x86_64: ../block/block-backend.c:1290: blk_in_drain:
>>>> Assertion `qemu_in_main_thread()' failed.
>>>>
>>>> Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted.
>>>> 0x00007ffff5ffc724 in __pthread_kill_implementation () from
>>>> /lib64/
>>>> libc.so.6
>>>> (gdb) bt
>>>> #0  0x00007ffff5ffc724 in __pthread_kill_implementation () at
>>>> /lib64/
>>>> libc.so.6
>>>> #1  0x00007ffff5fa3d1e in raise () at /lib64/libc.so.6
>>>> #2  0x00007ffff5f8b942 in abort () at /lib64/libc.so.6
>>>> #3  0x00007ffff5f8b85e in __assert_fail_base.cold () at
>>>> /lib64/libc.so.6
>>>> #4  0x00007ffff5f9be47 in __assert_fail () at /lib64/libc.so.6
>>>> #5  0x0000555555abf911 in blk_in_drain (blk=0x555557ca6680)
>>>>       at ../block/block-backend.c:1290
>>>> #6  0x000055555593410c in xen_block_dataplane_stop
>>>> (dataplane=0x555558982950)
>>>>       at ../hw/block/dataplane/xen-block.c:695
>>>> #7  0x000055555593441a in xen_block_dataplane_stop
>>>> (dataplane=<optimized out>)
>>>>       at ../hw/block/dataplane/xen-block.c:689
>>>> #8  0x00005555555dfd5e in xen_block_disconnect
>>>>       (xendev=xendev@entry=0x55555880aa60, errp=<optimized out>)
>>>>       at ../hw/block/xen-block.c:172
>>>> #9  0x00005555555dfeca in xen_block_unrealize
>>>> (xendev=0x55555880aa60)
>>>>       at ../hw/block/xen-block.c:282
>>>> #10 0x000055555578ef71 in xen_device_unrealize (dev=<optimized
>>>> out>)
>>>>       at ../hw/xen/xen-bus.c:978
>>>> #11 0x0000555555bfe65f in notifier_list_notify (list=<optimized
>>>> out>,
>>>> data=0x0)
>>>>       at ../util/notify.c:39
>>>> #12 0x00007ffff5fa6461 in __run_exit_handlers () at
>>>> /lib64/libc.so.6
>>>> #13 0x00007ffff5fa652e in exit () at /lib64/libc.so.6
>>>> #14 0x0000555555b523dc in qemu_default_main
>>>> (opaque=opaque@entry=0x0)
>>>> #15 0x00005555555609c0 in main (argc=<optimized out>,
>>>> argv=<optimized
>>>> out>) at ../system/main.c:76
>>>>
>>>
>>> Is this still an issue?
>>
>> Likely fixed by commit e7bc0204 ("system/runstate:
>> Fix regression, clarify BQL status of exit notifiers"), so
>> I'm closing https://gitlab.com/qemu-project/qemu/-/issues/2771.
> 
> Indeed. I think I was assuming the explicit Resolves: tag in that
> commit was going to magically close the issue when it was merged.
> Should I have closed it manually?

It should have been closed automatically. Maybe some transient
problem on GitLab side ¯\_(ツ)_/¯


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling
  2025-04-01 11:58           ` Philippe Mathieu-Daudé
@ 2025-04-01 12:00             ` David Woodhouse
  0 siblings, 0 replies; 38+ messages in thread
From: David Woodhouse @ 2025-04-01 12:00 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: Phil Dennis-Jordan, Akihiko Odaki

[-- Attachment #1: Type: text/plain, Size: 6209 bytes --]

On Tue, 2025-04-01 at 13:58 +0200, Philippe Mathieu-Daudé wrote:
> On 1/4/25 13:43, David Woodhouse wrote:
> > On Tue, 2025-04-01 at 13:30 +0200, Philippe Mathieu-Daudé wrote:
> > > On 1/4/25 13:18, Philippe Mathieu-Daudé wrote:
> > > > Hi David,
> > > > 
> > > > On 8/1/25 14:51, David Woodhouse wrote:
> > > > > On Tue, 2024-12-31 at 21:22 +0100, Philippe Mathieu-Daudé
> > > > > wrote:
> > > > > > 
> > > > > > This change tidies up main thread management to be more
> > > > > > flexible.
> > > > > > 
> > > > > >    * The qemu_main global function pointer is a custom
> > > > > > function
> > > > > > for the
> > > > > >      main thread, and it may now be NULL. When it is, the
> > > > > > main
> > > > > > thread
> > > > > >      runs the main Qemu loop. This represents the
> > > > > > traditional
> > > > > > setup.
> > > > > >    * When non-null, spawning the main Qemu event loop on a
> > > > > > separate
> > > > > >      thread is now done centrally rather than inside the
> > > > > > Cocoa
> > > > > > UI code.
> > > > > >    * For most platforms, qemu_main is indeed NULL by
> > > > > > default,
> > > > > > but on
> > > > > >      Darwin, it defaults to a function that runs the
> > > > > > CFRunLoop.
> > > > > >    * The Cocoa UI sets qemu_main to a function which runs
> > > > > > the
> > > > > >      NSApplication event handling runloop, as is usual for
> > > > > > a
> > > > > > Cocoa app.
> > > > > >    * The SDL UI overrides the qemu_main function to NULL,
> > > > > > thus
> > > > > >      specifying that Qemu's main loop must run on the main
> > > > > >      thread.
> > > > > >    * The GTK UI also overrides the qemu_main function to
> > > > > > NULL.
> > > > > >    * For other UIs, or in the absence of UIs, the
> > > > > > platform's
> > > > > > default
> > > > > >      behaviour is followed.
> > > > > 
> > > > > When exiting an emulated Xen guest with <Ctrl-a x> on the
> > > > > console, I
> > > > > now see:
> > > > > 
> > > > > (gdb) run
> > > > > Starting program: /home/dwmw2/git/qemu/ball/qemu-system-
> > > > > x86_64 -
> > > > > display none -vga none -serial mon:stdio -machine q35 -accel
> > > > > kvm,xen-
> > > > > version=0x4000a,kernel-irqchip=split -smp 2 -kernel
> > > > > /home/dwmw2/
> > > > > avocado/data/cache/by_name/bzImage -append printk.time=0\
> > > > > root=/dev/
> > > > > xvda\ console=ttyS0\ xen_emul_unplug=ide-disks\
> > > > > xen_no_vector_callback\ noapic\ loglevel=0 -drive
> > > > > file=/home/dwmw2/
> > > > > avocado/data/cache/by_name/
> > > > > rootfs.ext4,if=none,snapshot=on,format=raw,id=drv0 -device
> > > > > xen-
> > > > > disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet
> > > > > -
> > > > > netdev
> > > > > user,id=unet,hostfwd=:127.0.0.1:0-:22
> > > > > 
> > > > > Starting syslogd: OK
> > > > > Starting klogd: OK
> > > > > Running sysctl: OK
> > > > > Saving 256 bits of non-creditable seed for next boot
> > > > > Starting network: OK
> > > > > Starting dhcpcd...
> > > > > no such user dhcpcd
> > > > > dhcpcd-9.4.1 starting
> > > > > no interfaces have a carrier
> > > > > forked to background, child pid 111
> > > > > Starting dropbear sshd: OK
> > > > > #
> > > > > QEMU: Terminated
> > > > > qemu-system-x86_64: ../block/block-backend.c:1290:
> > > > > blk_in_drain:
> > > > > Assertion `qemu_in_main_thread()' failed.
> > > > > 
> > > > > Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted.
> > > > > 0x00007ffff5ffc724 in __pthread_kill_implementation () from
> > > > > /lib64/
> > > > > libc.so.6
> > > > > (gdb) bt
> > > > > #0  0x00007ffff5ffc724 in __pthread_kill_implementation () at
> > > > > /lib64/
> > > > > libc.so.6
> > > > > #1  0x00007ffff5fa3d1e in raise () at /lib64/libc.so.6
> > > > > #2  0x00007ffff5f8b942 in abort () at /lib64/libc.so.6
> > > > > #3  0x00007ffff5f8b85e in __assert_fail_base.cold () at
> > > > > /lib64/libc.so.6
> > > > > #4  0x00007ffff5f9be47 in __assert_fail () at
> > > > > /lib64/libc.so.6
> > > > > #5  0x0000555555abf911 in blk_in_drain (blk=0x555557ca6680)
> > > > >       at ../block/block-backend.c:1290
> > > > > #6  0x000055555593410c in xen_block_dataplane_stop
> > > > > (dataplane=0x555558982950)
> > > > >       at ../hw/block/dataplane/xen-block.c:695
> > > > > #7  0x000055555593441a in xen_block_dataplane_stop
> > > > > (dataplane=<optimized out>)
> > > > >       at ../hw/block/dataplane/xen-block.c:689
> > > > > #8  0x00005555555dfd5e in xen_block_disconnect
> > > > >       (xendev=xendev@entry=0x55555880aa60, errp=<optimized
> > > > > out>)
> > > > >       at ../hw/block/xen-block.c:172
> > > > > #9  0x00005555555dfeca in xen_block_unrealize
> > > > > (xendev=0x55555880aa60)
> > > > >       at ../hw/block/xen-block.c:282
> > > > > #10 0x000055555578ef71 in xen_device_unrealize
> > > > > (dev=<optimized
> > > > > out>)
> > > > >       at ../hw/xen/xen-bus.c:978
> > > > > #11 0x0000555555bfe65f in notifier_list_notify
> > > > > (list=<optimized
> > > > > out>,
> > > > > data=0x0)
> > > > >       at ../util/notify.c:39
> > > > > #12 0x00007ffff5fa6461 in __run_exit_handlers () at
> > > > > /lib64/libc.so.6
> > > > > #13 0x00007ffff5fa652e in exit () at /lib64/libc.so.6
> > > > > #14 0x0000555555b523dc in qemu_default_main
> > > > > (opaque=opaque@entry=0x0)
> > > > > #15 0x00005555555609c0 in main (argc=<optimized out>,
> > > > > argv=<optimized
> > > > > out>) at ../system/main.c:76
> > > > > 
> > > > 
> > > > Is this still an issue?
> > > 
> > > Likely fixed by commit e7bc0204 ("system/runstate:
> > > Fix regression, clarify BQL status of exit notifiers"), so
> > > I'm closing https://gitlab.com/qemu-project/qemu/-/issues/2771.
> > 
> > Indeed. I think I was assuming the explicit Resolves: tag in that
> > commit was going to magically close the issue when it was merged.
> > Should I have closed it manually?
> 
> It should have been closed automatically. Maybe some transient
> problem on GitLab side ¯\_(ツ)_/¯

Ack. Thanks for confirming.


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2025-04-01 12:01 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-31 20:21 [PULL 00/29] Misc HW patches for 2024-12-31 Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 01/29] hw/pci-host/gpex: Allow more than 4 legacy IRQs Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 02/29] hw/misc/ivshmem-flat: Add ivshmem-flat device Philippe Mathieu-Daudé
2025-01-02 21:19   ` Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 03/29] hw/misc/ivshmem: Rename ivshmem to ivshmem-pci Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 04/29] hw/usb/uhci: checkpatch cleanup Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 05/29] hw/usb/uhci: Introduce and use register defines Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 06/29] hw/microblaze: Propagate CPU endianness to microblaze_load_kernel() Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 07/29] hw/i386: Mark devices as little-endian Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 08/29] hw/tricore: " Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 09/29] hw/openrisc: Mark devices as big-endian Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 10/29] hw/sparc: " Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 11/29] hw/net/xilinx_ethlite: Convert some debug logs to trace events Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 12/29] hw/net/xilinx_ethlite: Remove unuseful debug logs Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 13/29] hw/net/xilinx_ethlite: Update QOM style Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 14/29] hw/net/xilinx_ethlite: Correct maximum RX buffer size Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 15/29] hw/net/xilinx_ethlite: Rename rxbuf -> port_index Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 16/29] fw_cfg: Don't set callback_opaque NULL in fw_cfg_modify_bytes_read() Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 17/29] hw/misc/vmcoreinfo: Declare QOM type using DEFINE_TYPES macro Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 18/29] hw/misc/vmcoreinfo: Rename opaque pointer as 'opaque' Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 19/29] hw/i386/amd_iommu: Simplify non-KVM checks on XTSup feature Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 20/29] hw/block/virtio-blk: Replaces request free function with g_free Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 21/29] hw/usb/hcd-xhci-pci: Move msi/msix properties from NEC to superclass Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 22/29] hw/usb/hcd-xhci: Unimplemented/guest error logging for port MMIO Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 23/29] ui & main loop: Redesign of system-specific main thread event handling Philippe Mathieu-Daudé
2025-01-08 13:51   ` David Woodhouse
2025-04-01 11:18     ` Philippe Mathieu-Daudé
2025-04-01 11:30       ` Philippe Mathieu-Daudé
2025-04-01 11:43         ` David Woodhouse
2025-04-01 11:58           ` Philippe Mathieu-Daudé
2025-04-01 12:00             ` David Woodhouse
2024-12-31 20:22 ` [PULL 24/29] hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework support Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 25/29] hw/display/apple-gfx: Adds PCI implementation Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 26/29] hw/display/apple-gfx: Adds configurable mode list Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 27/29] MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 28/29] net/vmnet: Pad short Ethernet frames Philippe Mathieu-Daudé
2024-12-31 20:22 ` [PULL 29/29] hw/display/qxl: Do not use C99 // comments Philippe Mathieu-Daudé
2025-01-01 23:41 ` [PULL 00/29] Misc HW patches for 2024-12-31 Stefan Hajnoczi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).