# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxx>
# Date 1313144964 -3600
# Node ID 537ed3b74b3f13267cfb3eb0e1483f432f3685cd
# Parent 1f08b380d4386cdd6714786a9163e5f51aecab5d
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@xxxxxxx>
Acked-by: Wei Wang2 <wei.wang2@xxxxxxx>
Acked-by: Allen M Kay <allen.m.kay@xxxxxxxxx>
---
diff -r 1f08b380d438 -r 537ed3b74b3f xen/drivers/passthrough/amd/iommu_init.c
--- a/xen/drivers/passthrough/amd/iommu_init.c Wed Aug 10 14:43:34 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_init.c Fri Aug 12 11:29:24 2011 +0100
@@ -461,7 +461,7 @@
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",
@@ -496,6 +496,18 @@
"%s: domain = %d, device id = 0x%04x, "
"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_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);
+ }
}
else
{
diff -r 1f08b380d438 -r 537ed3b74b3f xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Wed Aug 10 14:43:34 2011 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Fri Aug 12 11:29:24 2011 +0100
@@ -884,7 +884,7 @@
while (1)
{
u8 fault_reason;
- u16 source_id;
+ u16 source_id, cword;
u32 data;
u64 guest_addr;
int type;
@@ -917,6 +917,14 @@
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;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|