|
|
6d3351 |
From 672fd7d403ef52f10084c5c0b6aaeeb94f6fba2a Mon Sep 17 00:00:00 2001
|
|
|
6d3351 |
Message-Id: <672fd7d403ef52f10084c5c0b6aaeeb94f6fba2a@dist-git>
|
|
|
6d3351 |
From: Andrea Bolognani <abologna@redhat.com>
|
|
|
6d3351 |
Date: Tue, 18 Jul 2017 12:10:06 +0200
|
|
|
6d3351 |
Subject: [PATCH] conf: Implement isolation rules
|
|
|
6d3351 |
|
|
|
6d3351 |
These rules will make it possible for libvirt to
|
|
|
6d3351 |
automatically assign PCI addresses in a way that
|
|
|
6d3351 |
respects any isolation constraints devices might
|
|
|
6d3351 |
have.
|
|
|
6d3351 |
|
|
|
6d3351 |
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
|
|
|
6d3351 |
Reviewed-by: Laine Stump <laine@laine.org>
|
|
|
6d3351 |
(cherry picked from commit 209dc615e898f027b6dc8fa6acd3aeba5fd465bd)
|
|
|
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/conf/domain_addr.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++---
|
|
|
6d3351 |
src/conf/domain_addr.h | 3 +++
|
|
|
6d3351 |
2 files changed, 72 insertions(+), 4 deletions(-)
|
|
|
6d3351 |
|
|
|
6d3351 |
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
|
|
|
6d3351 |
index a067493136..d586bb7e47 100644
|
|
|
6d3351 |
--- a/src/conf/domain_addr.c
|
|
|
6d3351 |
+++ b/src/conf/domain_addr.c
|
|
|
6d3351 |
@@ -369,6 +369,20 @@ virDomainPCIAddressBusIsFullyReserved(virDomainPCIAddressBusPtr bus)
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
|
|
|
6d3351 |
+bool
|
|
|
6d3351 |
+virDomainPCIAddressBusIsEmpty(virDomainPCIAddressBusPtr bus)
|
|
|
6d3351 |
+{
|
|
|
6d3351 |
+ size_t i;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ for (i = bus->minSlot; i <= bus->maxSlot; i++) {
|
|
|
6d3351 |
+ if (bus->slot[i].functions)
|
|
|
6d3351 |
+ return false;
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ return true;
|
|
|
6d3351 |
+}
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+
|
|
|
6d3351 |
/* Ensure addr fits in the address set, by expanding it if needed
|
|
|
6d3351 |
*
|
|
|
6d3351 |
* Return value:
|
|
|
6d3351 |
@@ -548,7 +562,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 |
+ unsigned int isolationGroup,
|
|
|
6d3351 |
bool fromConfig)
|
|
|
6d3351 |
{
|
|
|
6d3351 |
int ret = -1;
|
|
|
6d3351 |
@@ -586,6 +600,26 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs,
|
|
|
6d3351 |
bus->slot[addr->slot].aggregate = true;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
+ if (virDomainPCIAddressBusIsEmpty(bus) && !bus->isolationGroupLocked) {
|
|
|
6d3351 |
+ /* The first device decides the isolation group for the
|
|
|
6d3351 |
+ * entire bus */
|
|
|
6d3351 |
+ bus->isolationGroup = isolationGroup;
|
|
|
6d3351 |
+ VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %u because of "
|
|
|
6d3351 |
+ "first device %s",
|
|
|
6d3351 |
+ addr->domain, addr->bus, isolationGroup, addrStr);
|
|
|
6d3351 |
+ } else if (bus->isolationGroup != isolationGroup && fromConfig) {
|
|
|
6d3351 |
+ /* If this is not the first function and its isolation group
|
|
|
6d3351 |
+ * doesn't match the bus', then it should not be using this
|
|
|
6d3351 |
+ * address. However, if the address comes from the user then
|
|
|
6d3351 |
+ * we comply with the request and change the isolation group
|
|
|
6d3351 |
+ * back to the default (because at that point isolation can't
|
|
|
6d3351 |
+ * be guaranteed anymore) */
|
|
|
6d3351 |
+ bus->isolationGroup = 0;
|
|
|
6d3351 |
+ VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %u because of "
|
|
|
6d3351 |
+ "user assigned address %s",
|
|
|
6d3351 |
+ addr->domain, addr->bus, isolationGroup, addrStr);
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+
|
|
|
6d3351 |
/* mark the requested function as reserved */
|
|
|
6d3351 |
bus->slot[addr->slot].functions |= (1 << addr->function);
|
|
|
6d3351 |
VIR_DEBUG("Reserving PCI address %s (aggregate='%s')", addrStr,
|
|
|
6d3351 |
@@ -763,7 +797,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 |
+ unsigned int isolationGroup,
|
|
|
6d3351 |
int function)
|
|
|
6d3351 |
{
|
|
|
6d3351 |
virPCIDeviceAddress a = { 0 };
|
|
|
6d3351 |
@@ -779,12 +813,17 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs,
|
|
|
6d3351 |
else
|
|
|
6d3351 |
a.function = function;
|
|
|
6d3351 |
|
|
|
6d3351 |
- /* "Begin at the beginning," the King said, very gravely, "and go on
|
|
|
6d3351 |
- * till you come to the end: then stop." */
|
|
|
6d3351 |
+ /* When looking for a suitable bus for the device, start by being
|
|
|
6d3351 |
+ * very strict and ignoring all those where the isolation groups
|
|
|
6d3351 |
+ * don't match. This ensures all devices sharing the same isolation
|
|
|
6d3351 |
+ * group will end up on the same bus */
|
|
|
6d3351 |
for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) {
|
|
|
6d3351 |
virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus];
|
|
|
6d3351 |
bool found = false;
|
|
|
6d3351 |
|
|
|
6d3351 |
+ if (bus->isolationGroup != isolationGroup)
|
|
|
6d3351 |
+ continue;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
a.slot = bus->minSlot;
|
|
|
6d3351 |
|
|
|
6d3351 |
if (virDomainPCIAddressFindUnusedFunctionOnBus(bus, &a, function,
|
|
|
6d3351 |
@@ -796,6 +835,32 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs,
|
|
|
6d3351 |
goto success;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
+ /* We haven't been able to find a perfectly matching bus, but we
|
|
|
6d3351 |
+ * might still be able to make this work by altering the isolation
|
|
|
6d3351 |
+ * group for a bus that's currently empty. So let's try that */
|
|
|
6d3351 |
+ for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) {
|
|
|
6d3351 |
+ virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus];
|
|
|
6d3351 |
+ bool found = false;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ /* We can only change the isolation group for a bus when
|
|
|
6d3351 |
+ * plugging in the first device; moreover, some buses are
|
|
|
6d3351 |
+ * prevented from ever changing it */
|
|
|
6d3351 |
+ if (!virDomainPCIAddressBusIsEmpty(bus) || bus->isolationGroupLocked)
|
|
|
6d3351 |
+ continue;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ a.slot = bus->minSlot;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ if (virDomainPCIAddressFindUnusedFunctionOnBus(bus, &a, function,
|
|
|
6d3351 |
+ flags, &found) < 0) {
|
|
|
6d3351 |
+ goto error;
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ /* The isolation group for the bus will actually be changed
|
|
|
6d3351 |
+ * later, in virDomainPCIAddressReserveAddrInternal() */
|
|
|
6d3351 |
+ if (found)
|
|
|
6d3351 |
+ goto success;
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+
|
|
|
6d3351 |
/* There were no free slots after the last used one */
|
|
|
6d3351 |
if (addrs->dryRun) {
|
|
|
6d3351 |
/* a is already set to the first new bus */
|
|
|
6d3351 |
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
|
|
|
6d3351 |
index 01dbc5114f..ae6a342dbc 100644
|
|
|
6d3351 |
--- a/src/conf/domain_addr.h
|
|
|
6d3351 |
+++ b/src/conf/domain_addr.h
|
|
|
6d3351 |
@@ -150,6 +150,9 @@ int virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
|
|
|
6d3351 |
bool virDomainPCIAddressBusIsFullyReserved(virDomainPCIAddressBusPtr bus)
|
|
|
6d3351 |
ATTRIBUTE_NONNULL(1);
|
|
|
6d3351 |
|
|
|
6d3351 |
+bool virDomainPCIAddressBusIsEmpty(virDomainPCIAddressBusPtr bus)
|
|
|
6d3351 |
+ ATTRIBUTE_NONNULL(1);
|
|
|
6d3351 |
+
|
|
|
6d3351 |
bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
|
|
|
6d3351 |
virPCIDeviceAddressPtr addr)
|
|
|
6d3351 |
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
|
6d3351 |
--
|
|
|
6d3351 |
2.13.3
|
|
|
6d3351 |
|