Skip to contentSkip to conversation

pci: Cleanups & preparations for KVM device assignment

PATCH Applied Jan Kiszka 6 participants 88 messages Jun 4, 2012 – Jun 10, 2012

v1 of 2 Applied Latest is v2 →

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

cover pci: Cleanups & preparations for KVM device assignment

Besides some smaller cleanups, this series has two main topics:

The first is the already posted PCI IRQ routing lookup and notifier. The lookup has been based on the cached routing Michael suggested also for emulated devices. However, this still introduces a new callback and keeps the bus irq_count untouched due to the vmstate complications when changing it.

The second half refactors PCI device address parsing, introducing an universal parsing function. It is then used to provide a new qdev property that accepts fully qualified PCI addresses (domain:bus:device. function).

These two major changes will help refactoring PCI device assignment in qemu-kvm in order to upstream it soon. But also the upcoming VFIO-based assignment should be able to benefit.

Jan Kiszka (13):
pci: Refactor pci_change_irq_level
pci: Fold pci_bus_new_inplace into pci_bus_new
pci: Introduce cached device INTx routing
pci: Rename map_irq to route_pin
pci: Add pci_device_route_intx_to_irq
pci: Add INTx routing notifier
pci: Make domain and bus unsigned in pci_read_devaddr
pci: Export pci_parse_devaddr instead of pci_read_devaddr
pci: Introduce and apply PCIDeviceAddress
pci: Fix coding style of pci_parse_devaddr
Move pci_parse_devaddr to qdev-properties
qdev-properties: Use qemu_parse_pci_devaddr for pci-devfn property
qdev-properties: Add pci-devaddr property

 hw/alpha_sys.h          |    2 +-
 hw/alpha_typhoon.c      |    4 +-
 hw/apb_pci.c            |    6 +-
 hw/bonito.c             |    2 +-
 hw/dec_pci.c            |    2 +-
 hw/grackle_pci.c        |    1 +
 hw/gt64xxx.c            |    1 +
 hw/ioh3420.c            |    5 +-
 hw/ioh3420.h            |    3 +-
 hw/pci-hotplug.c        |   33 +++++--
 hw/pci.c                |  212 ++++++++++++++++++++++-------------------------
 hw/pci.h                |   40 +++++++---
 hw/pci_bridge.c         |   18 +++-
 hw/pci_bridge.h         |    4 +-
 hw/pci_bridge_dev.c     |    7 +-
 hw/pci_internals.h      |    5 +-
 hw/piix_pci.c           |   25 +++++-
 hw/ppc4xx_pci.c         |    2 +-
 hw/ppce500_pci.c        |    2 +-
 hw/prep_pci.c           |    2 +-
 hw/qdev-properties.c    |  142 ++++++++++++++++++++++++++++----
 hw/qdev.h               |   10 ++
 hw/sh_pci.c             |    2 +-
 hw/spapr_pci.c          |    2 +-
 hw/unin_pci.c           |    4 +-
 hw/versatile_pci.c      |    2 +-
 hw/xio3130_downstream.c |    5 +-
 hw/xio3130_downstream.h |    3 +-
 hw/xio3130_upstream.c   |    5 +-
 hw/xio3130_upstream.h   |    3 +-
 qemu-common.h           |    7 ++
 31 files changed, 371 insertions(+), 190 deletions(-)
Signature · 1 line
1.7.3.4
author
#1 lore raw

PATCH 1/13 pci: Refactor pci_change_irq_level

Align the bus traversal in pci_change_irq_level to other functions. They use PCIBus:parent_dev to detect the root.

---
 hw/pci.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
hw/pci.c +4 -4
index c1ebdde..893f89c 100644
@@ -115,13 +115,13 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
 static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
 {
     PCIBus *bus;
-    for (;;) {
+
+    do {
         bus = pci_dev->bus;
         irq_num = bus->map_irq(pci_dev, irq_num);
-        if (bus->set_irq)
-            break;
         pci_dev = bus->parent_dev;
-    }
+    } while (pci_dev);
+
     bus->irq_count[irq_num] += change;
     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
 }
Signature · 1 line
1.7.3.4
#2 lore raw

Re: [Qemu-devel] [PATCH 01/13] pci: Refactor pci_change_irq_level

Quoted 4 lines · Jan Kiszka

Align the bus traversal in pci_change_irq_level to other functions. They use PCIBus:parent_dev to detect the root.

Applied.

Quoted 28 lines
---
 hw/pci.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
hw/pci.c +4 -4
index c1ebdde..893f89c 100644
@@ -115,13 +115,13 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
 static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
 {
     PCIBus *bus;
-    for (;;) {
+
+    do {
         bus = pci_dev->bus;
         irq_num = bus->map_irq(pci_dev, irq_num);
-        if (bus->set_irq)
-            break;
         pci_dev = bus->parent_dev;
-    }
+    } while (pci_dev);
+
     bus->irq_count[irq_num] += change;
     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
 }
Signature · 1 line
1.7.3.4
author
#3 lore raw

PATCH 2/13 pci: Fold pci_bus_new_inplace into pci_bus_new

In reply to Jan Kiszka

There are no external users for this function.

---
 hw/pci.c |   29 +++++++++++------------------
 hw/pci.h |    5 -----
 2 files changed, 11 insertions(+), 23 deletions(-)
hw/pci.c +11 -18
index 893f89c..33452ab 100644
@@ -259,36 +259,29 @@ int pci_find_domain(const PCIBus *bus)
     return -1;
 }
 
-void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io,
-                         uint8_t devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    uint8_t devfn_min)
 {
-    qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
+    PCIBus *bus;
+
+    bus = g_malloc0(sizeof(*bus));
+    bus->qbus.qdev_allocated = 1;
+
     assert(PCI_FUNC(devfn_min) == 0);
     bus->devfn_min = devfn_min;
     bus->address_space_mem = address_space_mem;
     bus->address_space_io = address_space_io;
 
+    qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
+
     /* host bridge */
     QLIST_INIT(&bus->child);
     pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
 
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
-}
-
-PCIBus *pci_bus_new(DeviceState *parent, const char *name,
-                    MemoryRegion *address_space_mem,
-                    MemoryRegion *address_space_io,
-                    uint8_t devfn_min)
-{
-    PCIBus *bus;
 
-    bus = g_malloc0(sizeof(*bus));
-    bus->qbus.qdev_allocated = 1;
-    pci_bus_new_inplace(bus, parent, name, address_space_mem,
-                        address_space_io, devfn_min);
     return bus;
 }
 
hw/pci.h +0 -5
index c3cacce..7eaf90b 100644
@@ -285,11 +285,6 @@ typedef enum {
 
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
-void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io,
-                         uint8_t devfn_min);
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
Signature · 1 line
1.7.3.4
#4 lore raw

Re: [Qemu-devel] [PATCH 02/13] pci: Fold pci_bus_new_inplace into pci_bus_new

Am 04.06.2012 10:52, schrieb Jan Kiszka:

Quoted 3 lines

There are no external users for this function.

Nack, please take a look at my recent prep_pci RFC series. Instead of dropping _inplace we need to convert all PCI host controllers to initialize the bus in-place for the QOM realize model to work.

Andreas

Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
#5 lore raw

Re: [Qemu-devel] [PATCH 02/13] pci: Fold pci_bus_new_inplace into pci_bus_new

Quoted 8 lines · Andreas Färber

Am 04.06.2012 10:52, schrieb Jan Kiszka:

Quoted 3 lines

There are no external users for this function.

Nack, please take a look at my recent prep_pci RFC series. Instead of dropping _inplace we need to convert all PCI host controllers to initialize the bus in-place for the QOM realize model to work.

No problem, I can drop this patch. Was just an observation based on the in-tree history.

Jan

author
#6 lore raw

PATCH 3/13 pci: Introduce cached device INTx routing

In reply to Jan Kiszka

Based on the original version by Michael Tsirkin: Instead of traversing the PCI bus hierarchy from a device to the host bridge, cache this path in PCIDevice and use it directly on interrupt delivery. This will specifically pay off with more complex topologies than the current single host bus.

---
 hw/pci.c |   53 ++++++++++++++++++++++++++++++++++++++++++++---------
 hw/pci.h |    4 ++++
 2 files changed, 48 insertions(+), 9 deletions(-)
hw/pci.c +44 -9
index 33452ab..771fb39 100644
@@ -68,6 +68,8 @@ static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
 static void pci_del_option_rom(PCIDevice *pdev);
+static void pci_for_each_device_under_bus(PCIBus *bus,
+                                          void (*fn)(PCIBus *b, PCIDevice *d));
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
@@ -112,18 +114,49 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
 	d->irq_state |= level << irq_num;
 }
 
-static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
+static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
 {
-    PCIBus *bus;
+    int pin, output_pin;
+    PCIDevice *pci_dev;
+
+    /* We might be too early, i.e. before pci_bus_irqs was called.
+     * We will be called again when this happened. */
+    if (!bus->map_irq) {
+        return;
+    }
+
+    for (pin = 0; pin < PCI_NUM_PINS; pin++) {
+        pci_dev = dev;
+        output_pin = pin;
+        do {
+            bus = pci_dev->bus;
+            output_pin = bus->map_irq(pci_dev, output_pin);
+            pci_dev = bus->parent_dev;
+        } while (pci_dev);
+
+        dev->host_intx_pin[pin] = output_pin;
+        dev->host_bus = bus;
+    }
+}
+
+static void pci_set_bus_intx_routing(PCIBus *bus)
+{
+    PCIBus *sec;
+
+    pci_for_each_device_under_bus(bus, pci_set_device_intx_routing);
 
-    do {
-        bus = pci_dev->bus;
-        irq_num = bus->map_irq(pci_dev, irq_num);
-        pci_dev = bus->parent_dev;
-    } while (pci_dev);
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        pci_set_bus_intx_routing(sec);
+    }
+}
+
+static void pci_change_irq_level(PCIDevice *dev, int pin, int change)
+{
+    PCIBus *bus = dev->host_bus;
+    int output_pin = dev->host_intx_pin[pin];
 
-    bus->irq_count[irq_num] += change;
-    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
+    bus->irq_count[output_pin] += change;
+    bus->set_irq(bus->irq_opaque, output_pin, bus->irq_count[output_pin] != 0);
 }
 
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
@@ -293,6 +326,7 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
     bus->irq_opaque = irq_opaque;
     bus->nirq = nirq;
     bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
+    pci_set_bus_intx_routing(bus);
 }
 
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
@@ -798,6 +832,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     bus->devices[devfn] = pci_dev;
     pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
     pci_dev->version_id = 2; /* Current pci device vmstate version */
+    pci_set_device_intx_routing(bus, pci_dev);
     return pci_dev;
 }
 
hw/pci.h +4 -0
index 7eaf90b..c4fd863 100644
@@ -211,6 +211,10 @@ struct PCIDevice {
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
     uint8_t irq_state;
 
+    /* Used internally by PCI code to cache the interrupt routing */
+    PCIBus *host_bus;
+    int host_intx_pin[PCI_NUM_PINS];
+
     /* Capability bits */
     uint32_t cap_present;
 
Signature · 1 line
1.7.3.4
#7 lore raw

Re: [Qemu-devel] [PATCH 03/13] pci: Introduce cached device INTx routing

Quoted 7 lines · Jan Kiszka

Based on the original version by Michael Tsirkin: Instead of traversing the PCI bus hierarchy from a device to the host bridge, cache this path in PCIDevice and use it directly on interrupt delivery. This will specifically pay off with more complex topologies than the current single host bus.

OK, I applied this. I still think we should go the extra mile and cache the final IRQ not just the root intx. But that can be a patch on top.

Quoted 98 lines
---
 hw/pci.c |   53 ++++++++++++++++++++++++++++++++++++++++++++---------
 hw/pci.h |    4 ++++
 2 files changed, 48 insertions(+), 9 deletions(-)
hw/pci.c +44 -9
index 33452ab..771fb39 100644
@@ -68,6 +68,8 @@ static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
 static void pci_del_option_rom(PCIDevice *pdev);
+static void pci_for_each_device_under_bus(PCIBus *bus,
+                                          void (*fn)(PCIBus *b, PCIDevice *d));
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
@@ -112,18 +114,49 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
 	d->irq_state |= level << irq_num;
 }
 
-static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
+static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
 {
-    PCIBus *bus;
+    int pin, output_pin;
+    PCIDevice *pci_dev;
+
+    /* We might be too early, i.e. before pci_bus_irqs was called.
+     * We will be called again when this happened. */
+    if (!bus->map_irq) {
+        return;
+    }
+
+    for (pin = 0; pin < PCI_NUM_PINS; pin++) {
+        pci_dev = dev;
+        output_pin = pin;
+        do {
+            bus = pci_dev->bus;
+            output_pin = bus->map_irq(pci_dev, output_pin);
+            pci_dev = bus->parent_dev;
+        } while (pci_dev);
+
+        dev->host_intx_pin[pin] = output_pin;
+        dev->host_bus = bus;
+    }
+}
+
+static void pci_set_bus_intx_routing(PCIBus *bus)
+{
+    PCIBus *sec;
+
+    pci_for_each_device_under_bus(bus, pci_set_device_intx_routing);
 
-    do {
-        bus = pci_dev->bus;
-        irq_num = bus->map_irq(pci_dev, irq_num);
-        pci_dev = bus->parent_dev;
-    } while (pci_dev);
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        pci_set_bus_intx_routing(sec);
+    }
+}
+
+static void pci_change_irq_level(PCIDevice *dev, int pin, int change)
+{
+    PCIBus *bus = dev->host_bus;
+    int output_pin = dev->host_intx_pin[pin];
 
-    bus->irq_count[irq_num] += change;
-    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
+    bus->irq_count[output_pin] += change;
+    bus->set_irq(bus->irq_opaque, output_pin, bus->irq_count[output_pin] != 0);
 }
 
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
@@ -293,6 +326,7 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
     bus->irq_opaque = irq_opaque;
     bus->nirq = nirq;
     bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
+    pci_set_bus_intx_routing(bus);
 }
 
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
@@ -798,6 +832,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     bus->devices[devfn] = pci_dev;
     pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
     pci_dev->version_id = 2; /* Current pci device vmstate version */
+    pci_set_device_intx_routing(bus, pci_dev);
     return pci_dev;
 }
 
hw/pci.h +0 -0
index 7eaf90b..c4fd863 100644

hw/pci.h struct PCIDevice { · line 217

Quoted 7 lines
hw/pci.h +4 -0
@@ -211,6 +211,10 @@ struct PCIDevice {
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
     uint8_t irq_state;
 
+    /* Used internally by PCI code to cache the interrupt routing */
+    PCIBus *host_bus;
+    int host_intx_pin[PCI_NUM_PINS];
+

A better name would be root_XXXX: host is an overloaded term. I applied such a patch.

Quoted 5 lines
hw/pci.h +0 -0
     /* Capability bits */
     uint32_t cap_present;
 
Signature · 1 line
1.7.3.4
author
#8 lore raw

PATCH 4/13 pci: Rename map_irq to route_pin

In reply to Jan Kiszka

To avoid confusion with the board-level IRQ the host bridge triggers on output, rename the per-bridge routing function for the INTx pins to pci_route_pin_fn. Also adjust variable names of that type. And rename pci_bridge_map_irq to pci_bridge_prepare, which better reflects the job of that function.

---
 hw/alpha_sys.h          |    2 +-
 hw/alpha_typhoon.c      |    2 +-
 hw/apb_pci.c            |    4 ++--
 hw/dec_pci.c            |    2 +-
 hw/ioh3420.c            |    5 +++--
 hw/ioh3420.h            |    3 ++-
 hw/pci.c                |   14 ++++++++------
 hw/pci.h                |    8 +++++---
 hw/pci_bridge.c         |   10 +++++-----
 hw/pci_bridge.h         |    4 ++--
 hw/pci_bridge_dev.c     |    7 ++++---
 hw/pci_internals.h      |    4 ++--
 hw/xio3130_downstream.c |    5 +++--
 hw/xio3130_downstream.h |    3 ++-
 hw/xio3130_upstream.c   |    5 +++--
 hw/xio3130_upstream.h   |    3 ++-
 16 files changed, 46 insertions(+), 35 deletions(-)
hw/alpha_sys.h +1 -1
index de40f8b..ddeb360 100644
@@ -12,7 +12,7 @@
 
 
 PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4],
-                     pci_map_irq_fn);
+                     pci_route_pin_fn);
 
 /* alpha_pci.c.  */
 extern const MemoryRegionOps alpha_pci_bw_io_ops;
hw/alpha_typhoon.c +1 -1
index 872e112..d5193bb 100644
@@ -693,7 +693,7 @@ static void typhoon_alarm_timer(void *opaque)
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                      qemu_irq *p_rtc_irq,
-                     CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
+                     CPUAlphaState *cpus[4], pci_route_pin_fn sys_map_irq)
 {
     const uint64_t MB = 1024 * 1024;
     const uint64_t GB = 1024 * MB;
hw/apb_pci.c +2 -2
index c28411a..57ead09 100644
@@ -392,7 +392,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
+    pci_bridge_prepare(br, "Advanced PCI Bus secondary bridge 1",
                        pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
     *bus2 = pci_bridge_get_sec_bus(br);
@@ -400,7 +400,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
+    pci_bridge_prepare(br, "Advanced PCI Bus secondary bridge 2",
                        pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
     *bus3 = pci_bridge_get_sec_bus(br);
hw/dec_pci.c +1 -1
index 37337bf..be63ac7 100644
@@ -81,7 +81,7 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
     dev = pci_create_multifunction(parent_bus, devfn, false,
                                    "dec-21154-p2p-bridge");
     br = DO_UPCAST(PCIBridge, dev, dev);
-    pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
+    pci_bridge_prepare(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
     qdev_init_nofail(&dev->qdev);
     return pci_bridge_get_sec_bus(br);
 }
hw/ioh3420.c +3 -2
index 1632d31..21bc1fb 100644
@@ -164,7 +164,8 @@ static int ioh3420_exitfn(PCIDevice *d)
 }
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                         const char *bus_name, pci_map_irq_fn map_irq,
+                         const char *bus_name,
+                         pci_route_pin_fn route_intx_pin,
                          uint8_t port, uint8_t chassis, uint16_t slot)
 {
     PCIDevice *d;
@@ -178,7 +179,7 @@ PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_prop_set_uint8(qdev, "chassis", chassis);
     qdev_prop_set_uint16(qdev, "slot", slot);
hw/ioh3420.h +2 -1
index 68c523a..091bef4 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                       const char *bus_name, pci_map_irq_fn map_irq,
+                       const char *bus_name,
+                       pci_route_pin_fn route_intx_pin,
                        uint8_t port, uint8_t chassis, uint16_t slot);
 
 #endif /* QEMU_IOH3420_H */
hw/pci.c +8 -6
index 771fb39..9a2b4a3 100644
@@ -121,7 +121,7 @@ static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
 
     /* We might be too early, i.e. before pci_bus_irqs was called.
      * We will be called again when this happened. */
-    if (!bus->map_irq) {
+    if (!bus->route_intx_pin) {
         return;
     }
 
@@ -130,7 +130,7 @@ static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
         output_pin = pin;
         do {
             bus = pci_dev->bus;
-            output_pin = bus->map_irq(pci_dev, output_pin);
+            output_pin = bus->route_intx_pin(pci_dev, output_pin);
             pci_dev = bus->parent_dev;
         } while (pci_dev);
 
@@ -318,11 +318,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
     return bus;
 }
 
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
+                  pci_route_pin_fn route_intx_pin,
                   void *irq_opaque, int nirq)
 {
     bus->set_irq = set_irq;
-    bus->map_irq = map_irq;
+    bus->route_intx_pin = route_intx_pin;
     bus->irq_opaque = irq_opaque;
     bus->nirq = nirq;
     bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
@@ -337,7 +338,8 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
 }
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         pci_set_irq_fn set_irq,
+                         pci_route_pin_fn route_intx_pin,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
@@ -347,7 +349,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 
     bus = pci_bus_new(parent, name, address_space_mem,
                       address_space_io, devfn_min);
-    pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
+    pci_bus_irqs(bus, set_irq, route_intx_pin, irq_opaque, nirq);
     return bus;
 }
 
hw/pci.h +5 -3
index c4fd863..5b54e2d 100644
@@ -279,7 +279,7 @@ MemoryRegion *pci_address_space(PCIDevice *dev);
 MemoryRegion *pci_address_space_io(PCIDevice *dev);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
-typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+typedef int (*pci_route_pin_fn)(PCIDevice *pci_dev, int pin);
 
 typedef enum {
     PCI_HOTPLUG_DISABLED,
@@ -293,12 +293,14 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     uint8_t devfn_min);
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
+                  pci_route_pin_fn route_intx_pin,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         pci_set_irq_fn set_irq,
+                         pci_route_pin_fn route_intx_pin,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
hw/pci_bridge.c +5 -5
index 866f0b6..7d13a85 100644
@@ -327,7 +327,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
-    sec_bus->map_irq = br->map_irq;
+    sec_bus->route_intx_pin = br->route_intx_pin;
     sec_bus->address_space_mem = &br->address_space_mem;
     memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
@@ -353,12 +353,12 @@ int pci_bridge_exitfn(PCIDevice *pci_dev)
 
 /*
  * before qdev initialization(qdev_init()), this function sets bus_name and
- * map_irq callback which are necessry for pci_bridge_initfn() to
+ * route_intx_pin callback which are necessry for pci_bridge_initfn() to
  * initialize bus.
  */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq)
+void pci_bridge_prepare(PCIBridge *br, const char* bus_name,
+                        pci_route_pin_fn route_intx_pin)
 {
-    br->map_irq = map_irq;
+    br->route_intx_pin = route_intx_pin;
     br->bus_name = bus_name;
 }
hw/pci_bridge.h +2 -2
index 84411a6..ac019a9 100644
@@ -52,8 +52,8 @@ int pci_bridge_exitfn(PCIDevice *pci_dev);
  * map_irq callback which are necessry for pci_bridge_initfn() to
  * initialize bus.
  */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq);
+void pci_bridge_prepare(PCIBridge *br, const char* bus_name,
+                        pci_route_pin_fn route_intx_pin);
 
 #endif  /* QEMU_PCI_BRIDGE_H */
 /*
hw/pci_bridge_dev.c +4 -3
index eccaa58..d5a14a9 100644
@@ -43,9 +43,9 @@ typedef struct PCIBridgeDev PCIBridgeDev;
 /* Mapping mandated by PCI-to-PCI Bridge architecture specification,
  * revision 1.2 */
 /* Table 9-1: Interrupt Binding for Devices Behind a Bridge */
-static int pci_bridge_dev_map_irq_fn(PCIDevice *dev, int irq_num)
+static int pci_bridge_dev_route_intx_pin(PCIDevice *dev, int pin)
 {
-    return (irq_num + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
+    return (pin + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
 }
 
 static int pci_bridge_dev_initfn(PCIDevice *dev)
@@ -53,7 +53,8 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
-    pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
+
+    pci_bridge_prepare(br, NULL, pci_bridge_dev_route_intx_pin);
     err = pci_bridge_initfn(dev);
     if (err) {
         goto bridge_error;
hw/pci_internals.h +2 -2
index 96690b7..be5594b 100644
@@ -18,7 +18,7 @@ struct PCIBus {
     BusState qbus;
     uint8_t devfn_min;
     pci_set_irq_fn set_irq;
-    pci_map_irq_fn map_irq;
+    pci_route_pin_fn route_intx_pin;
     pci_hotplug_fn hotplug;
     DeviceState *hotplug_qdev;
     void *irq_opaque;
@@ -59,7 +59,7 @@ struct PCIBridge {
     MemoryRegion alias_pref_mem;
     MemoryRegion alias_mem;
     MemoryRegion alias_io;
-    pci_map_irq_fn map_irq;
+    pci_route_pin_fn route_intx_pin;
     const char *bus_name;
 };
 
hw/xio3130_downstream.c +3 -2
index 319624f..d334e16 100644
@@ -128,7 +128,8 @@ static int xio3130_downstream_exitfn(PCIDevice *d)
 }
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  const char *bus_name,
+                                  pci_route_pin_fn route_intx_pin,
                                   uint8_t port, uint8_t chassis,
                                   uint16_t slot)
 {
@@ -144,7 +145,7 @@ PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_prop_set_uint8(qdev, "chassis", chassis);
     qdev_prop_set_uint16(qdev, "slot", slot);
hw/xio3130_downstream.h +2 -1
index 010487f..c4941bd 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  const char *bus_name,
+                                  pci_route_pin_fn route_intx_pin,
                                   uint8_t port, uint8_t chassis,
                                   uint16_t slot);
 
hw/xio3130_upstream.c +3 -2
index 34a99bb..39a8189 100644
@@ -110,7 +110,8 @@ static int xio3130_upstream_exitfn(PCIDevice *d)
 }
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                             const char *bus_name, pci_map_irq_fn map_irq,
+                             const char *bus_name,
+                             pci_route_pin_fn route_intx_pin,
                              uint8_t port)
 {
     PCIDevice *d;
@@ -124,7 +125,7 @@ PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_init_nofail(qdev);
 
hw/xio3130_upstream.h +2 -1
index e996997..bf3784e 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                const char *bus_name, pci_map_irq_fn map_irq,
+                                const char *bus_name,
+                                pci_route_pin_fn route_intx_pin,
                                 uint8_t port);
 
 #endif /* QEMU_XIO3130_H */
Signature · 1 line
1.7.3.4
#9 lore raw

Re: [Qemu-devel] [PATCH 04/13] pci: Rename map_irq to route_pin

Quoted 7 lines · Jan Kiszka

To avoid confusion with the board-level IRQ the host bridge triggers on output, rename the per-bridge routing function for the INTx pins to pci_route_pin_fn. Also adjust variable names of that type. And rename pci_bridge_map_irq to pci_bridge_prepare, which better reflects the job of that function.

Applied.

Quoted 372 lines
---
 hw/alpha_sys.h          |    2 +-
 hw/alpha_typhoon.c      |    2 +-
 hw/apb_pci.c            |    4 ++--
 hw/dec_pci.c            |    2 +-
 hw/ioh3420.c            |    5 +++--
 hw/ioh3420.h            |    3 ++-
 hw/pci.c                |   14 ++++++++------
 hw/pci.h                |    8 +++++---
 hw/pci_bridge.c         |   10 +++++-----
 hw/pci_bridge.h         |    4 ++--
 hw/pci_bridge_dev.c     |    7 ++++---
 hw/pci_internals.h      |    4 ++--
 hw/xio3130_downstream.c |    5 +++--
 hw/xio3130_downstream.h |    3 ++-
 hw/xio3130_upstream.c   |    5 +++--
 hw/xio3130_upstream.h   |    3 ++-
 16 files changed, 46 insertions(+), 35 deletions(-)
hw/alpha_sys.h +1 -1
index de40f8b..ddeb360 100644
@@ -12,7 +12,7 @@
 
 
 PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4],
-                     pci_map_irq_fn);
+                     pci_route_pin_fn);
 
 /* alpha_pci.c.  */
 extern const MemoryRegionOps alpha_pci_bw_io_ops;
hw/alpha_typhoon.c +1 -1
index 872e112..d5193bb 100644
@@ -693,7 +693,7 @@ static void typhoon_alarm_timer(void *opaque)
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                      qemu_irq *p_rtc_irq,
-                     CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
+                     CPUAlphaState *cpus[4], pci_route_pin_fn sys_map_irq)
 {
     const uint64_t MB = 1024 * 1024;
     const uint64_t GB = 1024 * MB;
hw/apb_pci.c +2 -2
index c28411a..57ead09 100644
@@ -392,7 +392,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
+    pci_bridge_prepare(br, "Advanced PCI Bus secondary bridge 1",
                        pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
     *bus2 = pci_bridge_get_sec_bus(br);
@@ -400,7 +400,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
+    pci_bridge_prepare(br, "Advanced PCI Bus secondary bridge 2",
                        pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
     *bus3 = pci_bridge_get_sec_bus(br);
hw/dec_pci.c +1 -1
index 37337bf..be63ac7 100644
@@ -81,7 +81,7 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
     dev = pci_create_multifunction(parent_bus, devfn, false,
                                    "dec-21154-p2p-bridge");
     br = DO_UPCAST(PCIBridge, dev, dev);
-    pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
+    pci_bridge_prepare(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
     qdev_init_nofail(&dev->qdev);
     return pci_bridge_get_sec_bus(br);
 }
hw/ioh3420.c +3 -2
index 1632d31..21bc1fb 100644
@@ -164,7 +164,8 @@ static int ioh3420_exitfn(PCIDevice *d)
 }
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                         const char *bus_name, pci_map_irq_fn map_irq,
+                         const char *bus_name,
+                         pci_route_pin_fn route_intx_pin,
                          uint8_t port, uint8_t chassis, uint16_t slot)
 {
     PCIDevice *d;
@@ -178,7 +179,7 @@ PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_prop_set_uint8(qdev, "chassis", chassis);
     qdev_prop_set_uint16(qdev, "slot", slot);
hw/ioh3420.h +2 -1
index 68c523a..091bef4 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                       const char *bus_name, pci_map_irq_fn map_irq,
+                       const char *bus_name,
+                       pci_route_pin_fn route_intx_pin,
                        uint8_t port, uint8_t chassis, uint16_t slot);
 
 #endif /* QEMU_IOH3420_H */
hw/pci.c +8 -6
index 771fb39..9a2b4a3 100644
@@ -121,7 +121,7 @@ static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
 
     /* We might be too early, i.e. before pci_bus_irqs was called.
      * We will be called again when this happened. */
-    if (!bus->map_irq) {
+    if (!bus->route_intx_pin) {
         return;
     }
 
@@ -130,7 +130,7 @@ static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
         output_pin = pin;
         do {
             bus = pci_dev->bus;
-            output_pin = bus->map_irq(pci_dev, output_pin);
+            output_pin = bus->route_intx_pin(pci_dev, output_pin);
             pci_dev = bus->parent_dev;
         } while (pci_dev);
 
@@ -318,11 +318,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
     return bus;
 }
 
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
+                  pci_route_pin_fn route_intx_pin,
                   void *irq_opaque, int nirq)
 {
     bus->set_irq = set_irq;
-    bus->map_irq = map_irq;
+    bus->route_intx_pin = route_intx_pin;
     bus->irq_opaque = irq_opaque;
     bus->nirq = nirq;
     bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
@@ -337,7 +338,8 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
 }
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         pci_set_irq_fn set_irq,
+                         pci_route_pin_fn route_intx_pin,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
@@ -347,7 +349,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 
     bus = pci_bus_new(parent, name, address_space_mem,
                       address_space_io, devfn_min);
-    pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
+    pci_bus_irqs(bus, set_irq, route_intx_pin, irq_opaque, nirq);
     return bus;
 }
 
hw/pci.h +5 -3
index c4fd863..5b54e2d 100644
@@ -279,7 +279,7 @@ MemoryRegion *pci_address_space(PCIDevice *dev);
 MemoryRegion *pci_address_space_io(PCIDevice *dev);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
-typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+typedef int (*pci_route_pin_fn)(PCIDevice *pci_dev, int pin);
 
 typedef enum {
     PCI_HOTPLUG_DISABLED,
@@ -293,12 +293,14 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     uint8_t devfn_min);
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
+                  pci_route_pin_fn route_intx_pin,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         pci_set_irq_fn set_irq,
+                         pci_route_pin_fn route_intx_pin,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
hw/pci_bridge.c +5 -5
index 866f0b6..7d13a85 100644
@@ -327,7 +327,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
-    sec_bus->map_irq = br->map_irq;
+    sec_bus->route_intx_pin = br->route_intx_pin;
     sec_bus->address_space_mem = &br->address_space_mem;
     memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
@@ -353,12 +353,12 @@ int pci_bridge_exitfn(PCIDevice *pci_dev)
 
 /*
  * before qdev initialization(qdev_init()), this function sets bus_name and
- * map_irq callback which are necessry for pci_bridge_initfn() to
+ * route_intx_pin callback which are necessry for pci_bridge_initfn() to
  * initialize bus.
  */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq)
+void pci_bridge_prepare(PCIBridge *br, const char* bus_name,
+                        pci_route_pin_fn route_intx_pin)
 {
-    br->map_irq = map_irq;
+    br->route_intx_pin = route_intx_pin;
     br->bus_name = bus_name;
 }
hw/pci_bridge.h +2 -2
index 84411a6..ac019a9 100644
@@ -52,8 +52,8 @@ int pci_bridge_exitfn(PCIDevice *pci_dev);
  * map_irq callback which are necessry for pci_bridge_initfn() to
  * initialize bus.
  */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq);
+void pci_bridge_prepare(PCIBridge *br, const char* bus_name,
+                        pci_route_pin_fn route_intx_pin);
 
 #endif  /* QEMU_PCI_BRIDGE_H */
 /*
hw/pci_bridge_dev.c +4 -3
index eccaa58..d5a14a9 100644
@@ -43,9 +43,9 @@ typedef struct PCIBridgeDev PCIBridgeDev;
 /* Mapping mandated by PCI-to-PCI Bridge architecture specification,
  * revision 1.2 */
 /* Table 9-1: Interrupt Binding for Devices Behind a Bridge */
-static int pci_bridge_dev_map_irq_fn(PCIDevice *dev, int irq_num)
+static int pci_bridge_dev_route_intx_pin(PCIDevice *dev, int pin)
 {
-    return (irq_num + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
+    return (pin + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
 }
 
 static int pci_bridge_dev_initfn(PCIDevice *dev)
@@ -53,7 +53,8 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
-    pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
+
+    pci_bridge_prepare(br, NULL, pci_bridge_dev_route_intx_pin);
     err = pci_bridge_initfn(dev);
     if (err) {
         goto bridge_error;
hw/pci_internals.h +2 -2
index 96690b7..be5594b 100644
@@ -18,7 +18,7 @@ struct PCIBus {
     BusState qbus;
     uint8_t devfn_min;
     pci_set_irq_fn set_irq;
-    pci_map_irq_fn map_irq;
+    pci_route_pin_fn route_intx_pin;
     pci_hotplug_fn hotplug;
     DeviceState *hotplug_qdev;
     void *irq_opaque;
@@ -59,7 +59,7 @@ struct PCIBridge {
     MemoryRegion alias_pref_mem;
     MemoryRegion alias_mem;
     MemoryRegion alias_io;
-    pci_map_irq_fn map_irq;
+    pci_route_pin_fn route_intx_pin;
     const char *bus_name;
 };
 
hw/xio3130_downstream.c +3 -2
index 319624f..d334e16 100644
@@ -128,7 +128,8 @@ static int xio3130_downstream_exitfn(PCIDevice *d)
 }
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  const char *bus_name,
+                                  pci_route_pin_fn route_intx_pin,
                                   uint8_t port, uint8_t chassis,
                                   uint16_t slot)
 {
@@ -144,7 +145,7 @@ PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_prop_set_uint8(qdev, "chassis", chassis);
     qdev_prop_set_uint16(qdev, "slot", slot);
hw/xio3130_downstream.h +2 -1
index 010487f..c4941bd 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  const char *bus_name,
+                                  pci_route_pin_fn route_intx_pin,
                                   uint8_t port, uint8_t chassis,
                                   uint16_t slot);
 
hw/xio3130_upstream.c +3 -2
index 34a99bb..39a8189 100644
@@ -110,7 +110,8 @@ static int xio3130_upstream_exitfn(PCIDevice *d)
 }
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                             const char *bus_name, pci_map_irq_fn map_irq,
+                             const char *bus_name,
+                             pci_route_pin_fn route_intx_pin,
                              uint8_t port)
 {
     PCIDevice *d;
@@ -124,7 +125,7 @@ PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_init_nofail(qdev);
 
hw/xio3130_upstream.h +2 -1
index e996997..bf3784e 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                const char *bus_name, pci_map_irq_fn map_irq,
+                                const char *bus_name,
+                                pci_route_pin_fn route_intx_pin,
                                 uint8_t port);
 
 #endif /* QEMU_XIO3130_H */
Signature · 1 line
1.7.3.4
#10 lore raw

Re: [Qemu-devel] [PATCH 04/13] pci: Rename map_irq to route_pin

In reply to Jan Kiszka
Quoted 7 lines · Jan Kiszka

To avoid confusion with the board-level IRQ the host bridge triggers on output, rename the per-bridge routing function for the INTx pins to pci_route_pin_fn. Also adjust variable names of that type. And rename pci_bridge_map_irq to pci_bridge_prepare, which better reflects the job of that function.

BTW there was a minor conflict when applying this, it would help me if you base future patches in this series on my pci branch.

Quoted 372 lines
---
 hw/alpha_sys.h          |    2 +-
 hw/alpha_typhoon.c      |    2 +-
 hw/apb_pci.c            |    4 ++--
 hw/dec_pci.c            |    2 +-
 hw/ioh3420.c            |    5 +++--
 hw/ioh3420.h            |    3 ++-
 hw/pci.c                |   14 ++++++++------
 hw/pci.h                |    8 +++++---
 hw/pci_bridge.c         |   10 +++++-----
 hw/pci_bridge.h         |    4 ++--
 hw/pci_bridge_dev.c     |    7 ++++---
 hw/pci_internals.h      |    4 ++--
 hw/xio3130_downstream.c |    5 +++--
 hw/xio3130_downstream.h |    3 ++-
 hw/xio3130_upstream.c   |    5 +++--
 hw/xio3130_upstream.h   |    3 ++-
 16 files changed, 46 insertions(+), 35 deletions(-)
hw/alpha_sys.h +1 -1
index de40f8b..ddeb360 100644
@@ -12,7 +12,7 @@
 
 
 PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4],
-                     pci_map_irq_fn);
+                     pci_route_pin_fn);
 
 /* alpha_pci.c.  */
 extern const MemoryRegionOps alpha_pci_bw_io_ops;
hw/alpha_typhoon.c +1 -1
index 872e112..d5193bb 100644
@@ -693,7 +693,7 @@ static void typhoon_alarm_timer(void *opaque)
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                      qemu_irq *p_rtc_irq,
-                     CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
+                     CPUAlphaState *cpus[4], pci_route_pin_fn sys_map_irq)
 {
     const uint64_t MB = 1024 * 1024;
     const uint64_t GB = 1024 * MB;
hw/apb_pci.c +2 -2
index c28411a..57ead09 100644
@@ -392,7 +392,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
+    pci_bridge_prepare(br, "Advanced PCI Bus secondary bridge 1",
                        pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
     *bus2 = pci_bridge_get_sec_bus(br);
@@ -400,7 +400,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
                                    "pbm-bridge");
     br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
+    pci_bridge_prepare(br, "Advanced PCI Bus secondary bridge 2",
                        pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
     *bus3 = pci_bridge_get_sec_bus(br);
hw/dec_pci.c +1 -1
index 37337bf..be63ac7 100644
@@ -81,7 +81,7 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
     dev = pci_create_multifunction(parent_bus, devfn, false,
                                    "dec-21154-p2p-bridge");
     br = DO_UPCAST(PCIBridge, dev, dev);
-    pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
+    pci_bridge_prepare(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
     qdev_init_nofail(&dev->qdev);
     return pci_bridge_get_sec_bus(br);
 }
hw/ioh3420.c +3 -2
index 1632d31..21bc1fb 100644
@@ -164,7 +164,8 @@ static int ioh3420_exitfn(PCIDevice *d)
 }
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                         const char *bus_name, pci_map_irq_fn map_irq,
+                         const char *bus_name,
+                         pci_route_pin_fn route_intx_pin,
                          uint8_t port, uint8_t chassis, uint16_t slot)
 {
     PCIDevice *d;
@@ -178,7 +179,7 @@ PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_prop_set_uint8(qdev, "chassis", chassis);
     qdev_prop_set_uint16(qdev, "slot", slot);
hw/ioh3420.h +2 -1
index 68c523a..091bef4 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                       const char *bus_name, pci_map_irq_fn map_irq,
+                       const char *bus_name,
+                       pci_route_pin_fn route_intx_pin,
                        uint8_t port, uint8_t chassis, uint16_t slot);
 
 #endif /* QEMU_IOH3420_H */
hw/pci.c +8 -6
index 771fb39..9a2b4a3 100644
@@ -121,7 +121,7 @@ static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
 
     /* We might be too early, i.e. before pci_bus_irqs was called.
      * We will be called again when this happened. */
-    if (!bus->map_irq) {
+    if (!bus->route_intx_pin) {
         return;
     }
 
@@ -130,7 +130,7 @@ static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
         output_pin = pin;
         do {
             bus = pci_dev->bus;
-            output_pin = bus->map_irq(pci_dev, output_pin);
+            output_pin = bus->route_intx_pin(pci_dev, output_pin);
             pci_dev = bus->parent_dev;
         } while (pci_dev);
 
@@ -318,11 +318,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
     return bus;
 }
 
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
+                  pci_route_pin_fn route_intx_pin,
                   void *irq_opaque, int nirq)
 {
     bus->set_irq = set_irq;
-    bus->map_irq = map_irq;
+    bus->route_intx_pin = route_intx_pin;
     bus->irq_opaque = irq_opaque;
     bus->nirq = nirq;
     bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
@@ -337,7 +338,8 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
 }
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         pci_set_irq_fn set_irq,
+                         pci_route_pin_fn route_intx_pin,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
@@ -347,7 +349,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 
     bus = pci_bus_new(parent, name, address_space_mem,
                       address_space_io, devfn_min);
-    pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
+    pci_bus_irqs(bus, set_irq, route_intx_pin, irq_opaque, nirq);
     return bus;
 }
 
hw/pci.h +5 -3
index c4fd863..5b54e2d 100644
@@ -279,7 +279,7 @@ MemoryRegion *pci_address_space(PCIDevice *dev);
 MemoryRegion *pci_address_space_io(PCIDevice *dev);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
-typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+typedef int (*pci_route_pin_fn)(PCIDevice *pci_dev, int pin);
 
 typedef enum {
     PCI_HOTPLUG_DISABLED,
@@ -293,12 +293,14 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     uint8_t devfn_min);
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
+                  pci_route_pin_fn route_intx_pin,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         pci_set_irq_fn set_irq,
+                         pci_route_pin_fn route_intx_pin,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
hw/pci_bridge.c +5 -5
index 866f0b6..7d13a85 100644
@@ -327,7 +327,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
-    sec_bus->map_irq = br->map_irq;
+    sec_bus->route_intx_pin = br->route_intx_pin;
     sec_bus->address_space_mem = &br->address_space_mem;
     memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
@@ -353,12 +353,12 @@ int pci_bridge_exitfn(PCIDevice *pci_dev)
 
 /*
  * before qdev initialization(qdev_init()), this function sets bus_name and
- * map_irq callback which are necessry for pci_bridge_initfn() to
+ * route_intx_pin callback which are necessry for pci_bridge_initfn() to
  * initialize bus.
  */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq)
+void pci_bridge_prepare(PCIBridge *br, const char* bus_name,
+                        pci_route_pin_fn route_intx_pin)
 {
-    br->map_irq = map_irq;
+    br->route_intx_pin = route_intx_pin;
     br->bus_name = bus_name;
 }
hw/pci_bridge.h +2 -2
index 84411a6..ac019a9 100644
@@ -52,8 +52,8 @@ int pci_bridge_exitfn(PCIDevice *pci_dev);
  * map_irq callback which are necessry for pci_bridge_initfn() to
  * initialize bus.
  */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq);
+void pci_bridge_prepare(PCIBridge *br, const char* bus_name,
+                        pci_route_pin_fn route_intx_pin);
 
 #endif  /* QEMU_PCI_BRIDGE_H */
 /*
hw/pci_bridge_dev.c +4 -3
index eccaa58..d5a14a9 100644
@@ -43,9 +43,9 @@ typedef struct PCIBridgeDev PCIBridgeDev;
 /* Mapping mandated by PCI-to-PCI Bridge architecture specification,
  * revision 1.2 */
 /* Table 9-1: Interrupt Binding for Devices Behind a Bridge */
-static int pci_bridge_dev_map_irq_fn(PCIDevice *dev, int irq_num)
+static int pci_bridge_dev_route_intx_pin(PCIDevice *dev, int pin)
 {
-    return (irq_num + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
+    return (pin + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
 }
 
 static int pci_bridge_dev_initfn(PCIDevice *dev)
@@ -53,7 +53,8 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
-    pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
+
+    pci_bridge_prepare(br, NULL, pci_bridge_dev_route_intx_pin);
     err = pci_bridge_initfn(dev);
     if (err) {
         goto bridge_error;
hw/pci_internals.h +2 -2
index 96690b7..be5594b 100644
@@ -18,7 +18,7 @@ struct PCIBus {
     BusState qbus;
     uint8_t devfn_min;
     pci_set_irq_fn set_irq;
-    pci_map_irq_fn map_irq;
+    pci_route_pin_fn route_intx_pin;
     pci_hotplug_fn hotplug;
     DeviceState *hotplug_qdev;
     void *irq_opaque;
@@ -59,7 +59,7 @@ struct PCIBridge {
     MemoryRegion alias_pref_mem;
     MemoryRegion alias_mem;
     MemoryRegion alias_io;
-    pci_map_irq_fn map_irq;
+    pci_route_pin_fn route_intx_pin;
     const char *bus_name;
 };
 
hw/xio3130_downstream.c +3 -2
index 319624f..d334e16 100644
@@ -128,7 +128,8 @@ static int xio3130_downstream_exitfn(PCIDevice *d)
 }
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  const char *bus_name,
+                                  pci_route_pin_fn route_intx_pin,
                                   uint8_t port, uint8_t chassis,
                                   uint16_t slot)
 {
@@ -144,7 +145,7 @@ PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_prop_set_uint8(qdev, "chassis", chassis);
     qdev_prop_set_uint16(qdev, "slot", slot);
hw/xio3130_downstream.h +2 -1
index 010487f..c4941bd 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  const char *bus_name,
+                                  pci_route_pin_fn route_intx_pin,
                                   uint8_t port, uint8_t chassis,
                                   uint16_t slot);
 
hw/xio3130_upstream.c +3 -2
index 34a99bb..39a8189 100644
@@ -110,7 +110,8 @@ static int xio3130_upstream_exitfn(PCIDevice *d)
 }
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                             const char *bus_name, pci_map_irq_fn map_irq,
+                             const char *bus_name,
+                             pci_route_pin_fn route_intx_pin,
                              uint8_t port)
 {
     PCIDevice *d;
@@ -124,7 +125,7 @@ PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
     br = DO_UPCAST(PCIBridge, dev, d);
 
     qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
+    pci_bridge_prepare(br, bus_name, route_intx_pin);
     qdev_prop_set_uint8(qdev, "port", port);
     qdev_init_nofail(qdev);
 
hw/xio3130_upstream.h +2 -1
index e996997..bf3784e 100644
@@ -4,7 +4,8 @@
 #include "pcie_port.h"
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                const char *bus_name, pci_map_irq_fn map_irq,
+                                const char *bus_name,
+                                pci_route_pin_fn route_intx_pin,
                                 uint8_t port);
 
 #endif /* QEMU_XIO3130_H */
Signature · 1 line
1.7.3.4
author
#11 lore raw

PATCH 5/13 pci: Add pci_device_route_intx_to_irq

In reply to Jan Kiszka

Add a PCI IRQ path discovery function that walks from a given device to the host bridge, returning the mode (enabled/inverted/disabled) and the IRQ number that is reported to the attached interrupt controller. For this purpose, another host bridge callback function is introduced:
route_intx_to_irq. It is so far only implemented by the PIIX3, other host bridges can be added later on as required.

Will be used for KVM PCI device assignment and VFIO.

---
 hw/alpha_typhoon.c |    2 +-
 hw/apb_pci.c       |    2 +-
 hw/bonito.c        |    2 +-
 hw/grackle_pci.c   |    1 +
 hw/gt64xxx.c       |    1 +
 hw/pci.c           |   14 +++++++++++++-
 hw/pci.h           |   13 +++++++++++++
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   23 ++++++++++++++++++++---
 hw/ppc4xx_pci.c    |    2 +-
 hw/ppce500_pci.c   |    2 +-
 hw/prep_pci.c      |    2 +-
 hw/sh_pci.c        |    2 +-
 hw/spapr_pci.c     |    2 +-
 hw/unin_pci.c      |    4 ++--
 hw/versatile_pci.c |    2 +-
 16 files changed, 60 insertions(+), 15 deletions(-)
hw/alpha_typhoon.c +1 -1
index d5193bb..1056b50 100644
@@ -764,7 +764,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                                 &s->pchip.reg_io);
 
     b = pci_register_bus(&s->host.busdev.qdev, "pci",
-                         typhoon_set_irq, sys_map_irq, s,
+                         typhoon_set_irq, sys_map_irq, NULL, s,
                          &s->pchip.reg_mem, addr_space_io, 0, 64);
     s->host.bus = b;
 
hw/apb_pci.c +1 -1
index 57ead09..270a785 100644
@@ -378,7 +378,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
 
     d->bus = pci_register_bus(&d->busdev.qdev, "pci",
-                              pci_apb_set_irq, pci_pbm_map_irq, d,
+                              pci_apb_set_irq, pci_pbm_map_irq, NULL, d,
                               &d->pci_mmio,
                               get_system_io(),
                               0, 32);
hw/bonito.c +1 -1
index 77786f8..7ce5993 100644
@@ -750,7 +750,7 @@ PCIBus *bonito_init(qemu_irq *pic)
     dev = qdev_create(NULL, "Bonito-pcihost");
     pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
     b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
-                         pci_bonito_map_irq, pic, get_system_memory(),
+                         pci_bonito_map_irq, NULL, pic, get_system_memory(),
                          get_system_io(),
                          0x28, 32);
     pcihost->bus = b;
hw/grackle_pci.c +1 -0
index 81ff3a3..f47d9fe 100644
@@ -85,6 +85,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_grackle_set_irq,
                                          pci_grackle_map_irq,
+                                         NULL,
                                          pic,
                                          &d->pci_mmio,
                                          address_space_io,
hw/gt64xxx.c +1 -0
index a2d0e5a..2418238 100644
@@ -1093,6 +1093,7 @@ PCIBus *gt64120_register(qemu_irq *pic)
     d = FROM_SYSBUS(GT64120State, s);
     d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                   gt64120_pci_set_irq, gt64120_pci_map_irq,
+                                  NULL,
                                   pic,
                                   get_system_memory(),
                                   get_system_io(),
hw/pci.c +13 -1
index 9a2b4a3..8878a11 100644
@@ -320,10 +320,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
 
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
                   pci_route_pin_fn route_intx_pin,
+                  pci_route_irq_fn route_intx_to_irq,
                   void *irq_opaque, int nirq)
 {
     bus->set_irq = set_irq;
     bus->route_intx_pin = route_intx_pin;
+    bus->route_intx_to_irq = route_intx_to_irq;
     bus->irq_opaque = irq_opaque;
     bus->nirq = nirq;
     bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
@@ -340,6 +342,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq,
                          pci_route_pin_fn route_intx_pin,
+                         pci_route_irq_fn route_intx_to_irq,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
@@ -349,7 +352,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 
     bus = pci_bus_new(parent, name, address_space_mem,
                       address_space_io, devfn_min);
-    pci_bus_irqs(bus, set_irq, route_intx_pin, irq_opaque, nirq);
+    pci_bus_irqs(bus, set_irq, route_intx_pin, route_intx_to_irq, irq_opaque,
+                 nirq);
     return bus;
 }
 
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +13 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;
+
 typedef struct PCIDeviceClass {
     DeviceClass parent_class;
 
@@ -280,6 +289,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
 typedef int (*pci_route_pin_fn)(PCIDevice *pci_dev, int pin);
+typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
 
 typedef enum {
     PCI_HOTPLUG_DISABLED,
@@ -295,16 +305,19 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
                   pci_route_pin_fn route_intx_pin,
+                  pci_route_irq_fn route_intx_to_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq,
                          pci_route_pin_fn route_intx_pin,
+                         pci_route_irq_fn route_intx_to_irq,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_internals.h +1 -0
index be5594b..6639232 100644
@@ -19,6 +19,7 @@ struct PCIBus {
     uint8_t devfn_min;
     pci_set_irq_fn set_irq;
     pci_route_pin_fn route_intx_pin;
+    pci_route_irq_fn route_intx_to_irq;
     pci_hotplug_fn hotplug;
     DeviceState *hotplug_qdev;
     void *irq_opaque;
hw/piix_pci.c +20 -3
index 09e84f5..347177f 100644
@@ -89,6 +89,7 @@ struct PCII440FXState {
 #define I440FX_SMRAM    0x72
 
 static void piix3_set_irq(void *opaque, int pirq, int level);
+static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx);
 static void piix3_write_config_xen(PCIDevice *dev,
                                uint32_t address, uint32_t val, int len);
 
@@ -308,13 +309,13 @@ static PCIBus *i440fx_common_init(const char *device_name,
     if (xen_enabled()) {
         piix3 = DO_UPCAST(PIIX3State, dev,
                 pci_create_simple_multifunction(b, -1, true, "PIIX3-xen"));
-        pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+        pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, NULL,
                 piix3, XEN_PIIX_NUM_PIRQS);
     } else {
         piix3 = DO_UPCAST(PIIX3State, dev,
                 pci_create_simple_multifunction(b, -1, true, "PIIX3"));
-        pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
-                PIIX_NUM_PIRQS);
+        pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq,
+                     piix3_route_intx_pin_to_irq, piix3, PIIX_NUM_PIRQS);
     }
     piix3->pic = pic;
     *isa_bus = DO_UPCAST(ISABus, qbus,
@@ -386,6 +387,22 @@ static void piix3_set_irq(void *opaque, int pirq, int level)
     piix3_set_irq_level(piix3, pirq, level);
 }
 
+static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin)
+{
+    PIIX3State *piix3 = opaque;
+    int irq = piix3->dev.config[PIIX_PIRQC + pin];
+    PCIINTxRoute route;
+
+    if (irq < PIIX_NUM_PIC_IRQS) {
+        route.mode = PCI_INTX_ENABLED;
+        route.irq = irq;
+    } else {
+        route.mode = PCI_INTX_DISABLED;
+        route.irq = -1;
+    }
+    return route;
+}
+
 /* irq routing is changed. so rebuild bitmap */
 static void piix3_update_irq_levels(PIIX3State *piix3)
 {
hw/ppc4xx_pci.c +1 -1
index 203c3cd..224c4a0 100644
@@ -343,7 +343,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
     }
 
     b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq,
-                         ppc4xx_pci_map_irq, s->irq, get_system_memory(),
+                         ppc4xx_pci_map_irq, NULL, s->irq, get_system_memory(),
                          get_system_io(), 0, 4);
     s->pci_state.bus = b;
 
hw/ppce500_pci.c +1 -1
index 0f60b24..dd924ae 100644
@@ -318,7 +318,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     }
 
     b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
-                         mpc85xx_pci_map_irq, s->irq, address_space_mem,
+                         mpc85xx_pci_map_irq, NULL, s->irq, address_space_mem,
                          address_space_io, PCI_DEVFN(0x11, 0), 4);
     s->pci_state.bus = b;
 
hw/prep_pci.c +1 -1
index 38dbff4..9d7bec7 100644
@@ -108,7 +108,7 @@ static int raven_pcihost_init(SysBusDevice *dev)
     }
 
     bus = pci_register_bus(&h->busdev.qdev, NULL,
-                           prep_set_irq, prep_map_irq, s->irq,
+                           prep_set_irq, prep_map_irq, NULL, s->irq,
                            address_space_mem, address_space_io, 0, 4);
     h->bus = bus;
 
hw/sh_pci.c +1 -1
index 0cfac46..1cea12b 100644
@@ -120,7 +120,7 @@ static int sh_pci_device_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->irq[i]);
     }
     s->bus = pci_register_bus(&s->busdev.qdev, "pci",
-                              sh_pci_set_irq, sh_pci_map_irq,
+                              sh_pci_set_irq, sh_pci_map_irq, NULL,
                               s->irq,
                               get_system_memory(),
                               get_system_io(),
hw/spapr_pci.c +1 -1
index 25b400a..4a43062 100644
@@ -306,7 +306,7 @@ static int spapr_phb_init(SysBusDevice *s)
 
     bus = pci_register_bus(&phb->busdev.qdev,
                            phb->busname ? phb->busname : phb->dtbusname,
-                           pci_spapr_set_irq, pci_spapr_map_irq, phb,
+                           pci_spapr_set_irq, pci_spapr_map_irq, NULL, phb,
                            &phb->memspace, &phb->iospace,
                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
     phb->host_state.bus = bus;
hw/unin_pci.c +2 -2
index 409bcd4..056e3bc 100644
@@ -227,7 +227,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
 
     d->host_state.bus = pci_register_bus(dev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic,
+                                         NULL, pic,
                                          &d->pci_mmio,
                                          address_space_io,
                                          PCI_DEVFN(11, 0), 4);
@@ -293,7 +293,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
 
     d->host_state.bus = pci_register_bus(dev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic,
+                                         NULL, pic,
                                          &d->pci_mmio,
                                          address_space_io,
                                          PCI_DEVFN(11, 0), 4);
hw/versatile_pci.c +1 -1
index ae53a8b..90c400e 100644
@@ -68,7 +68,7 @@ static int pci_vpb_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->irq[i]);
     }
     bus = pci_register_bus(&dev->qdev, "pci",
-                           pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
+                           pci_vpb_set_irq, pci_vpb_map_irq, NULL, s->irq,
                            get_system_memory(), get_system_io(),
                            PCI_DEVFN(11, 0), 4);
 
Signature · 1 line
1.7.3.4
#12 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 5 lines · Jan Kiszka
hw/pci.c +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
hw/pci.c +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 6 lines
hw/pci.h +0 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \

hw/pci.h enum { · line 151

Quoted 10 lines
hw/pci.h +8 -0
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;

Is this INTX route or IRQ route?
Is the INTX enabled/disabled/inverted or the IRQ?

I have the impression it's the IRQ, in the apic. PCI INTX are never inverted they are always active low.

#13 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 5 lines · Michael S. Tsirkin
Quoted 4 lines · Jan Kiszka
hw/pci.c +0 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
Quoted 14 lines

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 11 lines
hw/pci.c +8 -0
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

Quoted 21 lines
Quoted 7 lines
hw/pci.h +0 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \

hw/pci.h enum { · line 151

Quoted 10 lines
hw/pci.h +8 -0
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;

Is this INTX route or IRQ route?
Is the INTX enabled/disabled/inverted or the IRQ?

Quoted 2 lines

I have the impression it's the IRQ, in the apic. PCI INTX are never inverted they are always active low.

This should be considered as "the route *of* an INTx", not "to some IRQ". I could call it PCIINTxToIRQRoute if you prefer, but it's a bit lengthy.

Jan

#14 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 21 lines · Jan Kiszka
Quoted 5 lines · Michael S. Tsirkin
Quoted 4 lines · Jan Kiszka
hw/pci.c +0 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
Quoted 14 lines

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 11 lines
hw/pci.c +8 -0
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Quoted 21 lines
Quoted 21 lines
Quoted 7 lines
hw/pci.h +0 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \

hw/pci.h enum { · line 151

Quoted 10 lines
hw/pci.h +8 -0
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;

Is this INTX route or IRQ route?
Is the INTX enabled/disabled/inverted or the IRQ?

Quoted 8 lines
Quoted 2 lines

I have the impression it's the IRQ, in the apic. PCI INTX are never inverted they are always active low.

This should be considered as "the route *of* an INTx", not "to some IRQ". I could call it PCIINTxToIRQRoute if you prefer, but it's a bit lengthy.

Jan

Yes but the polarity is in apic? Or is it in host bridge?

Signature · 1 line
MST
#15 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
hw/pci.c +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
hw/pci.c +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
Quoted 8 lines
hw/pci.h +0 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \

hw/pci.h enum { · line 151

Quoted 10 lines
hw/pci.h +8 -0
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;

Is this INTX route or IRQ route?
Is the INTX enabled/disabled/inverted or the IRQ?

I have the impression it's the IRQ, in the apic. PCI INTX are never inverted they are always active low.

Quoted 8 lines
Quoted 5 lines

This should be considered as "the route *of* an INTx", not "to some IRQ". I could call it PCIINTxToIRQRoute if you prefer, but it's a bit lengthy.

Jan

Yes but the polarity is in apic? Or is it in host bridge?

Nope (then we would not have to bother). At least one host bridge (bonito) is apparently able to invert the polarity.

Jan

#16 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
hw/pci.c +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
hw/pci.c +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

Yes that's fine.

Quoted 39 lines
Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
Quoted 8 lines
hw/pci.h +0 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \

hw/pci.h enum { · line 151

Quoted 10 lines
hw/pci.h +8 -0
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;

Is this INTX route or IRQ route?
Is the INTX enabled/disabled/inverted or the IRQ?

I have the impression it's the IRQ, in the apic. PCI INTX are never inverted they are always active low.

Quoted 8 lines
Quoted 5 lines

This should be considered as "the route *of* an INTx", not "to some IRQ". I could call it PCIINTxToIRQRoute if you prefer, but it's a bit lengthy.

Jan

Yes but the polarity is in apic? Or is it in host bridge?

Nope (then we would not have to bother). At least one host bridge (bonito) is apparently able to invert the polarity.

Jan

#17 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

In reply to Jan Kiszka
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
hw/pci.c +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
hw/pci.c +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

As it is you are adding APIs that in theory address non PIIX issues but in practice don't implement for non PIIX. So we never really know.

Quoted 39 lines
Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
Quoted 8 lines
hw/pci.h +0 -0
index 5b54e2d..bbba01e 100644
@@ -141,6 +141,15 @@ enum {
 #define PCI_DEVICE_GET_CLASS(obj) \

hw/pci.h enum { · line 151

Quoted 10 lines
hw/pci.h +8 -0
      OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
 
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;

Is this INTX route or IRQ route?
Is the INTX enabled/disabled/inverted or the IRQ?

I have the impression it's the IRQ, in the apic. PCI INTX are never inverted they are always active low.

Quoted 8 lines
Quoted 5 lines

This should be considered as "the route *of* an INTx", not "to some IRQ". I could call it PCIINTxToIRQRoute if you prefer, but it's a bit lengthy.

Jan

Yes but the polarity is in apic? Or is it in host bridge?

Nope (then we would not have to bother). At least one host bridge (bonito) is apparently able to invert the polarity.

Jan

#18 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 43 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
hw/pci.c +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

hw/pci.c static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
hw/pci.c +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

Quoted 6 lines

I'd like to ponder this a bit more then.

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 4 lines

As it is you are adding APIs that in theory address non PIIX issues but in practice don't implement for non PIIX. So we never really know.

I once hacked q35 to make it work with device assignment. This really requires something like this. It actually requires something generic, independent of PCI, but that's too much for this round.

Jan

#19 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

Quoted 7 lines
Quoted 4 lines

As it is you are adding APIs that in theory address non PIIX issues but in practice don't implement for non PIIX. So we never really know.

I once hacked q35 to make it work with device assignment. This really requires something like this.

Yes I'm aware of this motivation. This does not do much to address the concerns though.

Quoted 4 lines

It actually requires something generic, independent of PCI, but that's too much for this round.

Jan

And this just makes the concerns worse :(

Signature · 1 line
MST
#20 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 56 lines · Michael S. Tsirkin
Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 6 lines

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

I don't share your view on this. It is surely _not_ a hack, specifically when compared to what we have so far and what could be done otherwise, e.g. hacking device-assignment and PIIX to make them cooperate (sorry, I would vote against such an attempt). This is just a partially used generic API. Any chipset not providing the required routing function will cause an assert once some tries to make use of it.

So, what can I do to make this API more acceptable for you?

Jan

#21 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 71 lines · Jan Kiszka
Quoted 56 lines · Michael S. Tsirkin
Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 6 lines

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

I don't share your view on this. It is surely _not_ a hack, specifically when compared to what we have so far and what could be done otherwise, e.g. hacking device-assignment and PIIX to make them cooperate (sorry, I would vote against such an attempt). This is just a partially used generic API. Any chipset not providing the required routing function will cause an assert once some tries to make use of it.

Quoted 4 lines

So, what can I do to make this API more acceptable for you?

Jan

The idea that I suggested above would address this concern. Or wait a bit, maybe I'll come around when I ponder the alternatives.

Signature · 1 line
MST
#22 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

In reply to Jan Kiszka
Quoted 64 lines · Jan Kiszka
Quoted 56 lines · Michael S. Tsirkin
Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 6 lines

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

Quoted 6 lines

I don't share your view on this. It is surely _not_ a hack, specifically when compared to what we have so far and what could be done otherwise, e.g. hacking device-assignment and PIIX to make them cooperate (sorry, I would vote against such an attempt). This is just a partially used generic API. Any chipset not providing the required routing function will cause an assert once some tries to make use of it.

I agree, and frankly it sounds like a rather biased attitude against device assignment. piix and q35 may be the only initial chipsets to implement this, but VFIO is designed to be architecture neutral. It's already working on POWER. Interrupt routing is one of the most intrusive parts because we cannot know from inside the device assignment code how the chipset exposes intx out to an irq. Jan's interface makes it easy for a chipset to add this, versus hacks in device assignment code, even if they were possible. If it needs to be tweaked for other chipsets, we'll do that when they come. Please don't roadblock device assignment or VFIO support by not allowing us a well architected, generic interface to track interrupts. Thanks,

Alex

#23 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 72 lines · Alex Williamson
Quoted 64 lines · Jan Kiszka
Quoted 56 lines · Michael S. Tsirkin
Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 6 lines

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

Quoted 6 lines

I don't share your view on this. It is surely _not_ a hack, specifically when compared to what we have so far and what could be done otherwise, e.g. hacking device-assignment and PIIX to make them cooperate (sorry, I would vote against such an attempt). This is just a partially used generic API. Any chipset not providing the required routing function will cause an assert once some tries to make use of it.

Quoted 5 lines

I agree, and frankly it sounds like a rather biased attitude against device assignment.
piix and q35 may be the only initial chipsets to
implement this, but VFIO is designed to be architecture neutral. It's already working on POWER.

Not with this patch it doesn't.

Quoted 10 lines

Interrupt routing is one of the most
intrusive parts because we cannot know from inside the device assignment code how the chipset exposes intx out to an irq. Jan's interface makes it easy for a chipset to add this, versus hacks in device assignment code, even if they were possible. If it needs to be tweaked for other chipsets, we'll do that when they come. Please don't roadblock device assignment or VFIO support by not allowing us a well architected, generic interface to track interrupts. Thanks,

Alex

Problems are:
1. This sticks NULL in all chipsets except one. This means it's hard to find and fill out.
2. Adds a function, in every chipset, that is only used by assignment. This means many maintainers have no way to test it.

Ways to handle this that came up so far, in order of my preference:
1. Cache all of route in devices.
2. Some ugly hack in device assignment.
3. Merge as is and fix it when it gets broken.

So if you expect me to merge this work, then either Jan does (1), or gives up and does (2), or I find some time and do (1), or I fail to do
(1) and get convinced that we need to do (3). Or someone else gets involved.

Signature · 1 line
MST
#24 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 73 lines · Michael S. Tsirkin
Quoted 72 lines · Alex Williamson
Quoted 70 lines · Jan Kiszka
Quoted 56 lines · Michael S. Tsirkin
Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 6 lines

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

I don't share your view on this. It is surely _not_ a hack, specifically when compared to what we have so far and what could be done otherwise, e.g. hacking device-assignment and PIIX to make them cooperate (sorry, I would vote against such an attempt). This is just a partially used generic API. Any chipset not providing the required routing function will cause an assert once some tries to make use of it.

Quoted 7 lines
Quoted 5 lines

I agree, and frankly it sounds like a rather biased attitude against device assignment.
piix and q35 may be the only initial chipsets to
implement this, but VFIO is designed to be architecture neutral. It's already working on POWER.

Not with this patch it doesn't.

Alexey, how are you handling INTx routing and EOI on POWER?

Quoted 9 lines
Quoted 9 lines

Interrupt routing is one of the most
intrusive parts because we cannot know from inside the device assignment code how the chipset exposes intx out to an irq. Jan's interface makes it easy for a chipset to add this, versus hacks in device assignment code, even if they were possible. If it needs to be tweaked for other chipsets, we'll do that when they come. Please don't roadblock device assignment or VFIO support by not allowing us a well architected, generic interface to track interrupts. Thanks,

Quoted 5 lines
Quoted 1 line

Alex

Problems are:
1. This sticks NULL in all chipsets except one. This means it's hard to find and fill out.

I don't buy that. Look for all the callers, find the one that's not NULL, look at what it does... How's that a problem? This can be solved by documentation.

Quoted 2 lines

2. Adds a function, in every chipset, that is only used by assignment. This means many maintainers have no way to test it.

It's effectively optional, so they don't have to implement it. They can wait to care about it until they want device assignment. This can also be solved by documentation so the maintainer knows when and how this is used and can choose to implement it or not.

Quoted 2 lines

Ways to handle this that came up so far, in order of my preference:
1. Cache all of route in devices.

How do we get the route to cache it?

Quoted 1 line

2. Some ugly hack in device assignment.

We still have the problem of how do we get the route to start with?

Quoted 1 line

3. Merge as is and fix it when it gets broken.

Isn't that how open source works? ;^)

Quoted 4 lines

So if you expect me to merge this work, then either Jan does (1), or gives up and does (2), or I find some time and do (1), or I fail to do
(1) and get convinced that we need to do (3). Or someone else gets involved.

I still have trouble seeing how (3) is a problem. The translation of an INTx to an irq is chipset specific. We need a chipset function to perform that transform. We don't know how to do this for every chipset in the tree, nor do many of those chipset care at the moment about device assignment. Jan has created an arrangement where chipsets can easily opt-in to this support. Aside from asking us to go spend a month digging up specs for every chipset in tree and trying to implement this ourselves, what kind of enhancement to the interface are you looking for? Thanks,

Alex

#25 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 95 lines · Alex Williamson
Quoted 73 lines · Michael S. Tsirkin
Quoted 72 lines · Alex Williamson
Quoted 70 lines · Jan Kiszka
Quoted 56 lines · Michael S. Tsirkin
Quoted 46 lines · Jan Kiszka
Quoted 45 lines · Michael S. Tsirkin
Quoted 35 lines · Jan Kiszka
Quoted 22 lines · Michael S. Tsirkin
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka
(quoted diff) +1 -0
@@ -1089,6 +1093,14 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)

Review static void pci_set_irq(void *opaque, int irq_num, int level) · line 1106

Quoted 10 lines
(quoted diff) +7 -0
+{
+    PCIBus *bus = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 

Just an idea: can devices cache this result, bypassing the intx to irq lookup on data path?

Quoted 8 lines
Quoted 4 lines

That lookup is part of set_irq which we don't bypass so far and where this is generally trivial. If we want to cache the effects of set_irq as well, I guess things would become pretty complex (e.g. due to vmstate compatibility), and I'm unsure if it would buy us much.

This is less for performance but more for making
everyone use the same infrastructure rather than
assigned devices being the weird case.

Device assignment is weird. It bypasses all state updates as it does not have to bother about migratability.

Quoted 6 lines

Well, of course we could cache the host bridge routing result as well, for every device. It would have to be in addition to host_intx_pin. But the result would look pretty strange to me.

In any case, I would prefer to do this, if at all, on top of this series, specifically as it will require to touch all host bridges.

I'd like to ponder this a bit more then.

Quoted 8 lines
Quoted 4 lines

If the claim is that device assignment is only needed for piix anyway, then why not make it depend on piix *explicitly*? Yes ugly but this will make it very easy to find and address any missing pieces.

Because it is conceptually independent of the PIIX, we will need it for successors of that x86 chipset as well, and I won't add the ugly hack of qemu-kvm upstream

Quoted 6 lines

So you look at an API and see it requires a route callback. And you ask "why doesn't chipset X implement it"? And the answer is "because it's only used by device assignment". Which you will only know if you read this thread. So it's a hack. And I'd rather have the hacks in device-assignment.c than in pci.c even if the former are nastier.

I don't share your view on this. It is surely _not_ a hack, specifically when compared to what we have so far and what could be done otherwise, e.g. hacking device-assignment and PIIX to make them cooperate (sorry, I would vote against such an attempt). This is just a partially used generic API. Any chipset not providing the required routing function will cause an assert once some tries to make use of it.

Quoted 7 lines
Quoted 5 lines

I agree, and frankly it sounds like a rather biased attitude against device assignment.
piix and q35 may be the only initial chipsets to
implement this, but VFIO is designed to be architecture neutral. It's already working on POWER.

Not with this patch it doesn't.

Alexey, how are you handling INTx routing and EOI on POWER?

Quoted 11 lines
Quoted 10 lines

Interrupt routing is one of the most
intrusive parts because we cannot know from inside the device assignment code how the chipset exposes intx out to an irq. Jan's interface makes it easy for a chipset to add this, versus hacks in device assignment code, even if they were possible. If it needs to be tweaked for other chipsets, we'll do that when they come. Please don't roadblock device assignment or VFIO support by not allowing us a well architected, generic interface to track interrupts. Thanks,

Alex

Quoted 7 lines
Quoted 3 lines

Problems are:
1. This sticks NULL in all chipsets except one. This means it's hard to find and fill out.

I don't buy that. Look for all the callers, find the one that's not NULL, look at what it does... How's that a problem? This can be solved by documentation.

Yes but it's not there.

Quoted 7 lines
Quoted 2 lines

2. Adds a function, in every chipset, that is only used by assignment. This means many maintainers have no way to test it.

It's effectively optional, so they don't have to implement it. They can wait to care about it until they want device assignment. This can also be solved by documentation so the maintainer knows when and how this is used and can choose to implement it or not.

No, what I meant is it's hard to test on systems where it's implemented.

Quoted 4 lines
Quoted 2 lines

Ways to handle this that came up so far, in order of my preference:
1. Cache all of route in devices.

How do we get the route to cache it?

Move routing logic from piix3_set_irq_level
to a route_intx callback, or equivalent.
Then you just look it up in device->root_route.

Quoted 3 lines
Quoted 1 line

2. Some ugly hack in device assignment.

We still have the problem of how do we get the route to start with?

You are asking how an ugly hack might work? Think it up yourself, I'm not gonnu mention hacks at this point yet.

Quoted 3 lines
Quoted 1 line

3. Merge as is and fix it when it gets broken.

Isn't that how open source works? ;^)

It works by darwinism. This is exactly what's going on here.

Quoted 15 lines
Quoted 4 lines

So if you expect me to merge this work, then either Jan does (1), or gives up and does (2), or I find some time and do (1), or I fail to do
(1) and get convinced that we need to do (3). Or someone else gets involved.

I still have trouble seeing how (3) is a problem. The translation of an INTx to an irq is chipset specific. We need a chipset function to perform that transform. We don't know how to do this for every chipset in the tree, nor do many of those chipset care at the moment about device assignment. Jan has created an arrangement where chipsets can easily opt-in to this support. Aside from asking us to go spend a month digging up specs for every chipset in tree and trying to implement this ourselves, what kind of enhancement to the interface are you looking for? Thanks,

Quoted 1 line

Alex

Sorry I don't understand what you are talking about.
It's better to have one way to determine interrupt routing than two. It can be done, and IIUC Jan doesn't disagree.
There are gnarly issues related to migration compatibility
with old qemu sorrounding the solution which makes Jan think it's too complex, but nothing remotely related to digging up any specs.

Signature · 1 line
MST
#26 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 15 lines · Michael S. Tsirkin
Quoted 15 lines
Quoted 4 lines

So if you expect me to merge this work, then either Jan does (1), or gives up and does (2), or I find some time and do (1), or I fail to do
(1) and get convinced that we need to do (3). Or someone else gets involved.

I still have trouble seeing how (3) is a problem. The translation of an INTx to an irq is chipset specific. We need a chipset function to perform that transform. We don't know how to do this for every chipset in the tree, nor do many of those chipset care at the moment about device assignment. Jan has created an arrangement where chipsets can easily opt-in to this support. Aside from asking us to go spend a month digging up specs for every chipset in tree and trying to implement this ourselves, what kind of enhancement to the interface are you looking for? Thanks,

Quoted 8 lines
Quoted 1 line

Alex

Sorry I don't understand what you are talking about.
It's better to have one way to determine interrupt routing than two. It can be done, and IIUC Jan doesn't disagree.
There are gnarly issues related to migration compatibility
with old qemu sorrounding the solution which makes Jan think it's too complex, but nothing remotely related to digging up any specs.

Caching the host bridge generically means changing all chipsets and, well, also testing that they still work afterward. As explained before, I'd really like to avoid doing this in a single step.

And there are still migration issues - as explained based on the PIIX3. Until it is officially stated that we give up on backward migratability, it will be quite some effort (ie. lots of additional code) to provide compatibility on top of generic intx-to-irq routing.

This interface here is surely not the perfect solution. But it is better than a) hacking device assignment and VFIO into a specific chipset and
b) starting a huge refactoring now. We can surely tweak some aspects of this approach before merging, e.g. documentation. But lets try to move forward in small, well testable steps. I really don't see the need for touching all chipsets and migration formats for this purpose ATM.

Jan

#27 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 3 lines · Jan Kiszka

Caching the host bridge generically means changing all chipsets and, well, also testing that they still work afterward. As explained before, I'd really like to avoid doing this in a single step.

Surely it is not hard to find a way to switch chipsets gradually.

Signature · 1 line
MST
#28 lore raw

Re: [Qemu-devel] [PATCH 05/13] pci: Add pci_device_route_intx_to_irq

Quoted 6 lines · Michael S. Tsirkin
Quoted 3 lines · Jan Kiszka

Caching the host bridge generically means changing all chipsets and, well, also testing that they still work afterward. As explained before, I'd really like to avoid doing this in a single step.

Surely it is not hard to find a way to switch chipsets gradually.

Just to stress: the problem is that with this patch there are 2 ways to get routing even for piix.

So instead of your patch which caches just intx route
but always, and which I applied, you could have one that only caches if the root supplies a new route callback.

Then to set irq, you check cache and if not valid, fallback on the legacy interface.

With time we convert everyone and drop the legacy interface.

Quoted 2 lines
Signature · 1 line
MST
author
#29 lore raw

PATCH 6/13 pci: Add INTx routing notifier

In reply to Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +19 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +7 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +8 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+
 /* default qdev initialization function for PCI-to-PCI bridge */
 int pci_bridge_initfn(PCIDevice *dev)
 {
@@ -333,6 +340,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
+    pci_device_set_intx_routing_notifier(dev, pci_bridge_intx_routing_update);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
     return 0;
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4
#30 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 6 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

pci_device_get_host_irq isn't in the cards anymore, no?

Quoted 114 lines

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +19 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +7 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +8 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+
 /* default qdev initialization function for PCI-to-PCI bridge */
 int pci_bridge_initfn(PCIDevice *dev)
 {
@@ -333,6 +340,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
+    pci_device_set_intx_routing_notifier(dev, pci_bridge_intx_routing_update);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
     return 0;
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4
#31 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

pci_device_get_host_irq isn't in the cards anymore, no?

Yep, must be pci_device_route_intx_to_irq. Will fix if this series requires more than dropping patch 2. Otherwise, I would ask you to replace it on merge.

Thanks,
Jan

author
#32 lore raw

PATCH v2 6/13 pci: Add INTx routing notifier

In reply to Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_route_intx_to_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---

v2: Fixed the commit log to mention pci_device_route_intx_to_irq.

 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +19 -0
index fb56090..12f29f0 100644
@@ -1108,6 +1108,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +7 -0
index 85f5c93..647d91d 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -323,6 +327,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +8 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+
 /* default qdev initialization function for PCI-to-PCI bridge */
 int pci_bridge_initfn(PCIDevice *dev)
 {
@@ -333,6 +340,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
+    pci_device_set_intx_routing_notifier(dev, pci_bridge_intx_routing_update);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
     return 0;
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4
#33 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

In reply to Jan Kiszka
Quoted 29 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +3 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1116

Quoted 10 lines
hw/pci.c +10 -0
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+

No documentation and it's not obvious when do you need
to do this.
It would seem from the name that it should be called after you change interrupt routing at the specific bus?

Quoted 1 line

From commit log it would seem that even irq changes should

invoke this. So why isn't this notifier at the host bridge then?

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1122

Quoted 6 lines
hw/pci.c +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 12 lines

/***********************************************************/ /* monitor info on PCI */

hw/pci.h +1 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

Quoted 14 lines
hw/pci.h +3 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 4 lines
hw/pci.h +1 -0
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Quoted 46 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +8 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+
 /* default qdev initialization function for PCI-to-PCI bridge */
 int pci_bridge_initfn(PCIDevice *dev)
 {
@@ -333,6 +340,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
+    pci_device_set_intx_routing_notifier(dev, pci_bridge_intx_routing_update);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
     return 0;
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4
#34 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 27 lines · Michael S. Tsirkin
Quoted 26 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +0 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
Quoted 16 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1116

Quoted 13 lines
hw/pci.c +13 -0
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+

No documentation and it's not obvious when do you need to do this.

Yes, will add some lines.

Quoted 2 lines

It would seem from the name that it should be called after you change interrupt routing at the specific bus?

Correct.

Quoted 3 lines

From commit log it would seem that even irq changes should invoke this. So why isn't this notifier at the host bridge then?

Can't follow, where does the commit log imply this? It is only about routing changes, not IRQ level changes.

Quoted 13 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1122

Quoted 7 lines
hw/pci.c +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

It informs about changes on the route of the device interrupts to the output of the host bridge.

Quoted 12 lines
Quoted 12 lines
hw/pci.c +0 -0
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +0 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
Quoted 3 lines

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 1 line
hw/pci.h +1 -0
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

OK.

Quoted 8 lines
Quoted 8 lines
hw/pci.h +0 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
Quoted 14 lines

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 11 lines
hw/pci.h +4 -0
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Nope, it informs about updates _after_ they happened.

Quoted 39 lines
Quoted 39 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +8 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+
 /* default qdev initialization function for PCI-to-PCI bridge */
 int pci_bridge_initfn(PCIDevice *dev)
 {
@@ -333,6 +340,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
+    pci_device_set_intx_routing_notifier(dev, pci_bridge_intx_routing_update);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
     return 0;
hw/piix_pci.c +0 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
Quoted 10 lines
Quoted 8 lines
hw/piix_pci.c +2 -0
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4

Thanks,
Jan

#35 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 45 lines · Jan Kiszka
Quoted 27 lines · Michael S. Tsirkin
Quoted 26 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +0 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
Quoted 16 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1116

Quoted 13 lines
hw/pci.c +13 -0
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+

No documentation and it's not obvious when do you need to do this.

Quoted 1 line

Yes, will add some lines.

Also, who calls this? Apparently it's invoked from pci_bridge_intx_routing_update?

Quoted 11 lines
Quoted 2 lines

It would seem from the name that it should be called after you change interrupt routing at the specific bus?

Correct.

Quoted 3 lines

From commit log it would seem that even irq changes should invoke this. So why isn't this notifier at the host bridge then?

Can't follow, where does the commit log imply this? It is only about routing changes, not IRQ level changes.

Not sure - it says use pci_device_get_host_irq
so the implication is users cache the result of
pci_device_get_host_irq?

Quoted 57 lines
Quoted 13 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1122

Quoted 7 lines
hw/pci.c +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

It informs about changes on the route of the device interrupts to the output of the host bridge.

Quoted 12 lines
Quoted 12 lines
hw/pci.c +0 -0
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +0 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
Quoted 3 lines

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 1 line
hw/pci.h +1 -0
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

OK.

Quoted 8 lines
Quoted 8 lines
hw/pci.h +0 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
Quoted 14 lines

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 11 lines
hw/pci.h +4 -0
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Quoted 1 line

Nope, it informs about updates _after_ they happened.

Don't we need to update the cached pin if this happens? If yes I would this a better API would both update the cache and then trigger a notifier.
And the notifier can then be cache change notifier, and the "fire" function would instead be "update_cache".

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +0 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
Quoted 7 lines
Quoted 7 lines

hw/pci_bridge.c void pci_bridge_reset(DeviceState *qdev) · line 307

Quoted 7 lines
hw/pci_bridge.c +7 -0
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+

I'd prefer a version that uses a simple loop,
not recursion. For example it is not clear
at this point for which devices is it OK to set
the notifier and which assume the notifier
recurses to children.

Quoted 32 lines
Quoted 18 lines
Quoted 18 lines
hw/pci_bridge.c +1 -0
 /* default qdev initialization function for PCI-to-PCI bridge */
 int pci_bridge_initfn(PCIDevice *dev)
 {
@@ -333,6 +340,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
+    pci_device_set_intx_routing_notifier(dev, pci_bridge_intx_routing_update);
     QLIST_INIT(&sec_bus->child);
     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
     return 0;
hw/piix_pci.c +0 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
Quoted 10 lines
Quoted 8 lines
hw/piix_pci.c +2 -0
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4

Thanks,
Jan

#36 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 46 lines · Michael S. Tsirkin
Quoted 45 lines · Jan Kiszka
Quoted 43 lines · Michael S. Tsirkin
Quoted 29 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +3 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1116

Quoted 10 lines
hw/pci.c +10 -0
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+

No documentation and it's not obvious when do you need to do this.

Quoted 4 lines
Quoted 1 line

Yes, will add some lines.

Also, who calls this? Apparently it's invoked from pci_bridge_intx_routing_update?

That's to forward the change reported from the parent bus. In fact, PCI does not allow pin routing changes once the device is plugged. The only change can come from the host bridge's configuration.

So there are two types of users:
- the host bridge after internal configuration changes
- a PCI-PCI bridge to forward the notification to its children

Quoted 11 lines
Quoted 11 lines
Quoted 4 lines

It would seem from the name that it should be called after you change interrupt routing at the specific bus?

Correct.

Quoted 3 lines

From commit log it would seem that even irq changes should invoke this. So why isn't this notifier at the host bridge then?

Quoted 6 lines
Quoted 2 lines

Can't follow, where does the commit log imply this? It is only about routing changes, not IRQ level changes.

Not sure - it says use pci_device_get_host_irq
so the implication is users cache the result of
pci_device_get_host_irq?

That's the old name, I've sent v2 where the commitlog was fixed.

Quoted 58 lines
Quoted 58 lines
Quoted 14 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1122

Quoted 8 lines
hw/pci.c +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

It informs about changes on the route of the device interrupts to the output of the host bridge.

Quoted 12 lines
Quoted 12 lines
hw/pci.c +0 -0
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +0 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
Quoted 3 lines

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 1 line
hw/pci.h +1 -0
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

OK.

Quoted 22 lines
Quoted 15 lines
hw/pci.h +3 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 4 lines
hw/pci.h +1 -0
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Quoted 7 lines
Quoted 1 line

Nope, it informs about updates _after_ they happened.

Don't we need to update the cached pin if this happens? If yes I would this a better API would both update the cache and then trigger a notifier.
And the notifier can then be cache change notifier, and the "fire" function would instead be "update_cache".

See above, the cached part of the route is static anyway. What changes is the host bridge configuration.

Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +0 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
Quoted 13 lines
Quoted 7 lines
Quoted 7 lines

hw/pci_bridge.c void pci_bridge_reset(DeviceState *qdev) · line 307

Quoted 7 lines
hw/pci_bridge.c +7 -0
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+

I'd prefer a version that uses a simple loop,
not recursion. For example it is not clear
at this point for which devices is it OK to set
the notifier and which assume the notifier
recurses to children.

The notification must be forwarded to any secondary bus because any device below can have a notifier registered. And I think recursion is the cleaner approach for this as we can have complex topologies.

Jan

#37 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 71 lines · Jan Kiszka
Quoted 46 lines · Michael S. Tsirkin
Quoted 45 lines · Jan Kiszka
Quoted 43 lines · Michael S. Tsirkin
Quoted 29 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_get_host_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c        |   19 +++++++++++++++++++
 hw/pci.h        |    7 +++++++
 hw/pci_bridge.c |    8 ++++++++
 hw/piix_pci.c   |    2 ++
 4 files changed, 36 insertions(+), 0 deletions(-)
hw/pci.c +3 -0
index 8878a11..5b99f4b 100644
@@ -1101,6 +1101,25 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1116

Quoted 10 lines
hw/pci.c +10 -0
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+    }
+}
+

No documentation and it's not obvious when do you need to do this.

Quoted 4 lines
Quoted 1 line

Yes, will add some lines.

Also, who calls this? Apparently it's invoked from pci_bridge_intx_routing_update?

That's to forward the change reported from the parent bus. In fact, PCI does not allow pin routing changes once the device is plugged. The only change can come from the host bridge's configuration.

So there are two types of users:
- the host bridge after internal configuration changes
- a PCI-PCI bridge to forward the notification to its children

Quoted 11 lines
Quoted 11 lines
Quoted 4 lines

It would seem from the name that it should be called after you change interrupt routing at the specific bus?

Correct.

Quoted 3 lines

From commit log it would seem that even irq changes should invoke this. So why isn't this notifier at the host bridge then?

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Can't follow, where does the commit log imply this? It is only about routing changes, not IRQ level changes.

Not sure - it says use pci_device_get_host_irq
so the implication is users cache the result of
pci_device_get_host_irq?

That's the old name, I've sent v2 where the commitlog was fixed.

Yes but still. If users cache the irq they need to get notified about *that*. Not about intx routing.

Quoted 60 lines
Quoted 60 lines
Quoted 59 lines
Quoted 14 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1122

Quoted 8 lines
hw/pci.c +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

It informs about changes on the route of the device interrupts to the output of the host bridge.

Quoted 12 lines
Quoted 12 lines
hw/pci.c +0 -0
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +0 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
Quoted 3 lines

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 1 line
hw/pci.h +1 -0
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

OK.

Quoted 8 lines
Quoted 8 lines
hw/pci.h +0 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
Quoted 14 lines

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 11 lines
hw/pci.h +4 -0
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Nope, it informs about updates _after_ they happened.

Quoted 8 lines
Quoted 5 lines

Don't we need to update the cached pin if this happens? If yes I would this a better API would both update the cache and then trigger a notifier.
And the notifier can then be cache change notifier, and the "fire" function would instead be "update_cache".

See above, the cached part of the route is static anyway. What changes is the host bridge configuration.

You are saying it is only the intx to irq routing that can change?
So maybe "pci_bus_update_intx_to_irq_routing"?

Quoted 29 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +0 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
Quoted 13 lines
Quoted 7 lines
Quoted 7 lines

hw/pci_bridge.c void pci_bridge_reset(DeviceState *qdev) · line 307

Quoted 7 lines
hw/pci_bridge.c +7 -0
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+

I'd prefer a version that uses a simple loop,
not recursion. For example it is not clear
at this point for which devices is it OK to set
the notifier and which assume the notifier
recurses to children.

Quoted 6 lines

The notification must be forwarded to any secondary bus because any device below can have a notifier registered. And I think recursion is the cleaner approach for this as we can have complex topologies.

Jan

I don't think it's ever more complex than a tree.

Signature · 1 line
MST
#38 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
Quoted 2 lines

From commit log it would seem that even irq changes should invoke this. So why isn't this notifier at the host bridge then?

Can't follow, where does the commit log imply this? It is only about routing changes, not IRQ level changes.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

Not sure - it says use pci_device_get_host_irq
so the implication is users cache the result of
pci_device_get_host_irq?

That's the old name, I've sent v2 where the commitlog was fixed.

Yes but still. If users cache the irq they need to get notified about *that*. Not about intx routing.

The user caches the route of a device INTx to the host bridge output (precisely what pci_device_route_inx_to_irq returns), and for changes of that result it gets a notification this way. Nothing else.

Quoted 67 lines
Quoted 67 lines
Quoted 66 lines
Quoted 59 lines
Quoted 15 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1122

Quoted 9 lines
hw/pci.c +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

It informs about changes on the route of the device interrupts to the output of the host bridge.

Quoted 12 lines
Quoted 12 lines

/***********************************************************/ /* monitor info on PCI */

hw/pci.h +0 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
Quoted 3 lines

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 1 line
hw/pci.h +1 -0
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

OK.

Quoted 8 lines
Quoted 8 lines
hw/pci.h +0 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
Quoted 14 lines

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 11 lines
hw/pci.h +4 -0
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Quoted 1 line

Nope, it informs about updates _after_ they happened.

Don't we need to update the cached pin if this happens? If yes I would this a better API would both update the cache and then trigger a notifier.
And the notifier can then be cache change notifier, and the "fire" function would instead be "update_cache".

Quoted 6 lines
Quoted 2 lines

See above, the cached part of the route is static anyway. What changes is the host bridge configuration.

You are saying it is only the intx to irq routing that can change?
So maybe "pci_bus_update_intx_to_irq_routing"?

Again, this function does not _update_ anything. It informs about a host-bridge-specific update, i.e. something that happened outside the generic code beforehand.

Quoted 30 lines
Quoted 30 lines
Quoted 29 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +0 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
Quoted 7 lines
Quoted 7 lines

hw/pci_bridge.c void pci_bridge_reset(DeviceState *qdev) · line 307

Quoted 7 lines
hw/pci_bridge.c +7 -0
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+

I'd prefer a version that uses a simple loop,
not recursion. For example it is not clear
at this point for which devices is it OK to set
the notifier and which assume the notifier
recurses to children.

Quoted 9 lines
Quoted 6 lines

The notification must be forwarded to any secondary bus because any device below can have a notifier registered. And I think recursion is the cleaner approach for this as we can have complex topologies.

Jan

I don't think it's ever more complex than a tree.

For sure, and this is what the recursive invocation addresses.

Jan

#39 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 135 lines · Jan Kiszka
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
Quoted 2 lines

From commit log it would seem that even irq changes should invoke this. So why isn't this notifier at the host bridge then?

Can't follow, where does the commit log imply this? It is only about routing changes, not IRQ level changes.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

Not sure - it says use pci_device_get_host_irq
so the implication is users cache the result of
pci_device_get_host_irq?

That's the old name, I've sent v2 where the commitlog was fixed.

Yes but still. If users cache the irq they need to get notified about *that*. Not about intx routing.

The user caches the route of a device INTx to the host bridge output (precisely what pci_device_route_inx_to_irq returns), and for changes of that result it gets a notification this way. Nothing else.

Quoted 67 lines
Quoted 67 lines
Quoted 66 lines
Quoted 59 lines
Quoted 15 lines

Review

Quoted 9 lines
(quoted diff) +6 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

No documentation, and it's not obvious.
Why is this getting PCIDevice?
Does this notify users about updates to this device? Updates below this device?
Above this device?

It informs about changes on the route of the device interrupts to the output of the host bridge.

Quoted 12 lines
Quoted 12 lines

/***********************************************************/ /* monitor info on PCI */

hw/pci.h +0 -0
index bbba01e..e7237cf 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
Quoted 3 lines

hw/pci.h typedef struct PCIDeviceClass { · line 185

Quoted 1 line
hw/pci.h +1 -0
+typedef void (*INTxRoutingNotifier)(PCIDevice *dev);

Let's call it PCIINTx.... please

OK.

Quoted 8 lines
Quoted 8 lines
hw/pci.h +0 -0
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -261,6 +262,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
Quoted 14 lines

hw/pci.h PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 11 lines
hw/pci.h +4 -0
+    /* INTx routing notifier */
+    INTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Quoted 1 line

Nope, it informs about updates _after_ they happened.

Don't we need to update the cached pin if this happens? If yes I would this a better API would both update the cache and then trigger a notifier.
And the notifier can then be cache change notifier, and the "fire" function would instead be "update_cache".

Quoted 6 lines
Quoted 2 lines

See above, the cached part of the route is static anyway. What changes is the host bridge configuration.

You are saying it is only the intx to irq routing that can change?
So maybe "pci_bus_update_intx_to_irq_routing"?

Again, this function does not _update_ anything. It informs about a host-bridge-specific update, i.e. something that happened outside the generic code beforehand.

Quoted 37 lines
Quoted 36 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
hw/pci.h +2 -0
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          INTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/pci_bridge.c +0 -0
index 7d13a85..9ace0b7 100644
@@ -298,6 +298,13 @@ void pci_bridge_reset(DeviceState *qdev)
     pci_bridge_reset_reg(dev);
 }
 
Quoted 13 lines
Quoted 7 lines
Quoted 7 lines

hw/pci_bridge.c void pci_bridge_reset(DeviceState *qdev) · line 307

Quoted 7 lines
hw/pci_bridge.c +7 -0
+static void pci_bridge_intx_routing_update(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+
+    pci_bus_fire_intx_routing_notifier(&br->sec_bus);
+}
+

I'd prefer a version that uses a simple loop,
not recursion. For example it is not clear
at this point for which devices is it OK to set
the notifier and which assume the notifier
recurses to children.

The notification must be forwarded to any secondary bus because any device below can have a notifier registered. And I think recursion is the cleaner approach for this as we can have complex topologies.

Jan

Quoted 7 lines
Quoted 2 lines

I don't think it's ever more complex than a tree.

For sure, and this is what the recursive invocation addresses.

Jan

It's OK to use recursion but when done through a callback like this it's unreadable.
Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

Signature · 1 line
MST
#40 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 2 lines · Michael S. Tsirkin

It's OK to use recursion but when done through a callback like this it's unreadable.

Isn't the alternative poking into foreign bridge device states for their secondary buses?

Quoted 2 lines

Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

Once a PCI device is registered, the INTx route can be queried. So the device user will call pci_device_route_intx_to_irq once (e.g. in the device init function which is invoked afterward) to fill its cache and receive a notification if an update is needed. I do not see why, and specifically how you could query the route earlier or register a callback.

Quoted 7 lines

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

pci_set_bus_intx_routing is really only for the initial setup of the static INTx pin routes. And this happens on pci_bus_irqs/pci_register_bus, ie. triggered by the host bridge. By that time, there can't be any notifier listeners - as there are no devices yet.

Jan

#41 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 6 lines · Jan Kiszka
Quoted 2 lines · Michael S. Tsirkin

It's OK to use recursion but when done through a callback like this it's unreadable.

Isn't the alternative poking into foreign bridge device states for their secondary buses?

pci_set_bus_intx_routing does this already.

Quoted 8 lines
Quoted 2 lines

Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

Once a PCI device is registered, the INTx route can be queried. So the device user will call pci_device_route_intx_to_irq once (e.g. in the device init function which is invoked afterward) to fill its cache and receive a notification if an update is needed. I do not see why, and specifically how you could query the route earlier or register a callback.

Before pci_bus_irqs is called.
Why is another question.

Quoted 8 lines
Quoted 7 lines

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

Quoted 7 lines

pci_set_bus_intx_routing is really only for the initial setup of the static INTx pin routes. And this happens on pci_bus_irqs/pci_register_bus, ie. triggered by the host bridge. By that time, there can't be any notifier listeners - as there are no devices yet.

Jan

What I am saying is we'll cache the final IRQ at some point. Pretend it's already that way so callers are ready for this.

Signature · 1 line
MST
#42 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jan Kiszka
Quoted 2 lines · Michael S. Tsirkin

It's OK to use recursion but when done through a callback like this it's unreadable.

Isn't the alternative poking into foreign bridge device states for their secondary buses?

pci_set_bus_intx_routing does this already.

True. OK, I can do the recursion in pci_bus_fire_intx_routing_notifier directly instead of pushing this into the bridge.

Quoted 26 lines
Quoted 9 lines
Quoted 3 lines

Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

Once a PCI device is registered, the INTx route can be queried. So the device user will call pci_device_route_intx_to_irq once (e.g. in the device init function which is invoked afterward) to fill its cache and receive a notification if an update is needed. I do not see why, and specifically how you could query the route earlier or register a callback.

Before pci_bus_irqs is called.
Why is another question.

Quoted 13 lines
Quoted 7 lines

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

pci_set_bus_intx_routing is really only for the initial setup of the static INTx pin routes. And this happens on pci_bus_irqs/pci_register_bus, ie. triggered by the host bridge. By that time, there can't be any notifier listeners - as there are no devices yet.

Quoted 5 lines
Quoted 2 lines

Jan

What I am saying is we'll cache the final IRQ at some point. Pretend it's already that way so callers are ready for this.

This wouldn't change the picture very much: Before the host bridge is fully initialized, there is no valid route available. But before that, there is also no device attached to it. So the invocation pattern wouldn't change.

What would change is the semantic of the interface to the host bridge. So what about this: provide a public pci_root_bus_intx_routing_updated which so far just calls the internal-use-only pci_bus_fire_intx_routing_notifier?

Jan

#43 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 51 lines · Jan Kiszka
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jan Kiszka
Quoted 2 lines · Michael S. Tsirkin

It's OK to use recursion but when done through a callback like this it's unreadable.

Isn't the alternative poking into foreign bridge device states for their secondary buses?

pci_set_bus_intx_routing does this already.

True. OK, I can do the recursion in pci_bus_fire_intx_routing_notifier directly instead of pushing this into the bridge.

Quoted 26 lines
Quoted 9 lines
Quoted 3 lines

Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

Once a PCI device is registered, the INTx route can be queried. So the device user will call pci_device_route_intx_to_irq once (e.g. in the device init function which is invoked afterward) to fill its cache and receive a notification if an update is needed. I do not see why, and specifically how you could query the route earlier or register a callback.

Before pci_bus_irqs is called.
Why is another question.

Quoted 13 lines
Quoted 7 lines

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

pci_set_bus_intx_routing is really only for the initial setup of the static INTx pin routes. And this happens on pci_bus_irqs/pci_register_bus, ie. triggered by the host bridge. By that time, there can't be any notifier listeners - as there are no devices yet.

Quoted 5 lines
Quoted 2 lines

Jan

What I am saying is we'll cache the final IRQ at some point. Pretend it's already that way so callers are ready for this.

This wouldn't change the picture very much: Before the host bridge is fully initialized, there is no valid route available. But before that, there is also no device attached to it. So the invocation pattern wouldn't change.

Quoted 7 lines

What would change is the semantic of the interface to the host bridge. So what about this: provide a public pci_root_bus_intx_routing_updated which so far just calls the internal-use-only pci_bus_fire_intx_routing_notifier?

Jan

I think a better name is pci_bus_update_intx_irq_cache or something like that.

And I really think it's better to recalculate the intx routing there as well, so that if some bus implements a dynamic route_intx it just needs to call this after update.

Signature · 1 line
MST
#44 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jan Kiszka
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jan Kiszka
Quoted 2 lines · Michael S. Tsirkin

It's OK to use recursion but when done through a callback like this it's unreadable.

Isn't the alternative poking into foreign bridge device states for their secondary buses?

pci_set_bus_intx_routing does this already.

True. OK, I can do the recursion in pci_bus_fire_intx_routing_notifier directly instead of pushing this into the bridge.

Quoted 26 lines
Quoted 9 lines
Quoted 3 lines

Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

Once a PCI device is registered, the INTx route can be queried. So the device user will call pci_device_route_intx_to_irq once (e.g. in the device init function which is invoked afterward) to fill its cache and receive a notification if an update is needed. I do not see why, and specifically how you could query the route earlier or register a callback.

Before pci_bus_irqs is called.
Why is another question.

Quoted 13 lines
Quoted 7 lines

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

pci_set_bus_intx_routing is really only for the initial setup of the static INTx pin routes. And this happens on pci_bus_irqs/pci_register_bus, ie. triggered by the host bridge. By that time, there can't be any notifier listeners - as there are no devices yet.

Quoted 5 lines
Quoted 2 lines

Jan

What I am saying is we'll cache the final IRQ at some point. Pretend it's already that way so callers are ready for this.

This wouldn't change the picture very much: Before the host bridge is fully initialized, there is no valid route available. But before that, there is also no device attached to it. So the invocation pattern wouldn't change.

What would change is the semantic of the interface to the host bridge. So what about this: provide a public pci_root_bus_intx_routing_updated which so far just calls the internal-use-only pci_bus_fire_intx_routing_notifier?

Quoted 5 lines
Quoted 2 lines

Jan

I think a better name is pci_bus_update_intx_irq_cache or something like that.

At least "update cache" is not a better description as it implies in the function name the required steps of the implementation. In fact, this function /may/ update a cache and will fire notifiers. But that's nothing the care should worry about.

Quoted 5 lines

And I really think it's better to recalculate the intx routing there as well, so that if some bus implements a dynamic route_intx it just needs to call this after update.

I thought dynamic routing is disallowed according to the spec? If not, I agree.

Jan

#45 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

Quoted 58 lines · Jan Kiszka
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jan Kiszka
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jan Kiszka
Quoted 2 lines · Michael S. Tsirkin

It's OK to use recursion but when done through a callback like this it's unreadable.

Isn't the alternative poking into foreign bridge device states for their secondary buses?

pci_set_bus_intx_routing does this already.

True. OK, I can do the recursion in pci_bus_fire_intx_routing_notifier directly instead of pushing this into the bridge.

Quoted 26 lines
Quoted 9 lines
Quoted 3 lines

Also, you need to setup you cache after intx cache has been initialized, and you provide no clean way to do that.

Once a PCI device is registered, the INTx route can be queried. So the device user will call pci_device_route_intx_to_irq once (e.g. in the device init function which is invoked afterward) to fill its cache and receive a notification if an update is needed. I do not see why, and specifically how you could query the route earlier or register a callback.

Before pci_bus_irqs is called.
Why is another question.

Quoted 13 lines
Quoted 7 lines

One way to fix all this is call the notifier for devices, if set, from pci_set_bus_intx_routing.
Then assume that intx to irq translations can be cached even though they aren't now. So you will need to invoke pci_set_bus_intx_routing on intx to irq mapping changes, and that fires the notifier for free.

pci_set_bus_intx_routing is really only for the initial setup of the static INTx pin routes. And this happens on pci_bus_irqs/pci_register_bus, ie. triggered by the host bridge. By that time, there can't be any notifier listeners - as there are no devices yet.

Quoted 5 lines
Quoted 2 lines

Jan

What I am saying is we'll cache the final IRQ at some point. Pretend it's already that way so callers are ready for this.

This wouldn't change the picture very much: Before the host bridge is fully initialized, there is no valid route available. But before that, there is also no device attached to it. So the invocation pattern wouldn't change.

What would change is the semantic of the interface to the host bridge. So what about this: provide a public pci_root_bus_intx_routing_updated which so far just calls the internal-use-only pci_bus_fire_intx_routing_notifier?

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

Jan

I think a better name is pci_bus_update_intx_irq_cache or something like that.

At least "update cache" is not a better description as it implies in the function name the required steps of the implementation.

That's only reasonable: saying what a function does limits the implementation at some level.
If you don't you end up with no way to understand it or check for correctness unless you find and read all callers as well.

Quoted 2 lines

In fact, this
function /may/ update a cache and will fire notifiers.

notifiers *if any*. And the only reason to have a notifier is if you cache the routing.

Quoted 1 line

But that's nothing the care should worry about.

IMO function name should say what it does, not
how it does it (fire notifiers) or when
it should be called (routing updated).

Quoted 11 lines
Quoted 5 lines

And I really think it's better to recalculate the intx routing there as well, so that if some bus implements a dynamic route_intx it just needs to call this after update.

I thought dynamic routing is disallowed according to the spec? If not, I agree.

Jan

I think it is in pci to pci bridges, but might not be in pci host bridges. It's not a hard requirement though, but nice to have.

Signature · 1 line
MST
#46 lore raw

Re: [Qemu-devel] [PATCH 06/13] pci: Add INTx routing notifier

In reply to Jan Kiszka
Quoted 20 lines · Jan Kiszka
Quoted 20 lines
Quoted 19 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

Review PCIBus *pci_register_bus(DeviceState *parent, const char *name, · line 325

Quoted 5 lines
(quoted diff) +1 -0
@@ -318,6 +322,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);

Well true it fires the notifier but what it does conceptually is update intx routing.

Quoted 7 lines
Quoted 1 line

Nope, it informs about updates _after_ they happened.

Don't we need to update the cached pin if this happens? If yes I would this a better API would both update the cache and then trigger a notifier.
And the notifier can then be cache change notifier, and the "fire" function would instead be "update_cache".

See above, the cached part of the route is static anyway. What changes is the host bridge configuration.

Quoted 7 lines
Quoted 3 lines

You are saying it is only the intx to irq routing that can change?
So maybe "pci_bus_update_intx_to_irq_routing"?

Again, this function does not _update_ anything. It informs about a host-bridge-specific update, i.e. something that happened outside the generic code beforehand.

Yes it does what it says but it's an ugly interface all the same. What does a host device emulation care about notifiers? It's an implementation detail.

The *real* reason is that someone caches intx to irq routing and you need to update that cache.

So just say so.

Signature · 1 line
MST
author
#47 lore raw

PATCH 7/13 pci: Make domain and bus unsigned in pci_read_devaddr

In reply to Jan Kiszka

It's the more appropriate type as there are no negative domain or bus values.

---
 hw/pci-hotplug.c |    4 ++--
 hw/pci.c         |   11 ++++++-----
 hw/pci.h         |    4 ++--
 3 files changed, 10 insertions(+), 9 deletions(-)
hw/pci-hotplug.c +2 -2
index c55d8b9..e0ea8bb 100644
@@ -108,7 +108,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
 int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
                       DriveInfo *dinfo, int type)
 {
-    int dom, pci_bus;
+    unsigned int dom, pci_bus;
     unsigned slot;
     PCIDevice *dev;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
@@ -257,7 +257,7 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
 static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
 {
     PCIDevice *d;
-    int dom, bus;
+    unsigned int dom, bus;
     unsigned slot;
     Error *local_err = NULL;
 
hw/pci.c +6 -5
index 5b99f4b..d4c8b71 100644
@@ -512,8 +512,9 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
  * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
-                      unsigned int *slotp, unsigned int *funcp)
+static int pci_parse_devaddr(const char *addr, unsigned int *domp,
+                             unsigned int *busp, unsigned int *slotp,
+                             unsigned int *funcp)
 {
     const char *p;
     char *e;
@@ -571,8 +572,8 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
     return 0;
 }
 
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp)
+int pci_read_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
+                     unsigned int *busp, unsigned *slotp)
 {
     /* strip legacy tag */
     if (!strncmp(addr, "pci_addr=", 9)) {
@@ -587,7 +588,7 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
 
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 {
-    int dom, bus;
+    unsigned int dom, bus;
     unsigned slot;
 
     if (!devaddr) {
hw/pci.h +2 -2
index e7237cf..0c38c36 100644
@@ -340,8 +340,8 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp);
+int pci_read_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
+                     unsigned int *busp, unsigned *slotp);
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
Signature · 1 line
1.7.3.4
author
#48 lore raw

PATCH 8/13 pci: Export pci_parse_devaddr instead of pci_read_devaddr

In reply to Jan Kiszka

The latter is an internal helper for PCI hotplug. So move it where it belongs - before someone misuses it - and export the more versatile pci_parse_devaddr instead.

---
 hw/pci-hotplug.c |   18 ++++++++++++++++--
 hw/pci.c         |   19 ++-----------------
 hw/pci.h         |    4 ++--
 3 files changed, 20 insertions(+), 21 deletions(-)
hw/pci-hotplug.c +16 -2
index e0ea8bb..e1654dc 100644
@@ -34,6 +34,20 @@
 #include "blockdev.h"
 #include "error.h"
 
+static int read_pci_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
+                            unsigned int *busp, unsigned *slotp)
+{
+    /* strip legacy tag */
+    if (!strncmp(addr, "pci_addr=", 9)) {
+        addr += 9;
+    }
+    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
+        monitor_printf(mon, "Invalid pci address\n");
+        return -1;
+    }
+    return 0;
+}
+
 #if defined(TARGET_I386)
 static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
                                        const char *devaddr,
@@ -115,7 +129,7 @@ int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
 
     switch (type) {
     case IF_SCSI:
-        if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
+        if (read_pci_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
             goto err;
         }
         dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
@@ -261,7 +275,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
     unsigned slot;
     Error *local_err = NULL;
 
-    if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
+    if (read_pci_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
         return -1;
     }
 
hw/pci.c +2 -17
index d4c8b71..6471a68 100644
@@ -512,9 +512,8 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
  * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-static int pci_parse_devaddr(const char *addr, unsigned int *domp,
-                             unsigned int *busp, unsigned int *slotp,
-                             unsigned int *funcp)
+int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
+                      unsigned int *slotp, unsigned int *funcp)
 {
     const char *p;
     char *e;
@@ -572,20 +571,6 @@ static int pci_parse_devaddr(const char *addr, unsigned int *domp,
     return 0;
 }
 
-int pci_read_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
-                     unsigned int *busp, unsigned *slotp)
-{
-    /* strip legacy tag */
-    if (!strncmp(addr, "pci_addr=", 9)) {
-        addr += 9;
-    }
-    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
-        monitor_printf(mon, "Invalid pci address\n");
-        return -1;
-    }
-    return 0;
-}
-
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 {
     unsigned int dom, bus;
hw/pci.h +2 -2
index 0c38c36..552a586 100644
@@ -340,8 +340,8 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-int pci_read_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
-                     unsigned int *busp, unsigned *slotp);
+int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
+                      unsigned int *slotp, unsigned int *funcp);
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
Signature · 1 line
1.7.3.4
author
#49 lore raw

PATCH 9/13 pci: Introduce and apply PCIDeviceAddress

In reply to Jan Kiszka

This type encapsulates everything from domain to function. Use it first to simplify the pci_parse_devaddr interface.

---
 hw/pci-hotplug.c |   29 ++++++++++++++---------------
 hw/pci.c         |   31 ++++++++++++++-----------------
 hw/pci.h         |    6 ++++--
 qemu-common.h    |    7 +++++++
 4 files changed, 39 insertions(+), 34 deletions(-)
hw/pci-hotplug.c +14 -15
index e1654dc..aff4d85 100644
@@ -34,14 +34,14 @@
 #include "blockdev.h"
 #include "error.h"
 
-static int read_pci_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
-                            unsigned int *busp, unsigned *slotp)
+static int read_pci_devaddr(Monitor *mon, const char *addrstr,
+                            PCIDeviceAddress *addr)
 {
     /* strip legacy tag */
-    if (!strncmp(addr, "pci_addr=", 9)) {
-        addr += 9;
+    if (!strncmp(addrstr, "pci_addr=", 9)) {
+        addrstr += 9;
     }
-    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
+    if (pci_parse_devaddr(addrstr, addr, 0)) {
         monitor_printf(mon, "Invalid pci address\n");
         return -1;
     }
@@ -122,18 +122,17 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
 int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
                       DriveInfo *dinfo, int type)
 {
-    unsigned int dom, pci_bus;
-    unsigned slot;
+    PCIDeviceAddress addr;
     PCIDevice *dev;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
 
     switch (type) {
     case IF_SCSI:
-        if (read_pci_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
+        if (read_pci_devaddr(mon, pci_addr, &addr)) {
             goto err;
         }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
-                              PCI_DEVFN(slot, 0));
+        dev = pci_find_device(pci_find_root_bus(addr.domain), addr.bus,
+                              PCI_DEVFN(addr.slot, 0));
         if (!dev) {
             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
             goto err;
@@ -270,18 +269,18 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
 
 static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
 {
+    PCIDeviceAddress addr;
     PCIDevice *d;
-    unsigned int dom, bus;
-    unsigned slot;
     Error *local_err = NULL;
 
-    if (read_pci_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
+    if (read_pci_devaddr(mon, pci_addr, &addr)) {
         return -1;
     }
 
-    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
+    d = pci_find_device(pci_find_root_bus(addr.domain), addr.bus,
+                        PCI_DEVFN(addr.slot, 0));
     if (!d) {
-        monitor_printf(mon, "slot %d empty\n", slot);
+        monitor_printf(mon, "slot %d empty\n", addr.slot);
         return -1;
     }
 
hw/pci.c +14 -17
index 6471a68..4d700a9 100644
@@ -509,20 +509,20 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
 }
 
 /*
- * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
+ * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if !PCI_DEVADDR_WITH_FUNC
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
-                      unsigned int *slotp, unsigned int *funcp)
+int pci_parse_devaddr(const char *addrstr, PCIDeviceAddress *addr,
+                      unsigned int flags)
 {
     const char *p;
     char *e;
     unsigned long val;
     unsigned long dom = 0, bus = 0;
-    unsigned int slot = 0;
+    unsigned int slot;
     unsigned int func = 0;
 
-    p = addr;
+    p = addrstr;
     val = strtoul(p, &e, 16);
     if (e == p)
 	return -1;
@@ -544,7 +544,7 @@ int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
 
     slot = val;
 
-    if (funcp != NULL) {
+    if (flags & PCI_DEVADDR_WITH_FUNC) {
         if (*e != '.')
             return -1;
 
@@ -556,37 +556,34 @@ int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
         func = val;
     }
 
-    /* if funcp == NULL func is 0 */
     if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7)
 	return -1;
 
     if (*e)
 	return -1;
 
-    *domp = dom;
-    *busp = bus;
-    *slotp = slot;
-    if (funcp != NULL)
-        *funcp = func;
+    addr->domain = dom;
+    addr->bus = bus;
+    addr->slot = slot;
+    addr->function = func;
     return 0;
 }
 
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 {
-    unsigned int dom, bus;
-    unsigned slot;
+    PCIDeviceAddress addr;
 
     if (!devaddr) {
         *devfnp = -1;
         return pci_find_bus_nr(pci_find_root_bus(0), 0);
     }
 
-    if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
+    if (pci_parse_devaddr(devaddr, &addr, 0) < 0) {
         return NULL;
     }
 
-    *devfnp = PCI_DEVFN(slot, 0);
-    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
+    *devfnp = PCI_DEVFN(addr.slot, 0);
+    return pci_find_bus_nr(pci_find_root_bus(addr.domain), addr.bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
hw/pci.h +4 -2
index 552a586..6c48ffa 100644
@@ -340,8 +340,10 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
-                      unsigned int *slotp, unsigned int *funcp);
+#define PCI_DEVADDR_WITH_FUNC           2
+
+int pci_parse_devaddr(const char *addrstr, PCIDeviceAddress *addr,
+                      unsigned int flags);
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
qemu-common.h +7 -0
index 91e0562..32a35bc 100644
@@ -274,6 +274,13 @@ typedef enum LostTickPolicy {
     LOST_TICK_MAX
 } LostTickPolicy;
 
+typedef struct PCIDeviceAddress {
+    unsigned int domain;
+    unsigned int bus;
+    unsigned int slot;
+    unsigned int function;
+} PCIDeviceAddress;
+
 void tcg_exec_init(unsigned long tb_size);
 bool tcg_enabled(void);
 
Signature · 1 line
1.7.3.4
#50 lore raw

Re: [Qemu-devel] [PATCH 09/13] pci: Introduce and apply PCIDeviceAddress

Quoted 4 lines · Jan Kiszka

This type encapsulates everything from domain to function. Use it first to simplify the pci_parse_devaddr interface.

OK.
Except this really is a legacy interface.
So please call it PCILegacyDeviceAddress
or something like that.

Quoted 200 lines
---
 hw/pci-hotplug.c |   29 ++++++++++++++---------------
 hw/pci.c         |   31 ++++++++++++++-----------------
 hw/pci.h         |    6 ++++--
 qemu-common.h    |    7 +++++++
 4 files changed, 39 insertions(+), 34 deletions(-)
hw/pci-hotplug.c +14 -15
index e1654dc..aff4d85 100644
@@ -34,14 +34,14 @@
 #include "blockdev.h"
 #include "error.h"
 
-static int read_pci_devaddr(Monitor *mon, const char *addr, unsigned int *domp,
-                            unsigned int *busp, unsigned *slotp)
+static int read_pci_devaddr(Monitor *mon, const char *addrstr,
+                            PCIDeviceAddress *addr)
 {
     /* strip legacy tag */
-    if (!strncmp(addr, "pci_addr=", 9)) {
-        addr += 9;
+    if (!strncmp(addrstr, "pci_addr=", 9)) {
+        addrstr += 9;
     }
-    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
+    if (pci_parse_devaddr(addrstr, addr, 0)) {
         monitor_printf(mon, "Invalid pci address\n");
         return -1;
     }
@@ -122,18 +122,17 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
 int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
                       DriveInfo *dinfo, int type)
 {
-    unsigned int dom, pci_bus;
-    unsigned slot;
+    PCIDeviceAddress addr;
     PCIDevice *dev;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
 
     switch (type) {
     case IF_SCSI:
-        if (read_pci_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
+        if (read_pci_devaddr(mon, pci_addr, &addr)) {
             goto err;
         }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
-                              PCI_DEVFN(slot, 0));
+        dev = pci_find_device(pci_find_root_bus(addr.domain), addr.bus,
+                              PCI_DEVFN(addr.slot, 0));
         if (!dev) {
             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
             goto err;
@@ -270,18 +269,18 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
 
 static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
 {
+    PCIDeviceAddress addr;
     PCIDevice *d;
-    unsigned int dom, bus;
-    unsigned slot;
     Error *local_err = NULL;
 
-    if (read_pci_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
+    if (read_pci_devaddr(mon, pci_addr, &addr)) {
         return -1;
     }
 
-    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
+    d = pci_find_device(pci_find_root_bus(addr.domain), addr.bus,
+                        PCI_DEVFN(addr.slot, 0));
     if (!d) {
-        monitor_printf(mon, "slot %d empty\n", slot);
+        monitor_printf(mon, "slot %d empty\n", addr.slot);
         return -1;
     }
 
hw/pci.c +14 -17
index 6471a68..4d700a9 100644
@@ -509,20 +509,20 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
 }
 
 /*
- * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
+ * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if !PCI_DEVADDR_WITH_FUNC
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
-                      unsigned int *slotp, unsigned int *funcp)
+int pci_parse_devaddr(const char *addrstr, PCIDeviceAddress *addr,
+                      unsigned int flags)
 {
     const char *p;
     char *e;
     unsigned long val;
     unsigned long dom = 0, bus = 0;
-    unsigned int slot = 0;
+    unsigned int slot;
     unsigned int func = 0;
 
-    p = addr;
+    p = addrstr;
     val = strtoul(p, &e, 16);
     if (e == p)
 	return -1;
@@ -544,7 +544,7 @@ int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
 
     slot = val;
 
-    if (funcp != NULL) {
+    if (flags & PCI_DEVADDR_WITH_FUNC) {
         if (*e != '.')
             return -1;
 
@@ -556,37 +556,34 @@ int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
         func = val;
     }
 
-    /* if funcp == NULL func is 0 */
     if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7)
 	return -1;
 
     if (*e)
 	return -1;
 
-    *domp = dom;
-    *busp = bus;
-    *slotp = slot;
-    if (funcp != NULL)
-        *funcp = func;
+    addr->domain = dom;
+    addr->bus = bus;
+    addr->slot = slot;
+    addr->function = func;
     return 0;
 }
 
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 {
-    unsigned int dom, bus;
-    unsigned slot;
+    PCIDeviceAddress addr;
 
     if (!devaddr) {
         *devfnp = -1;
         return pci_find_bus_nr(pci_find_root_bus(0), 0);
     }
 
-    if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
+    if (pci_parse_devaddr(devaddr, &addr, 0) < 0) {
         return NULL;
     }
 
-    *devfnp = PCI_DEVFN(slot, 0);
-    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
+    *devfnp = PCI_DEVFN(addr.slot, 0);
+    return pci_find_bus_nr(pci_find_root_bus(addr.domain), addr.bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
hw/pci.h +4 -2
index 552a586..6c48ffa 100644
@@ -340,8 +340,10 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-int pci_parse_devaddr(const char *addr, unsigned int *domp, unsigned int *busp,
-                      unsigned int *slotp, unsigned int *funcp);
+#define PCI_DEVADDR_WITH_FUNC           2
+
+int pci_parse_devaddr(const char *addrstr, PCIDeviceAddress *addr,
+                      unsigned int flags);
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
qemu-common.h +7 -0
index 91e0562..32a35bc 100644
@@ -274,6 +274,13 @@ typedef enum LostTickPolicy {
     LOST_TICK_MAX
 } LostTickPolicy;
 
+typedef struct PCIDeviceAddress {
+    unsigned int domain;
+    unsigned int bus;
+    unsigned int slot;
+    unsigned int function;
+} PCIDeviceAddress;
+
 void tcg_exec_init(unsigned long tb_size);
 bool tcg_enabled(void);
 
Signature · 1 line
1.7.3.4
#51 lore raw

Re: [Qemu-devel] [PATCH 09/13] pci: Introduce and apply PCIDeviceAddress

Quoted 10 lines · Michael S. Tsirkin
Quoted 4 lines · Jan Kiszka

This type encapsulates everything from domain to function. Use it first to simplify the pci_parse_devaddr interface.

OK.
Except this really is a legacy interface.
So please call it PCILegacyDeviceAddress
or something like that.

Nope. It might be used for legacy addressing of emulated devices, but it's not legacy for PCI host devices. The address container is neutral /wrt its usage.

Jan

author
#52 lore raw

PATCH 10/13 pci: Fix coding style of pci_parse_devaddr

In reply to Jan Kiszka

So that we can move it unmodified without raising alarms. No functional changes.

---
 hw/pci.c |   52 ++++++++++++++++++++++++++++------------------------
 1 files changed, 28 insertions(+), 24 deletions(-)
hw/pci.c +28 -24
index 4d700a9..62ad61c 100644
@@ -524,43 +524,47 @@ int pci_parse_devaddr(const char *addrstr, PCIDeviceAddress *addr,
 
     p = addrstr;
     val = strtoul(p, &e, 16);
-    if (e == p)
-	return -1;
+    if (e == p) {
+        return -1;
+    }
     if (*e == ':') {
-	bus = val;
-	p = e + 1;
-	val = strtoul(p, &e, 16);
-	if (e == p)
-	    return -1;
-	if (*e == ':') {
-	    dom = bus;
-	    bus = val;
-	    p = e + 1;
-	    val = strtoul(p, &e, 16);
-	    if (e == p)
-		return -1;
-	}
+        bus = val;
+        p = e + 1;
+        val = strtoul(p, &e, 16);
+        if (e == p) {
+            return -1;
+        }
+        if (*e == ':') {
+            dom = bus;
+            bus = val;
+            p = e + 1;
+            val = strtoul(p, &e, 16);
+            if (e == p) {
+                return -1;
+            }
+        }
     }
 
     slot = val;
 
     if (flags & PCI_DEVADDR_WITH_FUNC) {
-        if (*e != '.')
+        if (*e != '.') {
             return -1;
-
+        }
         p = e + 1;
         val = strtoul(p, &e, 16);
-        if (e == p)
+        if (e == p) {
             return -1;
-
+        }
         func = val;
     }
 
-    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7)
-	return -1;
-
-    if (*e)
-	return -1;
+    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
+        return -1;
+    }
+    if (*e) {
+        return -1;
+    }
 
     addr->domain = dom;
     addr->bus = bus;
Signature · 1 line
1.7.3.4
author
#53 lore raw

PATCH 11/13 Move pci_parse_devaddr to qdev-properties

In reply to Jan Kiszka

We will some use this function also for property parsing, so move it over unmodified and rename it.

---
 hw/pci-hotplug.c     |    2 +-
 hw/pci.c             |   67 +-------------------------------------------------
 hw/pci.h             |    5 ---
 hw/qdev-properties.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    5 +++
 5 files changed, 72 insertions(+), 72 deletions(-)
hw/pci-hotplug.c +1 -1
index aff4d85..60c8989 100644
@@ -41,7 +41,7 @@ static int read_pci_devaddr(Monitor *mon, const char *addrstr,
     if (!strncmp(addrstr, "pci_addr=", 9)) {
         addrstr += 9;
     }
-    if (pci_parse_devaddr(addrstr, addr, 0)) {
+    if (qemu_parse_pci_devaddr(addrstr, addr, 0)) {
         monitor_printf(mon, "Invalid pci address\n");
         return -1;
     }
hw/pci.c +1 -66

79 lines not on this page · raw message

hw/pci.h +0 -5
index 6c48ffa..a3e5ad9 100644
@@ -340,11 +340,6 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-#define PCI_DEVADDR_WITH_FUNC           2
-
-int pci_parse_devaddr(const char *addrstr, PCIDeviceAddress *addr,
-                      unsigned int flags);
-
 void pci_device_deassert_intx(PCIDevice *dev);
 
 static inline void
hw/qdev-properties.c +65 -0

71 lines not on this page · raw message

hw/qdev.h +5 -0
index 4e90119..102550b 100644
@@ -360,4 +360,9 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
 
 extern int qdev_hotplug;
 
+#define PCI_DEVADDR_WITH_FUNC           2
+
+int qemu_parse_pci_devaddr(const char *addrstr, PCIDeviceAddress *addr,
+                           unsigned int flags);
+
 #endif
Signature · 1 line
1.7.3.4
#54 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Am 04.06.2012 10:52, schrieb Jan Kiszka:

Quoted 4 lines

We will some use this function also for property parsing, so move it over unmodified and rename it.

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Thanks,
Andreas

Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
#55 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Quoted 10 lines · Andreas Färber

Am 04.06.2012 10:52, schrieb Jan Kiszka:

Quoted 4 lines

We will some use this function also for property parsing, so move it over unmodified and rename it.

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Depends on how long merging of those branches shall take. This is some important piece for preparing device assignment for upstream, thus finally closing the qemu-kvm fork. I need all this back-merged in qemu-kvm soon to proceed.

Can you (both) comment on the merge schedule for your patches? Are we talking about a week or so?

Jan

#56 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 07.06.2012 17:11, schrieb Jan Kiszka:

Quoted 7 lines · Andreas Färber
Quoted 5 lines

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Quoted 7 lines

Depends on how long merging of those branches shall take. This is some important piece for preparing device assignment for upstream, thus finally closing the qemu-kvm fork. I need all this back-merged in qemu-kvm soon to proceed.

Can you (both) comment on the merge schedule for your patches? Are we talking about a week or so?

I'm working towards sending the updated patches from realize branch today and the PULL by tomorrow. When it gets merged I cannot predict.

We could speed this up if Paolo takes a look at what I have so far, starting at "qdev: Push state up to Object":
https://github.com/afaerber/qemu-cpu/commits/realize
- From there on I expect it's gonna be cherry-picking and rebasing again.

Maybe split your series in two? I can cc you on the PULL so that you can rebase and immediately piggyback the property changes. ;)

Andreas

- --
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg -----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)

iQIcBAEBAgAGBQJP0M8rAAoJEPou0S0+fgE/928P/jTqH25GYtdtqPYLVkjRcMjL mRTl2ar8UOuqFdFFZMKOtoGXNK2lmcqAHkQ8++EkFdhzlrVvLOGVhG4/abRKr8Bx dKv5j1xNSW1wG7arDIWQj6EuKOBuzlCtBrHrU83vq5hcx3usJZJUJeoLH1D1D9st FCMRPy1g4NLIqPhoOfp1muqP9VLBVwmpKuFzXTe1Z3l4eIRY61jNKfnQF9zczUWy eJj2ntvBFOOD9myyCfyEcw1bnLNA7UalyhSGQ4ien8novlyYXCqT5+1uLdYeUmdm BTlPXlyRs5yrawFn2VlKEULxKQWyb+ddJzM+ppHGzdFRz4keqwkbGaCfKliuDJbN AASeN4IWLJMCJxz68eZvKSvzMn5A2IzwtFx0N04l4rZbTlylQtoZ5/W4D//+mH2n hOvZNptsI5Ht29G1hDL5z/VdseRV3XjR64S578bKOj1icpNLfmV4uyNA/gwMOp8Q htzaswdSMejeeJvbxylEtuh1phyMJmnwUf2L+JuG1Ay1v3QngrsVX2gJqnC8ES3w LqiIf1J08T9BhPLYrmm3pAsb5dorSLz+vZmhVB3iZlQAJXuEAjyaZoZJo/u02zY1 BRGfG0HCB4b94FVpcTTorFjf57oSB4MG/xN31rtovBX25oRXNFMWqemetF8A8IWc kprIWBCzOSC2ZGE1SXzL
=DLcx
-----END PGP SIGNATURE-----

author
#57 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Quoted 13 lines · Andreas Färber

Am 07.06.2012 17:11, schrieb Jan Kiszka:

Quoted 11 lines · Andreas Färber
Quoted 5 lines

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Depends on how long merging of those branches shall take. This is some important piece for preparing device assignment for upstream, thus finally closing the qemu-kvm fork. I need all this back-merged in qemu-kvm soon to proceed.

Quoted 5 lines
Quoted 2 lines

Can you (both) comment on the merge schedule for your patches? Are we talking about a week or so?

I'm working towards sending the updated patches from realize branch today and the PULL by tomorrow. When it gets merged I cannot predict.

To my understanding, patch 2 of your series faces some discussions, and the rest will require refactoring once that has settled. So I guess it's better now to proceed with my patches and rebase your changes on top of them, right?

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#58 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Am 08.06.2012 12:57, schrieb Jan Kiszka:

Quoted 17 lines · Andreas Färber
Quoted 16 lines

Am 07.06.2012 17:11, schrieb Jan Kiszka:

Quoted 14 lines · Andreas Färber
Quoted 5 lines

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Depends on how long merging of those branches shall take. This is some important piece for preparing device assignment for upstream, thus finally closing the qemu-kvm fork. I need all this back-merged in qemu-kvm soon to proceed.

Can you (both) comment on the merge schedule for your patches? Are we talking about a week or so?

Quoted 7 lines
Quoted 2 lines

I'm working towards sending the updated patches from realize branch today and the PULL by tomorrow. When it gets merged I cannot predict.

To my understanding, patch 2 of your series faces some discussions, and the rest will require refactoring once that has settled. So I guess it's better now to proceed with my patches and rebase your changes on top of them, right?

No, there's a patch queue of 28 before the patches under discussion, some of which touch qdev-properties.c as well. Those under discussion are not on qom-next yet.
What's open is that the Makefile series has not been pulled yet and pretty much everyone will need to rebase on that if it gets applied. Hoping for a statement from Anthony there.

Can't understand that you're trying to push your v1 so hard now when our series have been on the list for much longer. ;)

Cheers,
Andreas

Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
author
#59 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Quoted 26 lines · Andreas Färber

Am 08.06.2012 12:57, schrieb Jan Kiszka:

Quoted 17 lines · Andreas Färber
Quoted 16 lines

Am 07.06.2012 17:11, schrieb Jan Kiszka:

Quoted 14 lines · Andreas Färber
Quoted 5 lines

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Depends on how long merging of those branches shall take. This is some important piece for preparing device assignment for upstream, thus finally closing the qemu-kvm fork. I need all this back-merged in qemu-kvm soon to proceed.

Can you (both) comment on the merge schedule for your patches? Are we talking about a week or so?

Quoted 7 lines
Quoted 2 lines

I'm working towards sending the updated patches from realize branch today and the PULL by tomorrow. When it gets merged I cannot predict.

To my understanding, patch 2 of your series faces some discussions, and the rest will require refactoring once that has settled. So I guess it's better now to proceed with my patches and rebase your changes on top of them, right?

Quoted 6 lines

No, there's a patch queue of 28 before the patches under discussion, some of which touch qdev-properties.c as well. Those under discussion are not on qom-next yet.
What's open is that the Makefile series has not been pulled yet and pretty much everyone will need to rebase on that if it gets applied. Hoping for a statement from Anthony there.

As I was on CC in that second series, right after you told me you would CC me to allow tracking progress. So I was assuming it was related to this topic.

Quoted 3 lines

Can't understand that you're trying to push your v1 so hard now when our series have been on the list for much longer. ;)

I explained the reason, and I think my patches (minus the dropped one) are ready based on the feedback.

I'm fine if important central refactorings close master for a short period at the beginning of a merge window and require rebasing of other patches afterward. But that should really be *short*.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#60 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Am 08.06.2012 14:14, schrieb Jan Kiszka:

Quoted 10 lines · Andreas Färber
Quoted 2 lines

Can't understand that you're trying to push your v1 so hard now when our series have been on the list for much longer. ;)

I explained the reason, and I think my patches (minus the dropped one) are ready based on the feedback.

I'm fine if important central refactorings close master for a short period at the beginning of a merge window and require rebasing of other patches afterward. But that should really be *short*.

We had a long Hard Freeze that closed master. Your patches are new, so I oppose you sneaking by and having me rebase Paolo's patches on yours. If someone else wants to rebase them on yours that's fine with me.

Andreas

Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
author
#61 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Quoted 8 lines · Andreas Färber

Am 08.06.2012 14:14, schrieb Jan Kiszka:

Quoted 7 lines · Andreas Färber
Quoted 2 lines

Can't understand that you're trying to push your v1 so hard now when our series have been on the list for much longer. ;)

I explained the reason, and I think my patches (minus the dropped one) are ready based on the feedback.

Quoted 7 lines
Quoted 3 lines

I'm fine if important central refactorings close master for a short period at the beginning of a merge window and require rebasing of other patches afterward. But that should really be *short*.

We had a long Hard Freeze that closed master. Your patches are new, so I oppose you sneaking by and having me rebase Paolo's patches on yours. If someone else wants to rebase them on yours that's fine with me.

If your patches get merged over the next week, I'm fine. If not, be warned to see me grumbling again. ;)

Michael, unless there are other remarks, 1 and 3-10 could be picked up by you and pushed already. I'll send an update for 6 to fix the commit log.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#62 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Quoted 17 lines · Jan Kiszka
Quoted 8 lines · Andreas Färber

Am 08.06.2012 14:14, schrieb Jan Kiszka:

Quoted 7 lines · Andreas Färber
Quoted 2 lines

Can't understand that you're trying to push your v1 so hard now when our series have been on the list for much longer. ;)

I explained the reason, and I think my patches (minus the dropped one) are ready based on the feedback.

Quoted 7 lines
Quoted 3 lines

I'm fine if important central refactorings close master for a short period at the beginning of a merge window and require rebasing of other patches afterward. But that should really be *short*.

We had a long Hard Freeze that closed master. Your patches are new, so I oppose you sneaking by and having me rebase Paolo's patches on yours. If someone else wants to rebase them on yours that's fine with me.

Quoted 7 lines

If your patches get merged over the next week, I'm fine. If not, be warned to see me grumbling again. ;)

Michael, unless there are other remarks, 1 and 3-10 could be picked up by you and pushed already. I'll send an update for 6 to fix the commit log.

Jan

They look ready to me too, so I can pick your patches up and put them on the pci branch. Prefer doing it Sunday when I'm rested.
But FYI I just sent a pull request to Anthony Thursday and I try not to flood him with more than one a week unless there's a huge regression to fix.

If large changes land in master meanwhile we'll have to resolve the conflict but that's par for the course.

Quoted 3 lines
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#63 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Quoted 24 lines · Michael S. Tsirkin
Quoted 23 lines · Jan Kiszka
Quoted 8 lines · Andreas Färber

Am 08.06.2012 14:14, schrieb Jan Kiszka:

Quoted 7 lines · Andreas Färber
Quoted 2 lines

Can't understand that you're trying to push your v1 so hard now when our series have been on the list for much longer. ;)

I explained the reason, and I think my patches (minus the dropped one) are ready based on the feedback.

Quoted 7 lines
Quoted 3 lines

I'm fine if important central refactorings close master for a short period at the beginning of a merge window and require rebasing of other patches afterward. But that should really be *short*.

We had a long Hard Freeze that closed master. Your patches are new, so I oppose you sneaking by and having me rebase Paolo's patches on yours. If someone else wants to rebase them on yours that's fine with me.

If your patches get merged over the next week, I'm fine. If not, be warned to see me grumbling again. ;)

Michael, unless there are other remarks, 1 and 3-10 could be picked up by you and pushed already. I'll send an update for 6 to fix the commit log.

Quoted 7 lines
Quoted 1 line

Jan

They look ready to me too, so I can pick your patches up and put them on the pci branch. Prefer doing it Sunday when I'm rested.
But FYI I just sent a pull request to Anthony Thursday and I try not to flood him with more than one a week unless there's a huge regression to fix.

FYI, I don't plan on applying any more pulls until Monday most likely as I'm flying back to the US tomorrow morning. If you want to update the PULL on Sunday, just send out a new request that includes the old and I'll ignore it.

Paolo's series may conflict, but I don't think resolving will be too hard.

Regards,

Anthony Liguori

Quoted 7 lines

If large changes land in master meanwhile we'll have to resolve the conflict but that's par for the course.

Quoted 3 lines

--
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

#64 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

In reply to Andreas Färber
Quoted 10 lines · Andreas Färber

Am 04.06.2012 10:52, schrieb Jan Kiszka:

Quoted 4 lines

We will some use this function also for property parsing, so move it over unmodified and rename it.

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Sorry, this doesn't scale.

Patches need to go in when they're ready. If that means someone branch has a hard time rebasing, it probably means that branch should have attempted to merge sooner.

If you want to work out the issues earlier, then setup a next branch or something like that.

But don't expect someone else to hold up there work just because it conflicts with yours. That kind of ordering won't scale in a community as large as ours.

Regards,

Anthony Liguori

Quoted 4 lines

Thanks,
Andreas

#65 lore raw

Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties

Am 08.06.2012 15:55, schrieb Anthony Liguori:

Quoted 5 lines · Andreas Färber
Quoted 4 lines

Am 04.06.2012 10:52, schrieb Jan Kiszka:

Quoted 3 lines

We will some use this function also for property parsing, so move it over unmodified and rename it.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

These last three patches collide with Paolo's QOM properties
refactoring: qdev properties are being generalized to Object and on my GitHub "realize" branch are being moved to qom/object-properties.c (object.c in the original series). Please defer this change.

Sorry, this doesn't scale.

Jinx! :)

Quoted 6 lines

Patches need to go in when they're ready. If that means someone branch has a hard time rebasing, it probably means that branch should have attempted to merge sooner.

If you want to work out the issues earlier, then setup a next branch or something like that.

We *are* talking about qom-NEXT here! It serves exactly that purpose, to have a known location for people to rebase on and to avoid conflicts. Jan was ignoring that, I'm guessing because he doesn't read qemu-devel unless cc'ed. And in turn I don't consider it the duty of the qom-next maintainer to check everyone's submission for possible fumbling in qdev/qom code and rebasing onto every random open PULL. (Note that I'm not complaining about properties being added in some random file, I am specifically annoyed about refactoring in hw/qdev-properties.c after these series have been around for like two months and after I officially announced the branch as requested by you.)

And let's not forget that a certain release manager promised to talk to me/us about the post-1.1 merge plan after rc4 but then instead decided to fold rc4 and final and opened up the master branch without discussing any merge strategy, contributing to this chaos. The way you are handling it, it is totally unclear for submaintainers in which order series are going to go in. So either we need to coordinate PULLs among each other as attempted here, or you as maintainer need to volunteer to merge such conflicting PULLs yourself and not just bouncing them.

Anyway, some people need to take care of packaging the tarball after it's released and your part in the release process is finished. That takes time, and your change of schedule stirred my time planning for a whole week. ;)

Plus a contributor to qom-next surpassing himself with another invasive refactoring that you wanted to fast-track wasn't helpful either.

Not to mention that this is also connected to a nack of yours for which we still don't have a solution, while the original author is on travels.

So yes, I could have started merging qom-next earlier (e.g., had I taken the decision to split it earlier) and you could've supported that effort better through early review, better planning and better communication.

Quoted 3 lines

But don't expect someone else to hold up there work just because it conflicts with yours. That kind of ordering won't scale in a community as large as ours.

I am only one and cannot rebase onto every open pull request, especially not for a branch that was only meant to bridge the imposed Hard Freeze and should thus go away quickly because no longer needed.

If it were a private branch/series of mine then that would be a different matter of course.

Nevertheless conflicts do happen and need to be resolved by someone. If you are volunteering, so that I don't have to speak up, that's fine with me. But saying that ordering doesn't scale in a community is not solving the problem.

Regards,
Andreas

Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
author
#66 lore raw

PATCH 12/13 qdev-properties: Use qemu_parse_pci_devaddr for pci-devfn property

In reply to Jan Kiszka

Generalize qemu_parse_pci_devaddr by two flags so that it can be used for parsing pci-devfn properties as well.

---
 hw/pci-hotplug.c     |    2 +-
 hw/pci.c             |    3 ++-
 hw/qdev-properties.c |   49 ++++++++++++++++++++++++-------------------------
 hw/qdev.h            |    2 ++
 4 files changed, 29 insertions(+), 27 deletions(-)
hw/pci-hotplug.c +1 -1
index 60c8989..3156e99 100644
@@ -41,7 +41,7 @@ static int read_pci_devaddr(Monitor *mon, const char *addrstr,
     if (!strncmp(addrstr, "pci_addr=", 9)) {
         addrstr += 9;
     }
-    if (qemu_parse_pci_devaddr(addrstr, addr, 0)) {
+    if (qemu_parse_pci_devaddr(addrstr, addr, PCI_DEVADDR_WITH_DOM_BUS_OPT)) {
         monitor_printf(mon, "Invalid pci address\n");
         return -1;
     }
hw/pci.c +2 -1
index 5056fc4..ccbc6aa 100644
@@ -517,7 +517,8 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
         return pci_find_bus_nr(pci_find_root_bus(0), 0);
     }
 
-    if (qemu_parse_pci_devaddr(devaddr, &addr, 0) < 0) {
+    if (qemu_parse_pci_devaddr(devaddr, &addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT) < 0) {
         return NULL;
     }
 
hw/qdev-properties.c +24 -25

82 lines not on this page · raw message

hw/qdev.h +2 -0
index 102550b..15acfca 100644
@@ -360,7 +360,9 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
 
 extern int qdev_hotplug;
 
+#define PCI_DEVADDR_WITH_DOM_BUS_OPT    1
 #define PCI_DEVADDR_WITH_FUNC           2
+#define PCI_DEVADDR_WITH_FUNC_OPT       4
 
 int qemu_parse_pci_devaddr(const char *addrstr, PCIDeviceAddress *addr,
                            unsigned int flags);
Signature · 1 line
1.7.3.4
author
#67 lore raw

PATCH 13/13 qdev-properties: Add pci-devaddr property

In reply to Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +48 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",
+    .get   = get_pci_devaddr,
+    .set   = set_pci_devaddr,
+};
+
 /* --- blocksize --- */
 
 static void set_blocksize(Object *obj, Visitor *v, void *opaque,
hw/qdev.h +3 -0
index 15acfca..d2c87a0 100644
@@ -224,6 +224,7 @@ extern PropertyInfo qdev_prop_drive;
 extern PropertyInfo qdev_prop_netdev;
 extern PropertyInfo qdev_prop_vlan;
 extern PropertyInfo qdev_prop_pci_devfn;
+extern PropertyInfo qdev_prop_pci_devaddr;
 extern PropertyInfo qdev_prop_blocksize;
 
 #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
@@ -288,6 +289,8 @@ extern PropertyInfo qdev_prop_blocksize;
                         LostTickPolicy)
 #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
+#define DEFINE_PROP_PCI_DEVADDR(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_devaddr, PCIDeviceAddress)
 
 #define DEFINE_PROP_END_OF_LIST()               \
     {}
Signature · 1 line
1.7.3.4
#68 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

Quoted 47 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +34 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 10 lines
hw/qdev-properties.c +10 -0
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address? This also should be built on linux only.
Can this be part of device assignment code instead of qdev?

Quoted 30 lines
hw/qdev-properties.c +4 -0
+    .get   = get_pci_devaddr,
+    .set   = set_pci_devaddr,
+};
+
 /* --- blocksize --- */
 
 static void set_blocksize(Object *obj, Visitor *v, void *opaque,
hw/qdev.h +3 -0
index 15acfca..d2c87a0 100644
@@ -224,6 +224,7 @@ extern PropertyInfo qdev_prop_drive;
 extern PropertyInfo qdev_prop_netdev;
 extern PropertyInfo qdev_prop_vlan;
 extern PropertyInfo qdev_prop_pci_devfn;
+extern PropertyInfo qdev_prop_pci_devaddr;
 extern PropertyInfo qdev_prop_blocksize;
 
 #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
@@ -288,6 +289,8 @@ extern PropertyInfo qdev_prop_blocksize;
                         LostTickPolicy)
 #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
+#define DEFINE_PROP_PCI_DEVADDR(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_devaddr, PCIDeviceAddress)
 
 #define DEFINE_PROP_END_OF_LIST()               \
     {}
Signature · 1 line
1.7.3.4
#69 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices? And Xen?

Jan

#70 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

Quoted 5 lines

And Xen?

Jan

#71 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 89 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Quoted 7 lines

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

So we need this generic service. Let's called it pci-host-devaddr and be fine?

Jan

#72 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 92 lines · Jan Kiszka
Quoted 91 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 6 lines

So we need this generic service. Let's called it pci-host-devaddr and be fine?

Jan

#73 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 99 lines · Michael S. Tsirkin
Quoted 98 lines · Jan Kiszka
Quoted 96 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

#74 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 108 lines · Jan Kiszka
Quoted 99 lines · Michael S. Tsirkin
Quoted 98 lines · Jan Kiszka
Quoted 96 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

Signature · 1 line
MST
#75 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 109 lines · Michael S. Tsirkin
Quoted 108 lines · Jan Kiszka
Quoted 106 lines · Michael S. Tsirkin
Quoted 92 lines · Jan Kiszka
Quoted 91 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device. Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

#76 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 113 lines · Jan Kiszka
Quoted 112 lines · Michael S. Tsirkin
Quoted 111 lines · Jan Kiszka
Quoted 99 lines · Michael S. Tsirkin
Quoted 98 lines · Jan Kiszka
Quoted 96 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

Signature · 1 line
MST
#77 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 131 lines · Michael S. Tsirkin
Quoted 113 lines · Jan Kiszka
Quoted 112 lines · Michael S. Tsirkin
Quoted 111 lines · Jan Kiszka
Quoted 99 lines · Michael S. Tsirkin
Quoted 98 lines · Jan Kiszka
Quoted 96 lines · Michael S. Tsirkin
Quoted 82 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

We can keep code duplications, of course.

Quoted 52 lines
Quoted 52 lines
---
 hw/qdev-properties.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h            |    3 +++
 2 files changed, 51 insertions(+), 0 deletions(-)
hw/qdev-properties.c +38 -0
index 32e41f1..6634f22 100644
@@ -946,6 +946,54 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+static void get_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    char buffer[10 + 3 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%02x",
+             addr->domain, addr->bus, addr->slot, addr->function);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pci_devaddr(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    PCIDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (qemu_parse_pci_devaddr(str, addr,
+                               PCI_DEVADDR_WITH_DOM_BUS_OPT |
+                               PCI_DEVADDR_WITH_FUNC) < 0) {
Quoted 8 lines

hw/qdev-properties.c PropertyInfo qdev_prop_pci_devfn = { · line 992

Quoted 6 lines
hw/qdev-properties.c +6 -0
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    }
+}
+
+PropertyInfo qdev_prop_pci_devaddr = {
+    .name  = "pci-devaddr",

This is a very confusing name. Something like host-pci-address?

Quoted 5 lines

That might be an option.

Quoted 1 line

This also should be built on linux only.

Why, what do we gain with #ifdefs? And isn't the addressing concept generic?

Not the XXX:XX.X format. And not the concept of a domain.

Quoted 3 lines
Quoted 1 line

Can this be part of device assignment code instead of qdev?

How does VFIO address their host devices?

You get an fd I think. I think you don't need to know the host address.

Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

Quoted 3 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Quoted 7 lines
Quoted 2 lines

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Alex

#78 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 17 lines · Alex Williamson
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

Quoted 7 lines
Quoted 7 lines
Quoted 2 lines

As far as I understand the API, there is no device file per assigned device.

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

Quoted 11 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

Quoted 7 lines

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Signature · 1 line
MST
#79 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 17 lines
Quoted 17 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Quoted 8 lines
Quoted 1 line

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken? How does UIO avoid such a problem. UIO-pci requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Alex

#80 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 59 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 17 lines
Quoted 17 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Quoted 8 lines
Quoted 1 line

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

Quoted 3 lines

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Only uio_pci_generic. Other uio devices let you drive the device.

Quoted 8 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Quoted 8 lines

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

Signature · 1 line
MST
#81 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 60 lines · Michael S. Tsirkin
Quoted 59 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 25 lines
Quoted 11 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

Quoted 7 lines

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

Quoted 6 lines
Quoted 3 lines

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

We don't have UUIDs on PCI devices, so who's to say that the device that was in slot 3 is the same device that's now in slot 4 and the user should still have access to it? That sounds even more problematic.

Quoted 10 lines
Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Only uio_pci_generic. Other uio devices let you drive the device.

If this is actually a problem, this is the first ever complaint I've heard about it. As above, I don't think we can assume the same access when a device is moved.

Quoted 15 lines
Quoted 15 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

No, vfio syntax is -device vfio-pci,host=0:3.0, just like pci-assign. Qemu will figure out which group that device belongs to and "do the right thing". If we add support for libvirt passing a groupfd, it will be mostly the same, just using scm_rights to get the groupfd instead of opening it directly. Thanks,

Alex

#82 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 65 lines · Alex Williamson
Quoted 64 lines · Michael S. Tsirkin
Quoted 62 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 17 lines
Quoted 17 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Quoted 8 lines
Quoted 1 line

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Quoted 6 lines
Quoted 2 lines

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

We don't have UUIDs on PCI devices, so who's to say that the device that was in slot 3 is the same device that's now in slot 4 and the user should still have access to it? That sounds even more problematic.

PF has a driver loaded so you can identify that, and identify the VF through it. Again this is really policy, it should be up to the admin how to name the device.

Quoted 8 lines
Quoted 8 lines
Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Quoted 6 lines
Quoted 2 lines

Only uio_pci_generic. Other uio devices let you drive the device.

If this is actually a problem, this is the first ever complaint I've heard about it. As above, I don't think we can assume the same access when a device is moved.

I thought need for sane naming and for sysfs interface was discussed multiple times. But maybe I'm misremembering.

Quoted 19 lines
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

Quoted 7 lines

No, vfio syntax is -device vfio-pci,host=0:3.0, just like pci-assign. Qemu will figure out which group that device belongs to and "do the right thing". If we add support for libvirt passing a groupfd, it will be mostly the same, just using scm_rights to get the groupfd instead of opening it directly. Thanks,

Alex

Then how do you know which /dev/vfio/# to open?

Signature · 1 line
MST
#83 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 69 lines · Michael S. Tsirkin
Quoted 68 lines · Alex Williamson
Quoted 66 lines · Michael S. Tsirkin
Quoted 59 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 17 lines
Quoted 17 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Quoted 8 lines
Quoted 1 line

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

Quoted 3 lines

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

Quoted 7 lines
Quoted 3 lines

We don't have UUIDs on PCI devices, so who's to say that the device that was in slot 3 is the same device that's now in slot 4 and the user should still have access to it? That sounds even more problematic.

PF has a driver loaded so you can identify that, and identify the VF through it. Again this is really policy, it should be up to the admin how to name the device.

Do PFs have a UUID? Some devices support a serial number, but that's not related to being a PF vs VF. We need to support both PFs and VFs regardless of whether they have any kind of UUID. I think we're inventing a problem though.

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Only uio_pci_generic. Other uio devices let you drive the device.

Quoted 6 lines
Quoted 3 lines

If this is actually a problem, this is the first ever complaint I've heard about it. As above, I don't think we can assume the same access when a device is moved.

I thought need for sane naming and for sysfs interface was discussed multiple times. But maybe I'm misremembering.

There is sane naming and a sysfs interface...

Quoted 25 lines
Quoted 25 lines
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

No, vfio syntax is -device vfio-pci,host=0:3.0, just like pci-assign. Qemu will figure out which group that device belongs to and "do the right thing". If we add support for libvirt passing a groupfd, it will be mostly the same, just using scm_rights to get the groupfd instead of opening it directly. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

Then how do you know which /dev/vfio/# to open?

This is all in the documentation patch... groups are exposed in sysfs in /sys/kernel/iommu_groups. Each group has a unique number which is exposed as a directory. Each group directory has a subdirectory called devices which links to all devices in the group. Each device within a group as an iommu_group link back to the group directory. The /dev/vfio/# entry matches the group number in sysfs. So it's all pretty easy. Thanks,

Alex

#84 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 74 lines · Alex Williamson
Quoted 73 lines · Michael S. Tsirkin
Quoted 71 lines · Alex Williamson
Quoted 60 lines · Michael S. Tsirkin
Quoted 59 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may
guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 25 lines
Quoted 11 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

Quoted 7 lines

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

Quoted 6 lines
Quoted 3 lines

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

We don't have UUIDs on PCI devices, so who's to say that the device that was in slot 3 is the same device that's now in slot 4 and the user should still have access to it? That sounds even more problematic.

Quoted 7 lines
Quoted 3 lines

PF has a driver loaded so you can identify that, and identify the VF through it. Again this is really policy, it should be up to the admin how to name the device.

Do PFs have a UUID? Some devices support a serial number, but that's not related to being a PF vs VF. We need to support both PFs and VFs regardless of whether they have any kind of UUID.

This is a solved problem. udev has class-specific ways to get the device id and use it to find the name.

Quoted 1 line

I think we're inventing a problem though.

You think persistent names in udev were a solution in search of a problem?

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Only uio_pci_generic. Other uio devices let you drive the device.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

If this is actually a problem, this is the first ever complaint I've heard about it. As above, I don't think we can assume the same access when a device is moved.

I thought need for sane naming and for sysfs interface was discussed multiple times. But maybe I'm misremembering.

There is sane naming and a sysfs interface...

It's not sane if the admin can't rename the device without breaking applications.

Quoted 37 lines
Quoted 25 lines
Quoted 25 lines
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

No, vfio syntax is -device vfio-pci,host=0:3.0, just like pci-assign. Qemu will figure out which group that device belongs to and "do the right thing". If we add support for libvirt passing a groupfd, it will be mostly the same, just using scm_rights to get the groupfd instead of opening it directly. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

Then how do you know which /dev/vfio/# to open?

This is all in the documentation patch... groups are exposed in sysfs in /sys/kernel/iommu_groups. Each group has a unique number which is exposed as a directory. Each group directory has a subdirectory called devices which links to all devices in the group. Each device within a group as an iommu_group link back to the group directory. The /dev/vfio/# entry matches the group number in sysfs. So it's all pretty easy. Thanks,

Quoted 1 line

Alex

So what's the problem to have devices in sysfs linked e.g. from /sys/class/vfio/ ? udev could create the nodes e.g. in /dev/vfio/devices/. User can then pass the device name and qemu can figure out the group from sysfs.

Signature · 1 line
MST
#85 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 79 lines · Michael S. Tsirkin
Quoted 78 lines · Alex Williamson
Quoted 76 lines · Michael S. Tsirkin
Quoted 65 lines · Alex Williamson
Quoted 64 lines · Michael S. Tsirkin
Quoted 62 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may
guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 17 lines
Quoted 17 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Quoted 8 lines
Quoted 1 line

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Quoted 6 lines
Quoted 2 lines

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

We don't have UUIDs on PCI devices, so who's to say that the device that was in slot 3 is the same device that's now in slot 4 and the user should still have access to it? That sounds even more problematic.

PF has a driver loaded so you can identify that, and identify the VF through it. Again this is really policy, it should be up to the admin how to name the device.

Quoted 6 lines
Quoted 3 lines

Do PFs have a UUID? Some devices support a serial number, but that's not related to being a PF vs VF. We need to support both PFs and VFs regardless of whether they have any kind of UUID.

This is a solved problem. udev has class-specific ways to get the device id and use it to find the name.

Usually via things discovered via device specific drivers, ex. MACs, disk UUIDs, etc. We don't have those in VFIO. Don't forget, VFIO is also device agnostic, VFIO-pci is just one possible driver backend.

Quoted 4 lines
Quoted 1 line

I think we're inventing a problem though.

You think persistent names in udev were a solution in search of a problem?

Of course not, but I've never heard any indication that this is a real problem for device assignment. If it is, like udev, why not solve it in userspace? The kernel doesn't provide the persistence that udev exposes.

Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 10 lines
Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Only uio_pci_generic. Other uio devices let you drive the device.

If this is actually a problem, this is the first ever complaint I've heard about it. As above, I don't think we can assume the same access when a device is moved.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

I thought need for sane naming and for sysfs interface was discussed multiple times. But maybe I'm misremembering.

There is sane naming and a sysfs interface...

It's not sane if the admin can't rename the device without breaking applications.

Again, udev provides that persistence, not the kernel.

Quoted 37 lines
Quoted 37 lines
Quoted 25 lines
Quoted 25 lines
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

No, vfio syntax is -device vfio-pci,host=0:3.0, just like pci-assign. Qemu will figure out which group that device belongs to and "do the right thing". If we add support for libvirt passing a groupfd, it will be mostly the same, just using scm_rights to get the groupfd instead of opening it directly. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

Then how do you know which /dev/vfio/# to open?

This is all in the documentation patch... groups are exposed in sysfs in /sys/kernel/iommu_groups. Each group has a unique number which is exposed as a directory. Each group directory has a subdirectory called devices which links to all devices in the group. Each device within a group as an iommu_group link back to the group directory. The /dev/vfio/# entry matches the group number in sysfs. So it's all pretty easy. Thanks,

Quoted 4 lines
Quoted 1 line

Alex

So what's the problem to have devices in sysfs linked e.g. from /sys/class/vfio/ ?

They have to be bound to a VFIO driver, ex. vfio-pci. We have iommu groups in sysfs and can use that for this purpose. I did have a class for this before iommu_group were more integrated at the device level, now it just seems redundant.

Quoted 3 lines

udev could create the nodes e.g. in
/dev/vfio/devices/. User can then pass the device name and qemu can figure out the group from sysfs.

As previously noted, we don't, and I don't think it makes sense to expose individual devices in VFIO as the interface is fundamentally group based by necessity. Groups are just containers and they do support a name, which is exposed in sysfs when it's used, but groups are created by topology and don't follow the devices, so I don't think that's what you're looking for. It seems that if someone wants to create persistence for VFIO, they just need to identify something unique about a device in sysfs, then follow the device to the group. Userpsace is far more capable of providing this than the kernel. Thanks,

Alex

#86 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

Quoted 84 lines · Alex Williamson
Quoted 83 lines · Michael S. Tsirkin
Quoted 81 lines · Alex Williamson
Quoted 69 lines · Michael S. Tsirkin
Quoted 68 lines · Alex Williamson
Quoted 66 lines · Michael S. Tsirkin
Quoted 59 lines · Alex Williamson
Quoted 21 lines · Michael S. Tsirkin
Quoted 20 lines · Alex Williamson
Quoted 20 lines
Quoted 19 lines
Quoted 8 lines
Quoted 8 lines

vfio_pci.c contains a nice function called "parse_hostaddr". You may
guess what it does. ;)

Interesting. Why? This looks strange to me:
I would expect the admin to bind a device to vfio
the way it's now bound to a stub.
The pass /dev/vfioXXX to qemu.

Quoted 8 lines
Quoted 5 lines

That's the "libvirt way". We surely also want the "qemu command line
way" for which this kind of service is needed.

Jan

Yes, I imagine the qemu command line passing in /dev/vfioXXX, the libvirt way will pass in an fd for above. No?

As far as I understand the API, there is no device file per assigned device.

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

Does it do pci_get_domain_bus_and_slot like kvm then? With all the warts like you have to remember to bind pci stub or you get two drivers for one device?
If true that's unfortunate IMHO.

I hope the answer to the above is no?

No, it does a probe for devices. We need the devaddr to compare against dev_name of the device to figure out which device the user is attempting to identify.

Quoted 17 lines
Quoted 17 lines
Quoted 10 lines
Quoted 5 lines

Also, this [domain:]bus:dev.fn format is more handy for the command line.

Jan

Then users could add udev rules that will name vfio devices like this. Another interesting option: /dev/vfio/eth0/vf1. That's better I think: no one really likes running lspci and guessing the address from there.

That's not at all how VFIO works. /dev/vfio/# represents a group, which may contain one or more devices. Even if libvirt passes a file descriptor for the group, qemu needs to know which device in the group to add to the guest, so parsing a device address is still necessary. Thanks,

Quoted 8 lines
Quoted 1 line

Alex

That's very unusual, and unfortunate. For example this means that I must update applications just because I move a card to another slot. UIO does not have this problem.
The fact that it's broken in kvm ATM seems to have made people think it's okay, but it really is a bug. We didn't fix it because vfio was supposed to be the solution.

Quoted 3 lines

I don't know what you're talking about here. Are you suggesting that needing to specify -device pci-assign,host=3.0 changing to host=4.0 when you move a card is broken?

Yes. Absolutely. Admin should be able to abstract it away without users knowing anything about it.

Quoted 7 lines
Quoted 3 lines

We don't have UUIDs on PCI devices, so who's to say that the device that was in slot 3 is the same device that's now in slot 4 and the user should still have access to it? That sounds even more problematic.

PF has a driver loaded so you can identify that, and identify the VF through it. Again this is really policy, it should be up to the admin how to name the device.

Do PFs have a UUID? Some devices support a serial number, but that's not related to being a PF vs VF. We need to support both PFs and VFs regardless of whether they have any kind of UUID.

Quoted 6 lines
Quoted 2 lines

This is a solved problem. udev has class-specific ways to get the device id and use it to find the name.

Usually via things discovered via device specific drivers, ex. MACs, disk UUIDs, etc. We don't have those in VFIO. Don't forget, VFIO is also device agnostic, VFIO-pci is just one possible driver backend.

Exactly. But udev can see that what it got is a VF anf query the PF.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

I think we're inventing a problem though.

You think persistent names in udev were a solution in search of a problem?

Of course not, but I've never heard any indication that this is a real problem for device assignment.

How is it different from any other workload?

Quoted 3 lines

If it is, like udev, why not solve it in
userspace? The kernel doesn't provide the persistence that udev exposes.

To solve it you need to find the PF. Admin does it easily but VFIO conceptually handles one VF at a time. So let the admin set the name.
And it is better using standard udev tools than some hacked interface specific to vfio.

Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
Quoted 8 lines
Quoted 8 lines
Quoted 1 line

How does UIO avoid such a problem.

Normally you use a misc device that you can name with udev.

Quoted 3 lines

UIO-pci
requires the user to use pci-sysfs for resource access, so it surely cares about the device address.

Quoted 6 lines
Quoted 2 lines

Only uio_pci_generic. Other uio devices let you drive the device.

If this is actually a problem, this is the first ever complaint I've heard about it. As above, I don't think we can assume the same access when a device is moved.

I thought need for sane naming and for sysfs interface was discussed multiple times. But maybe I'm misremembering.

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

There is sane naming and a sysfs interface...

It's not sane if the admin can't rename the device without breaking applications.

Again, udev provides that persistence, not the kernel.

So let it do its thing.

Quoted 51 lines
Quoted 37 lines
Quoted 37 lines
Quoted 25 lines
Quoted 25 lines
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines

I do realize you want to represent a group of devices somehow but can't this be solved without breaking naming devices with udev? For example, the device could be a file as well. You would then use the fd to identify the device within the group. And in a somewhat common case of a single device within the group, you can even make opening the group optional. Don't know if this fix I suggest makes sense at all but it's a real problem all the same.

Unfortunately, exposing individual devices just confuses the ownership model we require for groups. It would provide the illusion of being able to assign an individual device, without the reality of the grouping. Groups are owned either by _a_ user or by the kernel, they can't be split across multiple users (at least not with any guarantees of isolation). The current interface makes this clear. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

So do users pass in group=/dev/vfio/1,host=0:3.0 then?

No, vfio syntax is -device vfio-pci,host=0:3.0, just like pci-assign. Qemu will figure out which group that device belongs to and "do the right thing". If we add support for libvirt passing a groupfd, it will be mostly the same, just using scm_rights to get the groupfd instead of opening it directly. Thanks,

Quoted 3 lines
Quoted 1 line

Alex

Then how do you know which /dev/vfio/# to open?

This is all in the documentation patch... groups are exposed in sysfs in /sys/kernel/iommu_groups. Each group has a unique number which is exposed as a directory. Each group directory has a subdirectory called devices which links to all devices in the group. Each device within a group as an iommu_group link back to the group directory. The /dev/vfio/# entry matches the group number in sysfs. So it's all pretty easy. Thanks,

Quoted 4 lines
Quoted 1 line

Alex

So what's the problem to have devices in sysfs linked e.g. from /sys/class/vfio/ ?

They have to be bound to a VFIO driver, ex. vfio-pci. We have iommu groups in sysfs and can use that for this purpose. I did have a class for this before iommu_group were more integrated at the device level, now it just seems redundant.

Quoted 3 lines

udev could create the nodes e.g. in
/dev/vfio/devices/. User can then pass the device name and qemu can figure out the group from sysfs.

Quoted 8 lines

As previously noted, we don't, and I don't think it makes sense to expose individual devices in VFIO as the interface is fundamentally group based by necessity. Groups are just containers and they do support a name, which is exposed in sysfs when it's used, but groups are created by topology and don't follow the devices, so I don't think that's what you're looking for. It seems that if someone wants to create persistence for VFIO, they just need to identify something unique about a device in sysfs, then follow the device to the group.

So you are forced to code this all upfront in qemu.
And since you don't in practice, no percictence and no way to provide it.

Quoted 2 lines

Userpsace
is far more capable of providing this than the kernel.

It's the admin that knows. Not applications.

Quoted 3 lines

Thanks,

Alex

#87 lore raw

Re: [Qemu-devel] [PATCH 13/13] qdev-properties: Add pci-devaddr property

In reply to Jan Kiszka
Quoted 19 lines · Jan Kiszka
Quoted 7 lines · Michael S. Tsirkin
Quoted 5 lines · Jan Kiszka

Add a property to receive a fully qualified PCI device address.

Will be used by KVM device assignment.

Quoted 10 lines

I'd like to ponder this a bit more. What bothers me is that this mixes two things:
- addressing of qemu devices
Using full device addresses there is a legacy feature, users really should supply the parent bus and the bus local address.
- addressing devices on the linux host for assignment It so happens that the syntax matches
the legacy naming very closely,
but conceptually is completely unrelated

Quoted 1 line

We can keep code duplications, of course.

Just note that the parsing that we have is not even consistent. For example what does it mean not to supply an optional field, e.g. a function number, a domain number, etc? lspci and friends all treat any missing number as a wildcard:

$ lspci -s 0.1
15:00.1 FireWire (IEEE 1394): Ricoh Co Ltd R5C832 IEEE 1394 Controller (rev 04)
$ lspci -s .1
00:02.1 Display controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
00:1a.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 03)
00:1c.1 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 2 (rev 03)
00:1d.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 03)
15:00.1 FireWire (IEEE 1394): Ricoh Co Ltd R5C832 IEEE 1394 Controller (rev 04)

We don't, and the only reason for that is that it's been buggy for a long time.

Signature · 1 line
MST