diff mbox series

[v1,2/7] pcihp: overwrite hotplug handler recursively from the start

Message ID 20181024101930.20674-3-david@redhat.com
State New
Headers show
Series pci: hotplug handler reworks | expand

Commit Message

David Hildenbrand Oct. 24, 2018, 10:19 a.m. UTC
For now, the hotplug handler is not called for devices that are
being cold plugged. The hotplug handler is setup when the machine
initialization is fully done. Only bridges that were cold plugged are
considered.

Set the hotplug handler for the root piix bus directly when realizing.
Overwrite the hotplug handler of bridges when hotplugging/coldplugging
them.

This will now make sure that the ACPI PCI hotplug handler is also called
for cold-plugged devices (also on bridges) and for bridges that were
hotplugged.

When trying to hotplug a device to a hotplugged bridge, we now correctly
get the error message
 "Unsupported bus. Bus doesn't have property 'acpi-pcihp-bsel' set"
Insted of going via the standard PCI hotplug handler.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 hw/acpi/pcihp.c | 10 ++++++++++
 hw/acpi/piix4.c | 16 +---------------
 2 files changed, 11 insertions(+), 15 deletions(-)

Comments

Igor Mammedov Nov. 1, 2018, 2:10 p.m. UTC | #1
On Wed, 24 Oct 2018 12:19:25 +0200
David Hildenbrand <david@redhat.com> wrote:

> For now, the hotplug handler is not called for devices that are
> being cold plugged. The hotplug handler is setup when the machine
> initialization is fully done. Only bridges that were cold plugged are
> considered.
> 
> Set the hotplug handler for the root piix bus directly when realizing.
> Overwrite the hotplug handler of bridges when hotplugging/coldplugging
> them.
> 
> This will now make sure that the ACPI PCI hotplug handler is also called
> for cold-plugged devices (also on bridges) and for bridges that were
> hotplugged.
> 
> When trying to hotplug a device to a hotplugged bridge, we now correctly
> get the error message
>  "Unsupported bus. Bus doesn't have property 'acpi-pcihp-bsel' set"
> Insted of going via the standard PCI hotplug handler.
Erroring out is probably not ok, since it can break existing setups
where SHPC hotplugging to hotplugged bridge was working just fine before.

Marcel/Michael what's your take on this change in behaviour?
CCing libvirt in case they are doing this stuff


> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  hw/acpi/pcihp.c | 10 ++++++++++
>  hw/acpi/piix4.c | 16 +---------------
>  2 files changed, 11 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
> index 5e7cef173c..647b5e8d82 100644
> --- a/hw/acpi/pcihp.c
> +++ b/hw/acpi/pcihp.c
> @@ -30,6 +30,7 @@
>  #include "hw/hw.h"
>  #include "hw/i386/pc.h"
>  #include "hw/pci/pci.h"
> +#include "hw/pci/pci_bridge.h"
>  #include "hw/acpi/acpi.h"
>  #include "sysemu/sysemu.h"
>  #include "exec/address-spaces.h"
> @@ -236,6 +237,15 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
>      int slot = PCI_SLOT(pdev->devfn);
>      int bsel;
>  
> +    if (!s->legacy_piix && object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
> +        PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
> +
> +        /* Overwrite the default hotplug handler with the ACPI PCI one. */
> +        qbus_set_hotplug_handler(BUS(sec), DEVICE(hotplug_dev), &error_abort);
> +        /* No need to do it recursively */
> +        assert(QLIST_EMPTY(&sec->child));
> +    }
> +
>      /* Don't send event when device is enabled during qemu machine creation:
>       * it is present on boot, no hotplug event is necessary. We do send an
>       * event when the device is disabled later. */
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index 167afe2cea..e611778daf 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -446,15 +446,6 @@ static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
>      }
>  }
>  
> -static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
> -{
> -    PIIX4PMState *s = opaque;
> -
> -    /* pci_bus cannot outlive PIIX4PMState, because /machine keeps it alive
> -     * and it's not hot-unpluggable */
> -    qbus_set_hotplug_handler(BUS(pci_bus), DEVICE(s), &error_abort);
> -}
> -
>  static void piix4_pm_machine_ready(Notifier *n, void *opaque)
>  {
>      PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
> @@ -468,12 +459,6 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
>      pci_conf[0x63] = 0x60;
>      pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
>          (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
> -
> -    if (s->use_acpi_pci_hotplug) {
> -        pci_for_each_bus(pci_get_bus(d), piix4_update_bus_hotplug, s);
> -    } else {
> -        piix4_update_bus_hotplug(pci_get_bus(d), s);
> -    }
>  }
>  
>  static void piix4_pm_add_propeties(PIIX4PMState *s)
> @@ -547,6 +532,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)
>  
>      piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
>                                     pci_get_bus(dev), s);
> +    qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), DEVICE(s), &error_abort);
>  
>      piix4_pm_add_propeties(s);
>  }
David Hildenbrand Nov. 2, 2018, 11:43 a.m. UTC | #2
On 01.11.18 15:10, Igor Mammedov wrote:
> On Wed, 24 Oct 2018 12:19:25 +0200
> David Hildenbrand <david@redhat.com> wrote:
> 
>> For now, the hotplug handler is not called for devices that are
>> being cold plugged. The hotplug handler is setup when the machine
>> initialization is fully done. Only bridges that were cold plugged are
>> considered.
>>
>> Set the hotplug handler for the root piix bus directly when realizing.
>> Overwrite the hotplug handler of bridges when hotplugging/coldplugging
>> them.
>>
>> This will now make sure that the ACPI PCI hotplug handler is also called
>> for cold-plugged devices (also on bridges) and for bridges that were
>> hotplugged.
>>
>> When trying to hotplug a device to a hotplugged bridge, we now correctly
>> get the error message
>>  "Unsupported bus. Bus doesn't have property 'acpi-pcihp-bsel' set"
>> Insted of going via the standard PCI hotplug handler.
> Erroring out is probably not ok, since it can break existing setups
> where SHPC hotplugging to hotplugged bridge was working just fine before.

The question is if it actually was supposed (and eventually did) work.

If this was the expected behavior (mixing hotplug types), then the
necessary change to this patch would boil down to checking if the bridge
it hot or coldplugged.

> 
> Marcel/Michael what's your take on this change in behaviour?
> CCing libvirt in case they are doing this stuff
> 

Indeed, it would be nice to know if this was actually supposed to work
like this (coldplugged bridges using ACPI hotplug and hotplugged bridges
using SHPC hotplug).
Igor Mammedov Nov. 2, 2018, 1 p.m. UTC | #3
On Fri, 2 Nov 2018 12:43:10 +0100
David Hildenbrand <david@redhat.com> wrote:

> On 01.11.18 15:10, Igor Mammedov wrote:
> > On Wed, 24 Oct 2018 12:19:25 +0200
> > David Hildenbrand <david@redhat.com> wrote:
> >   
> >> For now, the hotplug handler is not called for devices that are
> >> being cold plugged. The hotplug handler is setup when the machine
> >> initialization is fully done. Only bridges that were cold plugged are
> >> considered.
> >>
> >> Set the hotplug handler for the root piix bus directly when realizing.
> >> Overwrite the hotplug handler of bridges when hotplugging/coldplugging
> >> them.
> >>
> >> This will now make sure that the ACPI PCI hotplug handler is also called
> >> for cold-plugged devices (also on bridges) and for bridges that were
> >> hotplugged.
> >>
> >> When trying to hotplug a device to a hotplugged bridge, we now correctly
> >> get the error message
> >>  "Unsupported bus. Bus doesn't have property 'acpi-pcihp-bsel' set"
> >> Insted of going via the standard PCI hotplug handler.  
> > Erroring out is probably not ok, since it can break existing setups
> > where SHPC hotplugging to hotplugged bridge was working just fine before.  
> 
> The question is if it actually was supposed (and eventually did) work.
I think it works now, it's QEMU 'ACPI hotplug hack' (which exists for
the sake of Windows) limitation. We weren't able to dynamically add
ACPI description for hotplugged bridge, so it was using native hotplug.
Now theoretically we can load tables dynamically but that, would add
maintenance nightmare (versioned tables) and would be harder to debug.
I'd rather not go that direction and keep current limited version,
suggesting users to use native hotplug if guest is capable.

> If this was the expected behavior (mixing hotplug types), then the
> necessary change to this patch would boil down to checking if the bridge
> it hot or coldplugged.
> 
> > 
> > Marcel/Michael what's your take on this change in behaviour?
> > CCing libvirt in case they are doing this stuff
> >   
> 
> Indeed, it would be nice to know if this was actually supposed to work
> like this (coldplugged bridges using ACPI hotplug and hotplugged bridges
> using SHPC hotplug).
> 
>
David Hildenbrand Nov. 2, 2018, 1:34 p.m. UTC | #4
On 02.11.18 14:00, Igor Mammedov wrote:
> On Fri, 2 Nov 2018 12:43:10 +0100
> David Hildenbrand <david@redhat.com> wrote:
> 
>> On 01.11.18 15:10, Igor Mammedov wrote:
>>> On Wed, 24 Oct 2018 12:19:25 +0200
>>> David Hildenbrand <david@redhat.com> wrote:
>>>   
>>>> For now, the hotplug handler is not called for devices that are
>>>> being cold plugged. The hotplug handler is setup when the machine
>>>> initialization is fully done. Only bridges that were cold plugged are
>>>> considered.
>>>>
>>>> Set the hotplug handler for the root piix bus directly when realizing.
>>>> Overwrite the hotplug handler of bridges when hotplugging/coldplugging
>>>> them.
>>>>
>>>> This will now make sure that the ACPI PCI hotplug handler is also called
>>>> for cold-plugged devices (also on bridges) and for bridges that were
>>>> hotplugged.
>>>>
>>>> When trying to hotplug a device to a hotplugged bridge, we now correctly
>>>> get the error message
>>>>  "Unsupported bus. Bus doesn't have property 'acpi-pcihp-bsel' set"
>>>> Insted of going via the standard PCI hotplug handler.  
>>> Erroring out is probably not ok, since it can break existing setups
>>> where SHPC hotplugging to hotplugged bridge was working just fine before.  
>>
>> The question is if it actually was supposed (and eventually did) work.
> I think it works now, it's QEMU 'ACPI hotplug hack' (which exists for
> the sake of Windows) limitation. We weren't able to dynamically add
> ACPI description for hotplugged bridge, so it was using native hotplug.
> Now theoretically we can load tables dynamically but that, would add
> maintenance nightmare (versioned tables) and would be harder to debug.
> I'd rather not go that direction and keep current limited version,
> suggesting users to use native hotplug if guest is capable.

Alright I'll keep current behavior (checking if the bridge is hotplugged
or coldplugged). Thanks!
Michael S. Tsirkin Nov. 2, 2018, 4:28 p.m. UTC | #5
On Fri, Nov 02, 2018 at 02:00:32PM +0100, Igor Mammedov wrote:
> On Fri, 2 Nov 2018 12:43:10 +0100
> David Hildenbrand <david@redhat.com> wrote:
> 
> > On 01.11.18 15:10, Igor Mammedov wrote:
> > > On Wed, 24 Oct 2018 12:19:25 +0200
> > > David Hildenbrand <david@redhat.com> wrote:
> > >   
> > >> For now, the hotplug handler is not called for devices that are
> > >> being cold plugged. The hotplug handler is setup when the machine
> > >> initialization is fully done. Only bridges that were cold plugged are
> > >> considered.
> > >>
> > >> Set the hotplug handler for the root piix bus directly when realizing.
> > >> Overwrite the hotplug handler of bridges when hotplugging/coldplugging
> > >> them.
> > >>
> > >> This will now make sure that the ACPI PCI hotplug handler is also called
> > >> for cold-plugged devices (also on bridges) and for bridges that were
> > >> hotplugged.
> > >>
> > >> When trying to hotplug a device to a hotplugged bridge, we now correctly
> > >> get the error message
> > >>  "Unsupported bus. Bus doesn't have property 'acpi-pcihp-bsel' set"
> > >> Insted of going via the standard PCI hotplug handler.  
> > > Erroring out is probably not ok, since it can break existing setups
> > > where SHPC hotplugging to hotplugged bridge was working just fine before.  
> > 
> > The question is if it actually was supposed (and eventually did) work.
> I think it works now, it's QEMU 'ACPI hotplug hack' (which exists for
> the sake of Windows) limitation. We weren't able to dynamically add
> ACPI description for hotplugged bridge, so it was using native hotplug.
> Now theoretically we can load tables dynamically but that, would add
> maintenance nightmare (versioned tables) and would be harder to debug.
> I'd rather not go that direction and keep current limited version,
> suggesting users to use native hotplug if guest is capable.

Well a bunch of tables need to be dynamic, and generating them from ACPI
isn't a significant step up from generating them in the BIOS which did
create huge headaches, for many reasons but in particular because we
need to add custom interfaces for every little thing we are adding.
By comparison dynamic loading is a single interface and we can
ship any AML code we want across it.

So I'm working on a limited form of dynamic loading with versioning and
I don't necessarily agree it has to be a nightmare, but yes it does need
to be limited very carefully. Implementing bridge hotplug there
isn't in scope for me at this point.

> > If this was the expected behavior (mixing hotplug types), then the
> > necessary change to this patch would boil down to checking if the bridge
> > it hot or coldplugged.
> > 
> > > 
> > > Marcel/Michael what's your take on this change in behaviour?
> > > CCing libvirt in case they are doing this stuff
> > >   
> > 
> > Indeed, it would be nice to know if this was actually supposed to work
> > like this (coldplugged bridges using ACPI hotplug and hotplugged bridges
> > using SHPC hotplug).
> > 
> >
diff mbox series

Patch

diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 5e7cef173c..647b5e8d82 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -30,6 +30,7 @@ 
 #include "hw/hw.h"
 #include "hw/i386/pc.h"
 #include "hw/pci/pci.h"
+#include "hw/pci/pci_bridge.h"
 #include "hw/acpi/acpi.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
@@ -236,6 +237,15 @@  void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
     int slot = PCI_SLOT(pdev->devfn);
     int bsel;
 
+    if (!s->legacy_piix && object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
+        PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
+
+        /* Overwrite the default hotplug handler with the ACPI PCI one. */
+        qbus_set_hotplug_handler(BUS(sec), DEVICE(hotplug_dev), &error_abort);
+        /* No need to do it recursively */
+        assert(QLIST_EMPTY(&sec->child));
+    }
+
     /* Don't send event when device is enabled during qemu machine creation:
      * it is present on boot, no hotplug event is necessary. We do send an
      * event when the device is disabled later. */
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 167afe2cea..e611778daf 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -446,15 +446,6 @@  static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
     }
 }
 
-static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
-{
-    PIIX4PMState *s = opaque;
-
-    /* pci_bus cannot outlive PIIX4PMState, because /machine keeps it alive
-     * and it's not hot-unpluggable */
-    qbus_set_hotplug_handler(BUS(pci_bus), DEVICE(s), &error_abort);
-}
-
 static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
@@ -468,12 +459,6 @@  static void piix4_pm_machine_ready(Notifier *n, void *opaque)
     pci_conf[0x63] = 0x60;
     pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) |
         (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
-
-    if (s->use_acpi_pci_hotplug) {
-        pci_for_each_bus(pci_get_bus(d), piix4_update_bus_hotplug, s);
-    } else {
-        piix4_update_bus_hotplug(pci_get_bus(d), s);
-    }
 }
 
 static void piix4_pm_add_propeties(PIIX4PMState *s)
@@ -547,6 +532,7 @@  static void piix4_pm_realize(PCIDevice *dev, Error **errp)
 
     piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
                                    pci_get_bus(dev), s);
+    qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), DEVICE(s), &error_abort);
 
     piix4_pm_add_propeties(s);
 }