aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Deegan <tim@xen.org>2011-09-08 12:23:52 +0100
committerTim Deegan <tim@xen.org>2011-09-08 12:23:52 +0100
commitc8dc5e7b2537bc06790d7ba61521c11fe5f9bc7f (patch)
treefefa039b613a24cd6778088e0503cca00df1a6b7
parent123e4f10bc9ced554f67b8354c269d20928b34c3 (diff)
downloadxen-c8dc5e7b2537bc06790d7ba61521c11fe5f9bc7f.tar.gz
xen-c8dc5e7b2537bc06790d7ba61521c11fe5f9bc7f.tar.bz2
xen-c8dc5e7b2537bc06790d7ba61521c11fe5f9bc7f.zip
Passthrough: disable bus-mastering on any card that causes an IOMMU fault.
This stops the card from raising back-to-back faults and live-locking the CPU that handles them. Signed-off-by: Tim Deegan <tim@xen.org> Acked-by: Wei Wang2 <wei.wang2@amd.com> Acked-by: Allen M Kay <allen.m.kay@intel.com> xen-unstable changeset: 23762:537ed3b74b3f xen-unstable date: Fri Aug 12 11:29:24 2011 +0100
-rw-r--r--xen/drivers/passthrough/amd/iommu_init.c14
-rw-r--r--xen/drivers/passthrough/vtd/iommu.c10
2 files changed, 22 insertions, 2 deletions
diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c
index 4f420430ea..c0ceb2ee92 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -457,7 +457,7 @@ static hw_irq_controller iommu_msi_type = {
static void parse_event_log_entry(u32 entry[])
{
- u16 domain_id, device_id;
+ u16 domain_id, device_id, bdf, cword;
u32 code;
u64 *addr;
char * event_str[] = {"ILLEGAL_DEV_TABLE_ENTRY",
@@ -491,6 +491,18 @@ static void parse_event_log_entry(u32 entry[])
printk(XENLOG_ERR "AMD_IOV: "
"%s: domain:%d, device id:0x%x, fault address:0x%"PRIx64"\n",
event_str[code-1], domain_id, device_id, *addr);
+
+ /* Tell the device to stop DMAing; we can't rely on the guest to
+ * control it for us. */
+ for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
+ if ( get_dma_requestor_id(bdf) == device_id )
+ {
+ cword = pci_conf_read16(PCI_BUS(bdf), PCI_SLOT(bdf),
+ PCI_FUNC(bdf), PCI_COMMAND);
+ pci_conf_write16(PCI_BUS(bdf), PCI_SLOT(bdf),
+ PCI_FUNC(bdf), PCI_COMMAND,
+ cword & ~PCI_COMMAND_MASTER);
+ }
}
}
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index d5d5bfa63f..58fd111a42 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -888,7 +888,7 @@ static void iommu_page_fault(int irq, void *dev_id,
while (1)
{
u8 fault_reason;
- u16 source_id;
+ u16 source_id, cword;
u32 data;
u64 guest_addr;
int type;
@@ -921,6 +921,14 @@ static void iommu_page_fault(int irq, void *dev_id,
iommu_page_fault_do_one(iommu, type, fault_reason,
source_id, guest_addr);
+ /* Tell the device to stop DMAing; we can't rely on the guest to
+ * control it for us. */
+ cword = pci_conf_read16(PCI_BUS(source_id), PCI_SLOT(source_id),
+ PCI_FUNC(source_id), PCI_COMMAND);
+ pci_conf_write16(PCI_BUS(source_id), PCI_SLOT(source_id),
+ PCI_FUNC(source_id), PCI_COMMAND,
+ cword & ~PCI_COMMAND_MASTER);
+
fault_index++;
if ( fault_index > cap_num_fault_regs(iommu->cap) )
fault_index = 0;