aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>2013-03-08 13:57:54 +0100
committerJan Beulich <jbeulich@suse.com>2013-03-08 13:57:54 +0100
commitd3799c4e2a2d63b3300a9f48ee713df12c2232c2 (patch)
tree8a58bf9f5985c40392eeabbab045888bdb160a04
parentbbbeb7939e141c6cb29fd6f26beca68ffdfe9d46 (diff)
downloadxen-d3799c4e2a2d63b3300a9f48ee713df12c2232c2.tar.gz
xen-d3799c4e2a2d63b3300a9f48ee713df12c2232c2.tar.bz2
xen-d3799c4e2a2d63b3300a9f48ee713df12c2232c2.zip
IOMMU, AMD Family15h Model10-1Fh erratum 746 Workaround
The IOMMU may stop processing page translations due to a perceived lack of credits for writing upstream peripheral page service request (PPR) or event logs. If the L2B miscellaneous clock gating feature is enabled the IOMMU does not properly register credits after the log request has completed, leading to a potential system hang. BIOSes are supposed to disable L2B micellaneous clock gating by setting L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b. This patch corrects that for those which do not enable this workaround. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> master changeset: 0f8adcb2a7183bea5063f6fffba7d7e1aa14fc84 master date: 2013-02-26 10:14:53 +0100
-rw-r--r--xen/drivers/passthrough/amd/iommu_init.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c
index 282c04c0b2..31acec9310 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -636,6 +636,42 @@ static int set_iommu_interrupt_handler(struct amd_iommu *iommu)
return irq;
}
+/*
+ * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations)
+ * Workaround:
+ * BIOS should disable L2B micellaneous clock gating by setting
+ * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b
+ */
+static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
+{
+ u32 value;
+ u8 bus = PCI_BUS(iommu->bdf);
+ u8 dev = PCI_SLOT(iommu->bdf);
+ u8 func = PCI_FUNC(iommu->bdf);
+
+ if ( (boot_cpu_data.x86 != 0x15) ||
+ (boot_cpu_data.x86_model < 0x10) ||
+ (boot_cpu_data.x86_model > 0x1f) )
+ return;
+
+ pci_conf_write32(bus, dev, func, 0xf0, 0x90);
+ value = pci_conf_read32(bus, dev, func, 0xf4);
+
+ if ( value & (1 << 2) )
+ return;
+
+ /* Select NB indirect register 0x90 and enable writing */
+ pci_conf_write32(bus, dev, func, 0xf0, 0x90 | (1 << 8));
+
+ pci_conf_write32(bus, dev, func, 0xf4, value | (1 << 2));
+ printk(XENLOG_INFO
+ "AMD-Vi: Applying erratum 746 workaround for IOMMU at %02x:%02x.%u\n",
+ bus, dev, func);
+
+ /* Clear the enable writing bit */
+ pci_conf_write32(bus, dev, func, 0xf0, 0x90);
+}
+
static void enable_iommu(struct amd_iommu *iommu)
{
unsigned long flags;
@@ -648,6 +684,8 @@ static void enable_iommu(struct amd_iommu *iommu)
return;
}
+ amd_iommu_erratum_746_workaround(iommu);
+
register_iommu_dev_table_in_mmio_space(iommu);
register_iommu_cmd_buffer_in_mmio_space(iommu);
register_iommu_event_log_in_mmio_space(iommu);