diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2021-03-23 10:50:44 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2021-03-23 10:50:44 +0000 |
| commit | 97414988490de91673c51e6aa88a9f507e6a1edc (patch) | |
| tree | e71a42924f248c5e8dcf05a9e39422ff5666613f /hw/acpi/pcihp.c | |
| parent | 5ca634afcf83215a9a54ca6e66032325b5ffb5f6 (diff) | |
| parent | d07b22863b8e0981bdc9384a787a703f1fd4ba42 (diff) | |
| download | focaccia-qemu-97414988490de91673c51e6aa88a9f507e6a1edc.tar.gz focaccia-qemu-97414988490de91673c51e6aa88a9f507e6a1edc.zip | |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,virtio,pci: fixes, features Fixes all over the place. ACPI index support. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Mon 22 Mar 2021 22:58:45 GMT # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: acpi: Move setters/getters of oem fields to X86MachineState acpi: Set proper maximum size for "etc/acpi/rsdp" blob acpi: Move maximum size logic into acpi_add_rom_blob() microvm: Don't open-code "etc/table-loader" acpi: Set proper maximum size for "etc/table-loader" blob tests: acpi: update expected blobs pci: acpi: add _DSM method to PCI devices acpi: add aml_to_decimalstring() and aml_call6() helpers pci: acpi: ensure that acpi-index is unique pci: introduce acpi-index property for PCI device tests: acpi: temporary whitelist DSDT changes virtio-pmem: fix virtio_pmem_resp assign problem vhost-user: Monitor slave channel in vhost_user_read() vhost-user: Introduce nested event loop in vhost_user_read() vhost-user: Convert slave channel to QIOChannelSocket vhost-user: Factor out duplicated slave_fd teardown code vhost-user: Fix double-close on slave_read() error path vhost-user: Drop misleading EAGAIN checks in slave_read() virtio: Fix virtio_mmio_read()/virtio_mmio_write() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/acpi/pcihp.c')
| -rw-r--r-- | hw/acpi/pcihp.c | 104 |
1 files changed, 102 insertions, 2 deletions
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 9dc4d3e2db..f4cb3c979d 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -39,18 +39,34 @@ #include "trace.h" #define ACPI_PCIHP_ADDR 0xae00 -#define ACPI_PCIHP_SIZE 0x0014 +#define ACPI_PCIHP_SIZE 0x0018 #define PCI_UP_BASE 0x0000 #define PCI_DOWN_BASE 0x0004 #define PCI_EJ_BASE 0x0008 #define PCI_RMV_BASE 0x000c #define PCI_SEL_BASE 0x0010 +#define PCI_AIDX_BASE 0x0014 typedef struct AcpiPciHpFind { int bsel; PCIBus *bus; } 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) { Error *local_err = NULL; @@ -251,9 +267,13 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off) acpi_pcihp_update(s); } +#define ONBOARD_INDEX_MAX (16 * 1024 - 1) + void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + PCIDevice *pdev = PCI_DEVICE(dev); + /* Only hotplugged devices need the hotplug capability. */ if (dev->hotplugged && acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))) < 0) { @@ -261,6 +281,34 @@ void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev, ACPI_PCIHP_PROP_BSEL "' set"); return; } + + /* + * capped by systemd (see: udev-builtin-net_id.c) + * as it's the only known user honor it to avoid users + * misconfigure QEMU and then wonder why acpi-index doesn't work + */ + if (pdev->acpi_index > ONBOARD_INDEX_MAX) { + error_setg(errp, "acpi-index should be less or equal to %u", + ONBOARD_INDEX_MAX); + 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, @@ -299,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, DeviceState *dev, Error **errp) { + PCIDevice *pdev = PCI_DEVICE(dev); + trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn), 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); } @@ -347,7 +409,6 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) trace_acpi_pci_down_read(val); break; case PCI_EJ_BASE: - /* No feature defined yet */ trace_acpi_pci_features_read(val); break; case PCI_RMV_BASE: @@ -357,6 +418,12 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) case PCI_SEL_BASE: val = s->hotplug_select; trace_acpi_pci_sel_read(val); + break; + case PCI_AIDX_BASE: + val = s->acpi_index; + s->acpi_index = 0; + trace_acpi_pci_acpi_index_read(val); + break; default: break; } @@ -367,8 +434,35 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) static void pci_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { + int slot; + PCIBus *bus; + BusChild *kid, *next; AcpiPciHpState *s = opaque; + + s->acpi_index = 0; switch (addr) { + case PCI_AIDX_BASE: + /* + * fetch acpi-index for specified slot so that follow up read from + * PCI_AIDX_BASE can return it to guest + */ + slot = ctz32(data); + + if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) { + break; + } + + bus = acpi_pcihp_find_hotplug_bus(s, s->hotplug_select); + QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) { + Object *o = OBJECT(kid->child); + PCIDevice *dev = PCI_DEVICE(o); + if (PCI_SLOT(dev->devfn) == slot) { + s->acpi_index = object_property_get_uint(o, "acpi-index", NULL); + break; + } + } + trace_acpi_pci_acpi_index_write(s->hotplug_select, slot, s->acpi_index); + break; case PCI_EJ_BASE: if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) { break; @@ -413,6 +507,12 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus, OBJ_PROP_FLAG_READ); } +bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id) +{ + AcpiPciHpState *s = opaque; + return s->acpi_index; +} + const VMStateDescription vmstate_acpi_pcihp_pci_status = { .name = "acpi_pcihp_pci_status", .version_id = 1, |