mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-13 16:15:19 +00:00
Allow vfio hotplug of a device to the domain which owns the iommu
The commit 7e72de4 didn't consider the hotplug scenarios. The patch addresses the hotplug case whereby if atleast one of the pci function is owned by a guest, the hotplug of other functions/devices in the same iommu group to the same guest goes through successfully. Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com> (cherry picked from commit e3810db34f1acb74dfcfd69219930e23a30284f6)
This commit is contained in:
parent
9e41bdf4d0
commit
87bacf5df2
@ -54,23 +54,35 @@ static virClassPtr virHostdevManagerClass;
|
|||||||
static void virHostdevManagerDispose(void *obj);
|
static void virHostdevManagerDispose(void *obj);
|
||||||
static virHostdevManagerPtr virHostdevManagerNew(void);
|
static virHostdevManagerPtr virHostdevManagerNew(void);
|
||||||
|
|
||||||
|
struct virHostdevIsPCINodeDeviceUsedData {
|
||||||
|
virHostdevManagerPtr hostdev_mgr;
|
||||||
|
const char *domainName;
|
||||||
|
const bool usesVfio;
|
||||||
|
};
|
||||||
|
|
||||||
static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *opaque)
|
static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *opaque)
|
||||||
{
|
{
|
||||||
virPCIDevicePtr other;
|
virPCIDevicePtr other;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virPCIDevicePtr pci = NULL;
|
virPCIDevicePtr pci = NULL;
|
||||||
virHostdevManagerPtr hostdev_mgr = opaque;
|
struct virHostdevIsPCINodeDeviceUsedData *helperData = opaque;
|
||||||
|
|
||||||
if (!(pci = virPCIDeviceNew(devAddr->domain, devAddr->bus,
|
if (!(pci = virPCIDeviceNew(devAddr->domain, devAddr->bus,
|
||||||
devAddr->slot, devAddr->function)))
|
devAddr->slot, devAddr->function)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
other = virPCIDeviceListFind(hostdev_mgr->activePCIHostdevs, pci);
|
other = virPCIDeviceListFind(helperData->hostdev_mgr->activePCIHostdevs,
|
||||||
|
pci);
|
||||||
if (other) {
|
if (other) {
|
||||||
const char *other_drvname = NULL;
|
const char *other_drvname = NULL;
|
||||||
const char *other_domname = NULL;
|
const char *other_domname = NULL;
|
||||||
virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname);
|
virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname);
|
||||||
|
|
||||||
|
if (helperData->usesVfio &&
|
||||||
|
(other_domname && helperData->domainName) &&
|
||||||
|
(STREQ(other_domname, helperData->domainName)))
|
||||||
|
goto iommu_owner;
|
||||||
|
|
||||||
if (other_drvname && other_domname)
|
if (other_drvname && other_domname)
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
_("PCI device %s is in use by "
|
_("PCI device %s is in use by "
|
||||||
@ -83,6 +95,7 @@ static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *o
|
|||||||
virPCIDeviceGetName(pci));
|
virPCIDeviceGetName(pci));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
iommu_owner:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
cleanup:
|
cleanup:
|
||||||
virPCIDeviceFree(pci);
|
virPCIDeviceFree(pci);
|
||||||
@ -562,6 +575,9 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
|
|||||||
for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
|
for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
|
||||||
virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
|
virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
|
||||||
bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK);
|
bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK);
|
||||||
|
bool usesVfio = STREQ(virPCIDeviceGetStubDriver(dev), "vfio-pci");
|
||||||
|
struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, dom_name,
|
||||||
|
usesVfio};
|
||||||
|
|
||||||
if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) {
|
if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) {
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
@ -579,12 +595,12 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
|
|||||||
* belonging to same iommu group can't be shared
|
* belonging to same iommu group can't be shared
|
||||||
* across guests.
|
* across guests.
|
||||||
*/
|
*/
|
||||||
if (STREQ(virPCIDeviceGetStubDriver(dev), "vfio-pci")) {
|
if (usesVfio) {
|
||||||
if (virPCIDeviceAddressIOMMUGroupIterate(devAddr,
|
if (virPCIDeviceAddressIOMMUGroupIterate(devAddr,
|
||||||
virHostdevIsPCINodeDeviceUsed,
|
virHostdevIsPCINodeDeviceUsed,
|
||||||
hostdev_mgr) < 0)
|
&data) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr)) {
|
} else if (virHostdevIsPCINodeDeviceUsed(devAddr, &data)) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1544,6 +1560,8 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
|
|||||||
virPCIDevicePtr pci)
|
virPCIDevicePtr pci)
|
||||||
{
|
{
|
||||||
virPCIDeviceAddressPtr devAddr = NULL;
|
virPCIDeviceAddressPtr devAddr = NULL;
|
||||||
|
struct virHostdevIsPCINodeDeviceUsedData data = { hostdev_mgr, NULL,
|
||||||
|
false };
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
virObjectLock(hostdev_mgr->activePCIHostdevs);
|
virObjectLock(hostdev_mgr->activePCIHostdevs);
|
||||||
@ -1552,7 +1570,7 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
|
|||||||
if (!(devAddr = virPCIDeviceGetAddress(pci)))
|
if (!(devAddr = virPCIDeviceGetAddress(pci)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr))
|
if (virHostdevIsPCINodeDeviceUsed(devAddr, &data))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (virPCIDeviceDetach(pci, hostdev_mgr->activePCIHostdevs,
|
if (virPCIDeviceDetach(pci, hostdev_mgr->activePCIHostdevs,
|
||||||
@ -1573,6 +1591,8 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
|
|||||||
virPCIDevicePtr pci)
|
virPCIDevicePtr pci)
|
||||||
{
|
{
|
||||||
virPCIDeviceAddressPtr devAddr = NULL;
|
virPCIDeviceAddressPtr devAddr = NULL;
|
||||||
|
struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, NULL,
|
||||||
|
false};
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
virObjectLock(hostdev_mgr->activePCIHostdevs);
|
virObjectLock(hostdev_mgr->activePCIHostdevs);
|
||||||
@ -1581,7 +1601,7 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
|
|||||||
if (!(devAddr = virPCIDeviceGetAddress(pci)))
|
if (!(devAddr = virPCIDeviceGetAddress(pci)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr))
|
if (virHostdevIsPCINodeDeviceUsed(devAddr, &data))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
virPCIDeviceReattachInit(pci);
|
virPCIDeviceReattachInit(pci);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user