Rework pass through changes in r305485 to be safer.
Specifically, devices that do not support PCI-e FLR and were not gracefully shutdown by the guest OS could continue to issue DMA requests after the VM was terminated. The changes in r305485 meant that those DMA requests were completed against the host's memory which could result in random memory corruption. Instead, leave ppt devices that are not attached to a VM disabled in the IOMMU and only restore the devices to the host domain if the ppt(4) driver is detached from a device. As an added safety belt, disable busmastering for a pass-through device when before adding it to the host domain during ppt(4) detach. PR: 222937 Tested by: Harry Schmalzbauer <freebsd@omnilan.de> Reviewed by: grehan MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D12661
This commit is contained in:
parent
1c05a6ea6b
commit
6db55a0f3a
@ -174,6 +174,7 @@ iommu_init(void)
|
||||
{
|
||||
int error, bus, slot, func;
|
||||
vm_paddr_t maxaddr;
|
||||
devclass_t dc;
|
||||
device_t dev;
|
||||
|
||||
if (!iommu_enable)
|
||||
@ -214,6 +215,7 @@ iommu_init(void)
|
||||
add_tag = EVENTHANDLER_REGISTER(pci_add_device, iommu_pci_add, NULL, 0);
|
||||
delete_tag = EVENTHANDLER_REGISTER(pci_delete_device, iommu_pci_delete,
|
||||
NULL, 0);
|
||||
dc = devclass_find("ppt");
|
||||
for (bus = 0; bus <= PCI_BUSMAX; bus++) {
|
||||
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
|
||||
for (func = 0; func <= PCI_FUNCMAX; func++) {
|
||||
@ -221,7 +223,15 @@ iommu_init(void)
|
||||
if (dev == NULL)
|
||||
continue;
|
||||
|
||||
/* Everything belongs to the host domain. */
|
||||
/* Skip passthrough devices. */
|
||||
if (dc != NULL &&
|
||||
device_get_devclass(dev) == dc)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Everything else belongs to the host
|
||||
* domain.
|
||||
*/
|
||||
iommu_add_device(host_domain,
|
||||
pci_get_rid(dev));
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ ppt_attach(device_t dev)
|
||||
|
||||
ppt = device_get_softc(dev);
|
||||
|
||||
iommu_remove_device(iommu_host_domain(), pci_get_rid(dev));
|
||||
num_pptdevs++;
|
||||
TAILQ_INSERT_TAIL(&pptdev_list, ppt, next);
|
||||
ppt->dev = dev;
|
||||
@ -175,6 +176,8 @@ ppt_detach(device_t dev)
|
||||
return (EBUSY);
|
||||
num_pptdevs--;
|
||||
TAILQ_REMOVE(&pptdev_list, ppt, next);
|
||||
pci_disable_busmaster(dev);
|
||||
iommu_add_device(iommu_host_domain(), pci_get_rid(dev));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -368,7 +371,6 @@ ppt_assign_device(struct vm *vm, int bus, int slot, int func)
|
||||
true);
|
||||
pci_restore_state(ppt->dev);
|
||||
ppt->vm = vm;
|
||||
iommu_remove_device(iommu_host_domain(), pci_get_rid(ppt->dev));
|
||||
iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
|
||||
return (0);
|
||||
}
|
||||
@ -397,7 +399,6 @@ ppt_unassign_device(struct vm *vm, int bus, int slot, int func)
|
||||
ppt_teardown_msi(ppt);
|
||||
ppt_teardown_msix(ppt);
|
||||
iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
|
||||
iommu_add_device(iommu_host_domain(), pci_get_rid(ppt->dev));
|
||||
ppt->vm = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user