1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-25 01:34:11 +03:00

conf: Introduce isolation groups

Isolation groups will eventually allow us to make sure certain
devices, eg. PCI hostdevs, are assigned to guest PCI buses in
a way that guarantees improved isolation, error detection and
recovery for machine types and hypervisors that support it,
eg. pSeries guest on QEMU.

This patch merely defines storage for the new information
we're going to need later on and makes sure it is passed from
the hypervisor driver (QEMU / bhyve) down to the generic PCI
address allocation code.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org>
This commit is contained in:
Andrea Bolognani 2017-06-15 16:38:33 +08:00
parent dae23ec345
commit b8b6abbcd4
6 changed files with 52 additions and 25 deletions

View File

@ -57,7 +57,7 @@ bhyveCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
}
if (virDomainPCIAddressReserveAddr(addrs, addr,
VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) {
VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) {
goto cleanup;
}
@ -100,7 +100,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def,
lpc_addr.slot = 0x1;
if (virDomainPCIAddressReserveAddr(addrs, &lpc_addr,
VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) {
VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) {
goto error;
}

View File

@ -164,6 +164,16 @@ struct _virDomainDeviceInfo {
*/
int pciConnectFlags; /* enum virDomainPCIConnectFlags */
char *loadparm;
/* PCI devices will only be automatically placed on a PCI bus
* that shares the same isolation group */
unsigned int isolationGroup;
/* Usually, PCI buses will take on the same isolation group
* as the first device that is plugged into them, but in some
* cases we might want to prevent that from happening by
* locking the isolation group */
bool isolationGroupLocked;
};

View File

@ -548,6 +548,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr,
virDomainPCIConnectFlags flags,
unsigned int isolationGroup ATTRIBUTE_UNUSED,
bool fromConfig)
{
int ret = -1;
@ -600,9 +601,11 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs,
int
virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr,
virDomainPCIConnectFlags flags)
virDomainPCIConnectFlags flags,
unsigned int isolationGroup)
{
return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags, true);
return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags,
isolationGroup, true);
}
int
@ -638,7 +641,8 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
goto cleanup;
ret = virDomainPCIAddressReserveAddrInternal(addrs, &dev->addr.pci,
flags, true);
flags, dev->isolationGroup,
true);
} else {
ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1);
}
@ -759,6 +763,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr next_addr,
virDomainPCIConnectFlags flags,
unsigned int isolationGroup ATTRIBUTE_UNUSED,
int function)
{
virPCIDeviceAddress a = { 0 };
@ -839,10 +844,12 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
{
virPCIDeviceAddress addr;
if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, function) < 0)
if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags,
dev->isolationGroup, function) < 0)
return -1;
if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, false) < 0)
if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags,
dev->isolationGroup, false) < 0)
return -1;
if (!addrs->dryRun) {

View File

@ -100,6 +100,12 @@ typedef struct {
* bit is set, that function is in use by a device.
*/
virDomainPCIAddressSlot slot[VIR_PCI_ADDRESS_SLOT_LAST + 1];
/* See virDomainDeviceInfo::isolationGroup */
unsigned int isolationGroup;
/* See virDomainDeviceInfo::isolationGroupLocked */
bool isolationGroupLocked;
} virDomainPCIAddressBus;
typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
@ -142,7 +148,8 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr,
virDomainPCIConnectFlags flags)
virDomainPCIConnectFlags flags,
unsigned int isolationGroup)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,

View File

@ -3670,6 +3670,8 @@ void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info)
info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
VIR_FREE(info->romfile);
VIR_FREE(info->loadparm);
info->isolationGroup = 0;
info->isolationGroupLocked = false;
}

View File

@ -1037,7 +1037,8 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
}
if (virDomainPCIAddressReserveAddr(addrs, addr,
info->pciConnectFlags) < 0) {
info->pciConnectFlags,
info->isolationGroup) < 0) {
goto cleanup;
}
@ -1082,6 +1083,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
if (virDomainPCIAddressBusSetModel(&addrs->buses[idx], cont->model) < 0)
goto error;
/* Forward the information about isolation groups */
addrs->buses[idx].isolationGroup = cont->info.isolationGroup;
addrs->buses[idx].isolationGroupLocked = cont->info.isolationGroupLocked;
if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
hasPCIeRoot = true;
}
@ -1198,7 +1203,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
if (addrs->nbuses) {
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 1;
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
}
@ -1233,7 +1238,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
goto cleanup;
}
} else {
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
primaryVideo->info.addr.pci = tmp_addr;
primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
@ -1258,7 +1263,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video"
" device will not be possible without manual"
" intervention");
} else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) {
} else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) {
goto cleanup;
}
}
@ -1334,10 +1339,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
assign = true;
}
if (assign) {
if (virDomainPCIAddressReserveAddr(addrs,
&tmp_addr, flags) < 0) {
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
}
cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
cont->info.addr.pci.domain = 0;
@ -1359,10 +1362,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 0x1E;
if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
if (virDomainPCIAddressReserveAddr(addrs,
&tmp_addr, flags) < 0) {
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
}
cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
cont->info.addr.pci.domain = 0;
@ -1385,12 +1386,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
tmp_addr.slot = 0x1F;
tmp_addr.function = 0;
tmp_addr.multi = VIR_TRISTATE_SWITCH_ON;
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
tmp_addr.function = 3;
tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
}
@ -1424,7 +1425,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
goto cleanup;
}
} else {
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
primaryVideo->info.addr.pci = tmp_addr;
@ -1450,8 +1451,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
" device will not be possible without manual"
" intervention");
virResetLastError();
} else if (virDomainPCIAddressReserveAddr(addrs,
&tmp_addr, flags) < 0) {
} else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) {
goto cleanup;
}
}
@ -1472,7 +1472,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
!virDeviceInfoPCIAddressWanted(&sound->info)) {
continue;
}
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0)
if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
goto cleanup;
sound->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
@ -1676,7 +1676,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
if (foundAddr) {
/* Reserve this function on the slot we found */
if (virDomainPCIAddressReserveAddr(addrs, &addr,
cont->info.pciConnectFlags) < 0) {
cont->info.pciConnectFlags,
cont->info.isolationGroup) < 0) {
goto error;
}