File 25387-amd-iommu-workaround-73x.patch of Package xen.openSUSE_12.1_Update
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1337786286 -7200
# Node ID af559b5afbecba1048ad690347455ad54098f935
# Parent 340062faf2988eeea94e37dbb3943c5a449bff10
amd iommu: Add workaround for erratum 732 & 733
Signed-off-by: Wei Wang <wei.wang2@amd.com>
Add missing barriers. Fix early return from parse_ppr_log_entry().
Slightly adjust comments. Strip trailing blanks.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Committed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -27,6 +27,7 @@
#include <asm/hvm/svm/amd-iommu-proto.h>
#include <asm-x86/fixmap.h>
#include <mach_apic.h>
+#include <xen/delay.h>
static struct amd_iommu **irq_to_iommu;
static int nr_amd_iommus;
@@ -467,6 +468,7 @@ static void parse_event_log_entry(u32 en
u16 domain_id, device_id, bdf, cword;
u32 code;
u64 *addr;
+ int count = 0;
char * event_str[] = {"ILLEGAL_DEV_TABLE_ENTRY",
"IO_PAGE_FAULT",
"DEV_TABLE_HW_ERROR",
@@ -479,6 +481,25 @@ static void parse_event_log_entry(u32 en
code = get_field_from_reg_u32(entry[1], IOMMU_EVENT_CODE_MASK,
IOMMU_EVENT_CODE_SHIFT);
+ /*
+ * Workaround for erratum 732:
+ * It can happen that the tail pointer is updated before the actual entry
+ * got written. As suggested by RevGuide, we initialize the event log
+ * buffer to all zeros and clear event log entries after processing them.
+ */
+ while ( code == 0 )
+ {
+ if ( unlikely(++count == IOMMU_LOG_ENTRY_TIMEOUT) )
+ {
+ AMD_IOMMU_DEBUG("AMD-Vi: No event written to log\n");
+ return;
+ }
+ udelay(1);
+ rmb();
+ code = get_field_from_reg_u32(entry[1], IOMMU_EVENT_CODE_MASK,
+ IOMMU_EVENT_CODE_SHIFT);
+ }
+
if ( (code > IOMMU_EVENT_INVALID_DEV_REQUEST) ||
(code < IOMMU_EVENT_ILLEGAL_DEV_TABLE_ENTRY) )
{
@@ -517,6 +538,8 @@ static void parse_event_log_entry(u32 en
AMD_IOMMU_DEBUG("event 0x%08x 0x%08x 0x%08x 0x%08x\n", entry[0],
entry[1], entry[2], entry[3]);
}
+
+ memset(entry, 0, IOMMU_EVENT_LOG_ENTRY_SIZE);
}
static void do_amd_iommu_irq(unsigned long data)
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
@@ -269,6 +269,8 @@
#define IOMMU_EVENT_DEVICE_ID_MASK 0x0000FFFF
#define IOMMU_EVENT_DEVICE_ID_SHIFT 0
+#define IOMMU_LOG_ENTRY_TIMEOUT 1000
+
/* Control Register */
#define IOMMU_CONTROL_MMIO_OFFSET 0x18
#define IOMMU_CONTROL_TRANSLATION_ENABLE_MASK 0x00000001