mirror of https://github.com/xemu-project/xemu.git
pci: acpi: ensure that acpi-index is unique
it helps to avoid device naming conflicts when guest OS is configured to use acpi-index for naming. Spec ialso says so: PCI Firmware Specification Revision 3.2 4.6.7. _DSM for Naming a PCI or PCI Express Device Under Operating Systems " Instance number must be unique under \_SB scope. This instance number does not have to be sequential in a given system configuration. " Signed-off-by: Igor Mammedov <imammedo@redhat.com> Message-Id: <20210315180102.3008391-4-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
b32bd763a1
commit
4fd7da4c03
|
@ -52,6 +52,21 @@ typedef struct AcpiPciHpFind {
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
} AcpiPciHpFind;
|
} AcpiPciHpFind;
|
||||||
|
|
||||||
|
static gint g_cmp_uint32(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||||
|
{
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSequence *pci_acpi_index_list(void)
|
||||||
|
{
|
||||||
|
static GSequence *used_acpi_index_list;
|
||||||
|
|
||||||
|
if (!used_acpi_index_list) {
|
||||||
|
used_acpi_index_list = g_sequence_new(NULL);
|
||||||
|
}
|
||||||
|
return used_acpi_index_list;
|
||||||
|
}
|
||||||
|
|
||||||
static int acpi_pcihp_get_bsel(PCIBus *bus)
|
static int acpi_pcihp_get_bsel(PCIBus *bus)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
@ -277,6 +292,23 @@ void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||||
ONBOARD_INDEX_MAX);
|
ONBOARD_INDEX_MAX);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make sure that acpi-index is unique across all present PCI devices
|
||||||
|
*/
|
||||||
|
if (pdev->acpi_index) {
|
||||||
|
GSequence *used_indexes = pci_acpi_index_list();
|
||||||
|
|
||||||
|
if (g_sequence_lookup(used_indexes, GINT_TO_POINTER(pdev->acpi_index),
|
||||||
|
g_cmp_uint32, NULL)) {
|
||||||
|
error_setg(errp, "a PCI device with acpi-index = %" PRIu32
|
||||||
|
" already exist", pdev->acpi_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_sequence_insert_sorted(used_indexes,
|
||||||
|
GINT_TO_POINTER(pdev->acpi_index),
|
||||||
|
g_cmp_uint32, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
||||||
|
@ -315,8 +347,22 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
||||||
void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
PCIDevice *pdev = PCI_DEVICE(dev);
|
||||||
|
|
||||||
trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
|
trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
|
||||||
acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
|
acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clean up acpi-index so it could reused by another device
|
||||||
|
*/
|
||||||
|
if (pdev->acpi_index) {
|
||||||
|
GSequence *used_indexes = pci_acpi_index_list();
|
||||||
|
|
||||||
|
g_sequence_remove(g_sequence_lookup(used_indexes,
|
||||||
|
GINT_TO_POINTER(pdev->acpi_index),
|
||||||
|
g_cmp_uint32, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
qdev_unrealize(dev);
|
qdev_unrealize(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue