73 lines
2.7 KiB
Diff
73 lines
2.7 KiB
Diff
|
References: bnc#712051, CVE-2011-3131
|
||
|
|
||
|
# HG changeset patch
|
||
|
# User Tim Deegan <Tim.Deegan@citrix.com>
|
||
|
# 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@xen.org>
|
||
|
Acked-by: Wei Wang2 <wei.wang2@amd.com>
|
||
|
Acked-by: Allen M Kay <allen.m.kay@intel.com>
|
||
|
|
||
|
--- a/xen/drivers/passthrough/amd/iommu_init.c
|
||
|
+++ b/xen/drivers/passthrough/amd/iommu_init.c
|
||
|
@@ -462,7 +462,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",
|
||
|
@@ -497,6 +497,18 @@ static void parse_event_log_entry(u32 en
|
||
|
"%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_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);
|
||
|
+ }
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
--- a/xen/drivers/passthrough/vtd/iommu.c
|
||
|
+++ b/xen/drivers/passthrough/vtd/iommu.c
|
||
|
@@ -887,7 +887,7 @@ static void iommu_page_fault(int irq, vo
|
||
|
while (1)
|
||
|
{
|
||
|
u8 fault_reason;
|
||
|
- u16 source_id;
|
||
|
+ u16 source_id, cword;
|
||
|
u32 data;
|
||
|
u64 guest_addr;
|
||
|
int type;
|
||
|
@@ -920,6 +920,14 @@ static void iommu_page_fault(int irq, vo
|
||
|
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;
|