In x86/ACPI world, since systemd v197, linux distros are using predictable network interface naming since systemd v197. Which on QEMU based VMs results into path based naming scheme, that names network interfaces based on PCI topology. With this one has to plug NIC in exacly the same bus/slot, which was used when disk image was first provisioned/configured or one risks to loose network configuration due to NIC being renamed to actually used topology. That also restricts freedom reshape PCI configuration of VM without need to reconfigure used guest image. systemd also offers "onboard" naming scheme which is preffered over PCI slot/topology one, provided that firmware implements: " PCI Firmware Specification 3.1 4.6.7. DSM for Naming a PCI or PCI Express Device Under Operating Systems " that allows to assign user defined index to PCI device, which systemd will use to name NIC. For example, using -device e1000,acpi-index=100 guest will rename NIC to 'eno100', where 'eno' is default prefix for "onboard" naming scheme. This doesn't reqiure any advance configuration on guest side. Hope is that 'acpi-index' will be easier to consume by mangment layer, compared to forcing specic PCI topology and/or having several disk image templates for different topologies and will help to simplify process of spawning VM from the same template without need to reconfigure guest network configuration. this patch adds, 'acpi-index'* property and wires up (abuses) unused pci hotplug registers to pass index value to AML code at runtime. Following patch will add corresponding _DSM code and wire it up to PCI devices described in ACPI. *) name comes from linux kernel terminology Signed-off-by: Igor Mammedov <imammedo@xxxxxxxxxx> --- CC: libvir-list@xxxxxxxxxx include/hw/acpi/pcihp.h | 7 ++++++- include/hw/pci/pci.h | 1 + hw/acpi/pci.c | 6 ++++++ hw/acpi/pcihp.c | 25 ++++++++++++++++++++++++- hw/i386/acpi-build.c | 10 ++++++++++ hw/pci/pci.c | 1 + 6 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index dfd375820f..72d1773ca1 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -46,6 +46,7 @@ typedef struct AcpiPciHpPciStatus { typedef struct AcpiPciHpState { AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS]; uint32_t hotplug_select; + uint32_t acpi_index; PCIBus *root; MemoryRegion io; bool legacy_piix; @@ -71,6 +72,8 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off); extern const VMStateDescription vmstate_acpi_pcihp_pci_status; +bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id); + #define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp) \ VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \ test_pcihp), \ @@ -78,6 +81,8 @@ extern const VMStateDescription vmstate_acpi_pcihp_pci_status; ACPI_PCIHP_MAX_HOTPLUG_BUS, \ test_pcihp, 1, \ vmstate_acpi_pcihp_pci_status, \ - AcpiPciHpPciStatus) + AcpiPciHpPciStatus), \ + VMSTATE_UINT32_TEST(pcihp.acpi_index, state, \ + vmstate_acpi_pcihp_use_acpi_index) #endif diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 259f9c992d..e592532558 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -357,6 +357,7 @@ struct PCIDevice { /* ID of standby device in net_failover pair */ char *failover_pair_id; + uint32_t acpi_index; }; void pci_register_bar(PCIDevice *pci_dev, int region_num, diff --git a/hw/acpi/pci.c b/hw/acpi/pci.c index 9510597a19..07d5101d83 100644 --- a/hw/acpi/pci.c +++ b/hw/acpi/pci.c @@ -27,6 +27,7 @@ #include "hw/acpi/aml-build.h" #include "hw/acpi/pci.h" #include "hw/pci/pcie_host.h" +#include "hw/acpi/pcihp.h" void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) { @@ -59,3 +60,8 @@ void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) "MCFG", table_data->len - mcfg_start, 1, NULL, NULL); } +bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id) +{ + AcpiPciHpState *s = opaque; + return s->acpi_index; +} diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 9dc4d3e2db..9634567e3a 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -347,7 +347,8 @@ 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 */ + val = s->acpi_index; + s->acpi_index = 0; trace_acpi_pci_features_read(val); break; case PCI_RMV_BASE: @@ -367,8 +368,30 @@ 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_UP_BASE: + 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; + } + } + break; case PCI_EJ_BASE: if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) { break; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index f18b71dea9..27d2958e25 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1132,6 +1132,16 @@ static void build_piix4_pci_hotplug(Aml *table) aml_append(method, aml_return(aml_int(0))); aml_append(scope, method); + method = aml_method("AIDX", 2, AML_NOTSERIALIZED); + aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF)); + aml_append(method, aml_store(aml_arg(0), aml_name("BNUM"))); + aml_append(method, + aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("PCIU"))); + aml_append(method, aml_store(aml_name("B0EJ"), aml_local(0))); + aml_append(method, aml_release(aml_name("BLCK"))); + aml_append(method, aml_return(aml_local(0))); + aml_append(scope, method); + aml_append(table, scope); } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index d4349ea577..617f48ff3b 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -76,6 +76,7 @@ static Property pci_props[] = { QEMU_PCIE_EXTCAP_INIT_BITNR, true), DEFINE_PROP_STRING("failover_pair_id", PCIDevice, failover_pair_id), + DEFINE_PROP_UINT32("acpi-index", PCIDevice, acpi_index, -1), DEFINE_PROP_END_OF_LIST() }; -- 2.27.0