aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-19 12:39:08 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-19 12:39:08 +0100
commit92a3c6a08eebe277c36d5d3ceb14f3a355228976 (patch)
treede0a08699d46ac40a9679bcd6fd8fda730fb520f
parentb2c4071e1e5271df15bc64fd8124739c9815f0dd (diff)
downloadxen-92a3c6a08eebe277c36d5d3ceb14f3a355228976.tar.gz
xen-92a3c6a08eebe277c36d5d3ceb14f3a355228976.tar.bz2
xen-92a3c6a08eebe277c36d5d3ceb14f3a355228976.zip
svm: Fix for AMD erratum 383 on Family 10h CPUs
This patches implements the workaround of AMD erratum 383 on family 10h CPUs. It destroys the guest VM when a MC error with a special pattern is detected. Without this patch, a guest VM failure can potentially crash Xen hypervisor and the whole system. The erratum will be published in next version of guide. Signed-off-by: Wei Huang <wei.huang2@amd.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Christoph Egger <christoph.egger@amd.com> xen-unstable changeset: 21408:f40acba36be8 xen-unstable date: Tue May 18 11:21:25 2010 +0100
-rw-r--r--xen/arch/x86/hvm/svm/svm.c61
-rw-r--r--xen/include/asm-x86/msr-index.h6
2 files changed, 67 insertions, 0 deletions
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index fae90f4f67..d1139f3152 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -69,6 +69,8 @@ static void *hsa[NR_CPUS] __read_mostly;
/* vmcb used for extended host state */
static void *root_vmcb[NR_CPUS] __read_mostly;
+static bool_t amd_erratum383_found __read_mostly;
+
static void inline __update_guest_eip(
struct cpu_user_regs *regs, unsigned int inst_len)
{
@@ -819,6 +821,20 @@ static int svm_cpu_prepare(unsigned int cpu)
return 0;
}
+static void svm_init_erratum_383(struct cpuinfo_x86 *c)
+{
+ uint64_t msr_content;
+
+ /* only family 10h is affected */
+ if ( c->x86 != 0x10 )
+ return;
+
+ rdmsrl(MSR_AMD64_DC_CFG, msr_content);
+ wrmsrl(MSR_AMD64_DC_CFG, msr_content | (1ULL << 47));
+
+ amd_erratum383_found = 1;
+}
+
static int svm_cpu_up(struct cpuinfo_x86 *c)
{
u32 eax, edx, phys_hsa_lo, phys_hsa_hi;
@@ -844,6 +860,9 @@ static int svm_cpu_up(struct cpuinfo_x86 *c)
phys_hsa_hi = (u32)(phys_hsa >> 32);
wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
+ /* check for erratum 383 */
+ svm_init_erratum_383(c);
+
/* Initialize core's ASID handling. */
svm_asid_init(c);
@@ -1218,6 +1237,47 @@ static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
}
}
+extern unsigned int nr_mce_banks; /* from mce.h */
+
+static int svm_is_erratum_383(struct cpu_user_regs *regs)
+{
+ uint64_t msr_content;
+ uint32_t i;
+ struct vcpu *v = current;
+
+ if ( !amd_erratum383_found )
+ return 0;
+
+ rdmsrl(MSR_IA32_MC0_STATUS, msr_content);
+ /* Bit 62 may or may not be set for this mce */
+ msr_content &= ~(1ULL << 62);
+
+ if ( msr_content != 0xb600000000010015ULL )
+ return 0;
+
+ /* Clear MCi_STATUS registers */
+ for (i = 0; i < nr_mce_banks; i++)
+ wrmsrl(MSR_IA32_MCx_STATUS(i), 0ULL);
+
+ rdmsrl(MSR_IA32_MCG_STATUS, msr_content);
+ wrmsrl(MSR_IA32_MCG_STATUS, msr_content & ~(1ULL << 2));
+
+ /* flush TLB */
+ flush_tlb_mask(&v->domain->domain_dirty_cpumask);
+
+ return 1;
+}
+
+static void svm_vmexit_mce_intercept(
+ struct vcpu *v, struct cpu_user_regs *regs)
+{
+ if ( svm_is_erratum_383(regs) )
+ {
+ gdprintk(XENLOG_ERR, "SVM hits AMD erratum 383\n");
+ domain_crash(v->domain);
+ }
+}
+
static void wbinvd_ipi(void *info)
{
wbinvd();
@@ -1406,6 +1466,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
/* Asynchronous event, handled when we STGI'd after the VMEXIT. */
case VMEXIT_EXCEPTION_MC:
HVMTRACE_0D(MCE);
+ svm_vmexit_mce_intercept(v, regs);
break;
case VMEXIT_VINTR:
diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h
index 1045fb1f10..486621f4ed 100644
--- a/xen/include/asm-x86/msr-index.h
+++ b/xen/include/asm-x86/msr-index.h
@@ -146,6 +146,11 @@
#define MSR_IA32_MC8_ADDR 0x00000422
#define MSR_IA32_MC8_MISC 0x00000423
+#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x))
+#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x))
+#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x))
+#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x))
+
#define MSR_P6_PERFCTR0 0x000000c1
#define MSR_P6_PERFCTR1 0x000000c2
#define MSR_P6_EVNTSEL0 0x00000186
@@ -224,6 +229,7 @@
/* AMD64 MSRs */
#define MSR_AMD64_NB_CFG 0xc001001f
+#define MSR_AMD64_DC_CFG 0xc0011022
#define AMD64_NB_CFG_CF8_EXT_ENABLE_BIT 46
/* AMD Family10h machine check MSRs */