diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-05-19 12:39:08 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-05-19 12:39:08 +0100 |
commit | 92a3c6a08eebe277c36d5d3ceb14f3a355228976 (patch) | |
tree | de0a08699d46ac40a9679bcd6fd8fda730fb520f | |
parent | b2c4071e1e5271df15bc64fd8124739c9815f0dd (diff) | |
download | xen-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.c | 61 | ||||
-rw-r--r-- | xen/include/asm-x86/msr-index.h | 6 |
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 */ |