6d3351
From 0b739987779a9f197d558f9c3b31d557a564bb6d Mon Sep 17 00:00:00 2001
6d3351
Message-Id: <0b739987779a9f197d558f9c3b31d557a564bb6d@dist-git>
6d3351
From: Andrea Bolognani <abologna@redhat.com>
6d3351
Date: Tue, 18 Jul 2017 12:10:05 +0200
6d3351
Subject: [PATCH] conf: Introduce isolation groups
6d3351
6d3351
Isolation groups will eventually allow us to make sure certain
6d3351
devices, eg. PCI hostdevs, are assigned to guest PCI buses in
6d3351
a way that guarantees improved isolation, error detection and
6d3351
recovery for machine types and hypervisors that support it,
6d3351
eg. pSeries guest on QEMU.
6d3351
6d3351
This patch merely defines storage for the new information
6d3351
we're going to need later on and makes sure it is passed from
6d3351
the hypervisor driver (QEMU / bhyve) down to the generic PCI
6d3351
address allocation code.
6d3351
6d3351
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
6d3351
Reviewed-by: Laine Stump <laine@laine.org>
6d3351
(cherry picked from commit b8b6abbcd431d02ac106ee729204552d80762aae)
6d3351
6d3351
Conflicts:
6d3351
6d3351
  * src/conf/device_conf.h:
6d3351
6d3351
    caused by 54fa1b44afc8bfe4a36c7c4e3b2fe1fafde0506c, where
6d3351
    virDomainDeviceInfo::loadparm is introduced, not being
6d3351
    present in the tree;
6d3351
6d3351
  * src/conf/domain_conf.c:
6d3351
6d3351
    caused mostly by the absence of commit
6d3351
    0c53382d820aac4767895a727c01de23397a6aaa and hence the
6d3351
    virDomainSkipBackcompatConsole() function, but
6d3351
    54fa1b44afc8bfe4a36c7c4e3b2fe1fafde0506c mentioned above
6d3351
    also plays a role.
6d3351
6d3351
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1280542
6d3351
6d3351
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
---
6d3351
 src/bhyve/bhyve_device.c       |  4 ++--
6d3351
 src/conf/device_conf.h         | 10 ++++++++++
6d3351
 src/conf/domain_addr.c         | 17 ++++++++++++-----
6d3351
 src/conf/domain_addr.h         |  9 ++++++++-
6d3351
 src/conf/domain_conf.c         |  2 ++
6d3351
 src/qemu/qemu_domain_address.c | 35 ++++++++++++++++++-----------------
6d3351
 6 files changed, 52 insertions(+), 25 deletions(-)
6d3351
6d3351
diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c
6d3351
index fdfd512e10..03aa6c93bd 100644
6d3351
--- a/src/bhyve/bhyve_device.c
6d3351
+++ b/src/bhyve/bhyve_device.c
6d3351
@@ -57,7 +57,7 @@ bhyveCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
6d3351
     }
6d3351
 
6d3351
     if (virDomainPCIAddressReserveAddr(addrs, addr,
6d3351
-                                       VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) {
6d3351
+                                       VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) {
6d3351
         goto cleanup;
6d3351
     }
6d3351
 
6d3351
@@ -100,7 +100,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def,
6d3351
     lpc_addr.slot = 0x1;
6d3351
 
6d3351
     if (virDomainPCIAddressReserveAddr(addrs, &lpc_addr,
6d3351
-                                       VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) {
6d3351
+                                       VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) {
6d3351
         goto error;
6d3351
     }
6d3351
 
6d3351
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
6d3351
index a20de853f8..6436a8cf3f 100644
6d3351
--- a/src/conf/device_conf.h
6d3351
+++ b/src/conf/device_conf.h
6d3351
@@ -167,6 +167,16 @@ struct _virDomainDeviceInfo {
6d3351
      * assignment, never saved and never reported.
6d3351
      */
6d3351
     int pciConnectFlags; /* enum virDomainPCIConnectFlags */
6d3351
+
6d3351
+    /* PCI devices will only be automatically placed on a PCI bus
6d3351
+     * that shares the same isolation group */
6d3351
+    unsigned int isolationGroup;
6d3351
+
6d3351
+    /* Usually, PCI buses will take on the same isolation group
6d3351
+     * as the first device that is plugged into them, but in some
6d3351
+     * cases we might want to prevent that from happening by
6d3351
+     * locking the isolation group */
6d3351
+    bool isolationGroupLocked;
6d3351
 };
6d3351
 
6d3351
 
6d3351
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
6d3351
index 8990372ae0..a067493136 100644
6d3351
--- a/src/conf/domain_addr.c
6d3351
+++ b/src/conf/domain_addr.c
6d3351
@@ -548,6 +548,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
6d3351
 virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs,
6d3351
                                        virPCIDeviceAddressPtr addr,
6d3351
                                        virDomainPCIConnectFlags flags,
6d3351
+                                       unsigned int isolationGroup ATTRIBUTE_UNUSED,
6d3351
                                        bool fromConfig)
6d3351
 {
6d3351
     int ret = -1;
6d3351
@@ -600,9 +601,11 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs,
6d3351
 int
6d3351
 virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
6d3351
                                virPCIDeviceAddressPtr addr,
6d3351
-                               virDomainPCIConnectFlags flags)
6d3351
+                               virDomainPCIConnectFlags flags,
6d3351
+                               unsigned int isolationGroup)
6d3351
 {
6d3351
-    return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags, true);
6d3351
+    return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags,
6d3351
+                                                  isolationGroup, true);
6d3351
 }
6d3351
 
6d3351
 int
6d3351
@@ -638,7 +641,8 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
6d3351
             goto cleanup;
6d3351
 
6d3351
         ret = virDomainPCIAddressReserveAddrInternal(addrs, &dev->addr.pci,
6d3351
-                                                     flags, true);
6d3351
+                                                     flags, dev->isolationGroup,
6d3351
+                                                     true);
6d3351
     } else {
6d3351
         ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1);
6d3351
     }
6d3351
@@ -759,6 +763,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
6d3351
 virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs,
6d3351
                                virPCIDeviceAddressPtr next_addr,
6d3351
                                virDomainPCIConnectFlags flags,
6d3351
+                               unsigned int isolationGroup ATTRIBUTE_UNUSED,
6d3351
                                int function)
6d3351
 {
6d3351
     virPCIDeviceAddress a = { 0 };
6d3351
@@ -839,10 +844,12 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
6d3351
 {
6d3351
     virPCIDeviceAddress addr;
6d3351
 
6d3351
-    if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, function) < 0)
6d3351
+    if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags,
6d3351
+                                       dev->isolationGroup, function) < 0)
6d3351
         return -1;
6d3351
 
6d3351
-    if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, false) < 0)
6d3351
+    if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags,
6d3351
+                                               dev->isolationGroup, false) < 0)
6d3351
         return -1;
6d3351
 
6d3351
     if (!addrs->dryRun) {
6d3351
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
6d3351
index 49f30332f0..01dbc5114f 100644
6d3351
--- a/src/conf/domain_addr.h
6d3351
+++ b/src/conf/domain_addr.h
6d3351
@@ -100,6 +100,12 @@ typedef struct {
6d3351
      * bit is set, that function is in use by a device.
6d3351
      */
6d3351
     virDomainPCIAddressSlot slot[VIR_PCI_ADDRESS_SLOT_LAST + 1];
6d3351
+
6d3351
+    /* See virDomainDeviceInfo::isolationGroup */
6d3351
+    unsigned int isolationGroup;
6d3351
+
6d3351
+    /* See virDomainDeviceInfo::isolationGroupLocked */
6d3351
+    bool isolationGroupLocked;
6d3351
 } virDomainPCIAddressBus;
6d3351
 typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
6d3351
 
6d3351
@@ -155,7 +161,8 @@ int virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
6d3351
 
6d3351
 int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
6d3351
                                    virPCIDeviceAddressPtr addr,
6d3351
-                                   virDomainPCIConnectFlags flags)
6d3351
+                                   virDomainPCIConnectFlags flags,
6d3351
+                                   unsigned int isolationGroup)
6d3351
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
6d3351
 
6d3351
 int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
6d3351
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
6d3351
index f28f6aff63..5941a3a4c4 100644
6d3351
--- a/src/conf/domain_conf.c
6d3351
+++ b/src/conf/domain_conf.c
6d3351
@@ -3608,6 +3608,8 @@ void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info)
6d3351
     memset(&info->addr, 0, sizeof(info->addr));
6d3351
     info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
6d3351
     VIR_FREE(info->romfile);
6d3351
+    info->isolationGroup = 0;
6d3351
+    info->isolationGroupLocked = false;
6d3351
 }
6d3351
 
6d3351
 
6d3351
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
6d3351
index d19ffea7c9..02e214b8dd 100644
6d3351
--- a/src/qemu/qemu_domain_address.c
6d3351
+++ b/src/qemu/qemu_domain_address.c
6d3351
@@ -1032,7 +1032,8 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
6d3351
     }
6d3351
 
6d3351
     if (virDomainPCIAddressReserveAddr(addrs, addr,
6d3351
-                                       info->pciConnectFlags) < 0) {
6d3351
+                                       info->pciConnectFlags,
6d3351
+                                       info->isolationGroup) < 0) {
6d3351
         goto cleanup;
6d3351
     }
6d3351
 
6d3351
@@ -1077,6 +1078,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
6d3351
         if (virDomainPCIAddressBusSetModel(&addrs->buses[idx], cont->model) < 0)
6d3351
             goto error;
6d3351
 
6d3351
+        /* Forward the information about isolation groups */
6d3351
+        addrs->buses[idx].isolationGroup = cont->info.isolationGroup;
6d3351
+        addrs->buses[idx].isolationGroupLocked = cont->info.isolationGroupLocked;
6d3351
+
6d3351
         if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
6d3351
             hasPCIeRoot = true;
6d3351
     }
6d3351
@@ -1193,7 +1198,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
6d3351
     if (addrs->nbuses) {
6d3351
         memset(&tmp_addr, 0, sizeof(tmp_addr));
6d3351
         tmp_addr.slot = 1;
6d3351
-        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
6d3351
+        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
             goto cleanup;
6d3351
     }
6d3351
 
6d3351
@@ -1228,7 +1233,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
6d3351
                     goto cleanup;
6d3351
                 }
6d3351
             } else {
6d3351
-                if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
6d3351
+                if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
                     goto cleanup;
6d3351
                 primaryVideo->info.addr.pci = tmp_addr;
6d3351
                 primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6d3351
@@ -1253,7 +1258,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
6d3351
             VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video"
6d3351
                       " device will not be possible without manual"
6d3351
                       " intervention");
6d3351
-        } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) {
6d3351
+        } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) {
6d3351
             goto cleanup;
6d3351
         }
6d3351
     }
6d3351
@@ -1329,10 +1334,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
6d3351
                         assign = true;
6d3351
                 }
6d3351
                 if (assign) {
6d3351
-                    if (virDomainPCIAddressReserveAddr(addrs,
6d3351
-                                                       &tmp_addr, flags) < 0) {
6d3351
+                    if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
                         goto cleanup;
6d3351
-                    }
6d3351
 
6d3351
                     cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6d3351
                     cont->info.addr.pci.domain = 0;
6d3351
@@ -1354,10 +1357,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
6d3351
                 memset(&tmp_addr, 0, sizeof(tmp_addr));
6d3351
                 tmp_addr.slot = 0x1E;
6d3351
                 if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
6d3351
-                    if (virDomainPCIAddressReserveAddr(addrs,
6d3351
-                                                       &tmp_addr, flags) < 0) {
6d3351
+                    if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
                         goto cleanup;
6d3351
-                    }
6d3351
 
6d3351
                     cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6d3351
                     cont->info.addr.pci.domain = 0;
6d3351
@@ -1380,12 +1381,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
6d3351
         tmp_addr.slot = 0x1F;
6d3351
         tmp_addr.function = 0;
6d3351
         tmp_addr.multi = VIR_TRISTATE_SWITCH_ON;
6d3351
-        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
6d3351
+        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
            goto cleanup;
6d3351
 
6d3351
         tmp_addr.function = 3;
6d3351
         tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
6d3351
-        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
6d3351
+        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
            goto cleanup;
6d3351
     }
6d3351
 
6d3351
@@ -1419,7 +1420,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
6d3351
                     goto cleanup;
6d3351
                 }
6d3351
             } else {
6d3351
-                if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
6d3351
+                if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
                     goto cleanup;
6d3351
                 primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6d3351
                 primaryVideo->info.addr.pci = tmp_addr;
6d3351
@@ -1445,8 +1446,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
6d3351
                       " device will not be possible without manual"
6d3351
                       " intervention");
6d3351
             virResetLastError();
6d3351
-        } else if (virDomainPCIAddressReserveAddr(addrs,
6d3351
-                                                  &tmp_addr, flags) < 0) {
6d3351
+        } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) {
6d3351
             goto cleanup;
6d3351
         }
6d3351
     }
6d3351
@@ -1467,7 +1467,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
6d3351
                 !virDeviceInfoPCIAddressWanted(&sound->info)) {
6d3351
                 continue;
6d3351
             }
6d3351
-            if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
6d3351
+            if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
6d3351
                 goto cleanup;
6d3351
 
6d3351
             sound->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6d3351
@@ -1671,7 +1671,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
6d3351
             if (foundAddr) {
6d3351
                 /* Reserve this function on the slot we found */
6d3351
                 if (virDomainPCIAddressReserveAddr(addrs, &addr,
6d3351
-                                                   cont->info.pciConnectFlags) < 0) {
6d3351
+                                                   cont->info.pciConnectFlags,
6d3351
+                                                   cont->info.isolationGroup) < 0) {
6d3351
                     goto error;
6d3351
                 }
6d3351
 
6d3351
-- 
6d3351
2.13.3
6d3351