diff mbox series

[RFC,3/5] pci: introduce apci-index property for PCI device

Message ID 20201222233934.451578-4-imammedo@redhat.com
State New
Headers show
Series pc: support user provided NIC naming/indexing | expand

Commit Message

Igor Mammedov Dec. 22, 2020, 11:39 p.m. UTC
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@redhat.com>
---
CC: libvir-list@redhat.com

 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 mbox series

Patch

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()
 };