Skip to content

Commit

Permalink
iommu/vt-d: Avoid caching stale domain_device_info when hot-removing …
Browse files Browse the repository at this point in the history
…PCI device

Function device_notifier() in intel-iommu.c only remove domain_device_info
data structure associated with a PCI device when handling PCI device
driver unbinding events. If a PCI device has never been bound to a PCI
device driver, there won't be BUS_NOTIFY_UNBOUND_DRIVER event when
hot-removing the PCI device. So associated domain_device_info data
structure may get lost.

On the other hand, if iommu_pass_through is enabled, function
iommu_prepare_static_indentify_mapping() will create domain_device_info
data structure for each PCIe to PCIe bridge and PCIe endpoint,
no matter whether there are drivers associated with those PCIe devices
or not. So those domain_device_info data structures will get lost when
hot-removing the assocated PCIe devices if they have never bound to
any PCI device driver.

To be even worse, it's not only an memory leak issue, but also an
caching of stale information bug because the memory are kept in
device_domain_list and domain->devices lists.

Fix the bug by trying to remove domain_device_info data structure when
handling BUS_NOTIFY_DEL_DEVICE event.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Joerg Roedel <joro@8bytes.org>
  • Loading branch information
Jiang Liu authored and Joerg Roedel committed Mar 4, 2014
1 parent 816997d commit 7e7dfab
Showing 1 changed file with 9 additions and 8 deletions.
17 changes: 9 additions & 8 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3603,18 +3603,19 @@ static int device_notifier(struct notifier_block *nb,
if (iommu_dummy(pdev))
return 0;

if (action != BUS_NOTIFY_UNBOUND_DRIVER &&
action != BUS_NOTIFY_DEL_DEVICE)
return 0;

domain = find_domain(pdev);
if (!domain)
return 0;

if (action == BUS_NOTIFY_UNBOUND_DRIVER) {
domain_remove_one_dev_info(domain, pdev);

if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
!(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
list_empty(&domain->devices))
domain_exit(domain);
}
domain_remove_one_dev_info(domain, pdev);
if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
!(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
list_empty(&domain->devices))
domain_exit(domain);

return 0;
}
Expand Down

0 comments on commit 7e7dfab

Please sign in to comment.