Skip to content

Commit da72a37

Browse files
dsdjoergroedel
authored andcommitted
iommu/vt-d: Ignore devices with out-of-spec domain number
VMD subdevices are created with a PCI domain ID of 0x10000 or higher. These subdevices are also handled like all other PCI devices by dmar_pci_bus_notifier(). However, when dmar_alloc_pci_notify_info() take records of such devices, it will truncate the domain ID to a u16 value (in info->seg). The device at (e.g.) 10000:00:02.0 is then treated by the DMAR code as if it is 0000:00:02.0. In the unlucky event that a real device also exists at 0000:00:02.0 and also has a device-specific entry in the DMAR table, dmar_insert_dev_scope() will crash on:   BUG_ON(i >= devices_cnt); That's basically a sanity check that only one PCI device matches a single DMAR entry; in this case we seem to have two matching devices. Fix this by ignoring devices that have a domain number higher than what can be looked up in the DMAR table. This problem was carefully diagnosed by Jian-Hong Pan. Signed-off-by: Lu Baolu <[email protected]> Signed-off-by: Daniel Drake <[email protected]> Fixes: 59ce051 ("iommu/vt-d: Update DRHD/RMRR/ATSR device scope caches when PCI hotplug happens") Signed-off-by: Joerg Roedel <[email protected]>
1 parent b0bb0c2 commit da72a37

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

drivers/iommu/dmar.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/slab.h>
2929
#include <linux/iommu.h>
3030
#include <linux/numa.h>
31+
#include <linux/limits.h>
3132
#include <asm/irq_remapping.h>
3233
#include <asm/iommu_table.h>
3334

@@ -128,6 +129,13 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event)
128129

129130
BUG_ON(dev->is_virtfn);
130131

132+
/*
133+
* Ignore devices that have a domain number higher than what can
134+
* be looked up in DMAR, e.g. VMD subdevices with domain 0x10000
135+
*/
136+
if (pci_domain_nr(dev->bus) > U16_MAX)
137+
return NULL;
138+
131139
/* Only generate path[] for device addition event */
132140
if (event == BUS_NOTIFY_ADD_DEVICE)
133141
for (tmp = dev; tmp; tmp = tmp->bus->self)

0 commit comments

Comments
 (0)