74 lines
2.6 KiB
Diff
74 lines
2.6 KiB
Diff
|
# Commit 0f8adcb2a7183bea5063f6fffba7d7e1aa14fc84
|
||
|
# Date 2013-02-26 10:14:53 +0100
|
||
|
# Author Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
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>
|
||
|
|
||
|
--- a/xen/drivers/passthrough/amd/iommu_init.c
|
||
|
+++ b/xen/drivers/passthrough/amd/iommu_init.c
|
||
|
@@ -795,6 +795,42 @@ static int __init set_iommu_interrupt_ha
|
||
|
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(iommu->seg, bus, dev, func, 0xf0, 0x90);
|
||
|
+ value = pci_conf_read32(iommu->seg, bus, dev, func, 0xf4);
|
||
|
+
|
||
|
+ if ( value & (1 << 2) )
|
||
|
+ return;
|
||
|
+
|
||
|
+ /* Select NB indirect register 0x90 and enable writing */
|
||
|
+ pci_conf_write32(iommu->seg, bus, dev, func, 0xf0, 0x90 | (1 << 8));
|
||
|
+
|
||
|
+ pci_conf_write32(iommu->seg, bus, dev, func, 0xf4, value | (1 << 2));
|
||
|
+ printk(XENLOG_INFO
|
||
|
+ "AMD-Vi: Applying erratum 746 workaround for IOMMU at %04x:%02x:%02x.%u\n",
|
||
|
+ iommu->seg, bus, dev, func);
|
||
|
+
|
||
|
+ /* Clear the enable writing bit */
|
||
|
+ pci_conf_write32(iommu->seg, bus, dev, func, 0xf0, 0x90);
|
||
|
+}
|
||
|
+
|
||
|
static void enable_iommu(struct amd_iommu *iommu)
|
||
|
{
|
||
|
unsigned long flags;
|
||
|
@@ -807,6 +843,8 @@ static void enable_iommu(struct amd_iomm
|
||
|
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);
|