# User Christoph Egger # Date 1347954757 -7200 Add vMCE support to AMD. Add vmce namespace to Intel specific vMCE MSR functions. Move vMCE prototypes from mce.h to vmce.h Signed-off-by: Christoph Egger diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/amd_f10.c --- a/xen/arch/x86/cpu/mcheck/amd_f10.c +++ b/xen/arch/x86/cpu/mcheck/amd_f10.c @@ -104,3 +104,40 @@ enum mcheck_type amd_f10_mcheck_init(str return mcheck_amd_famXX; } + +/* amd specific MCA MSR */ +int vmce_amd_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val) +{ + int ret = 0; + + switch (msr) { + case MSR_F10_MC4_MISC1: + case MSR_F10_MC4_MISC2: + case MSR_F10_MC4_MISC3: + break; + default: + mce_printk(MCE_QUIET, "Guest writes unhandled MSR 0x%x\n", msr); + ret = 1; + break; + } + + return ret; +} + +int vmce_amd_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val) +{ + int ret = 0; + + switch (msr) { + case MSR_F10_MC4_MISC1: + case MSR_F10_MC4_MISC2: + case MSR_F10_MC4_MISC3: + break; + default: + mce_printk(MCE_QUIET, "Guest reads unhandled MSR 0x%x\n", msr); + ret = 1; + break; + } + + return ret; +} diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/amd_nonfatal.c --- a/xen/arch/x86/cpu/mcheck/amd_nonfatal.c +++ b/xen/arch/x86/cpu/mcheck/amd_nonfatal.c @@ -64,6 +64,7 @@ #include #include "mce.h" +#include "vmce.h" static struct timer mce_timer; diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/mce.c --- a/xen/arch/x86/cpu/mcheck/mce.c +++ b/xen/arch/x86/cpu/mcheck/mce.c @@ -25,6 +25,7 @@ #include "mce.h" #include "barrier.h" #include "util.h" +#include "vmce.h" bool_t __read_mostly mce_disabled; invbool_param("mce", mce_disabled); diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/mce.h --- a/xen/arch/x86/cpu/mcheck/mce.h +++ b/xen/arch/x86/cpu/mcheck/mce.h @@ -49,15 +49,9 @@ void intel_mcheck_timer(struct cpuinfo_x void mce_intel_feature_init(struct cpuinfo_x86 *c); void amd_nonfatal_mcheck_init(struct cpuinfo_x86 *c); -int is_vmce_ready(struct mcinfo_bank *bank, struct domain *d); -int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn); - -u64 mce_cap_init(void); +uint64_t mce_cap_init(void); extern unsigned int firstbank; -int intel_mce_rdmsr(const struct vcpu *, uint32_t msr, uint64_t *val); -int intel_mce_wrmsr(struct vcpu *, uint32_t msr, uint64_t val); - struct mcinfo_extended *intel_get_extended_msrs( struct mcinfo_global *mig, struct mc_info *mi); @@ -69,9 +63,6 @@ void mc_panic(char *s); void x86_mc_get_cpu_info(unsigned, uint32_t *, uint16_t *, uint16_t *, uint32_t *, uint32_t *, uint32_t *, uint32_t *); -#define dom0_vmce_enabled() (dom0 && dom0->max_vcpus && dom0->vcpu[0] \ - && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) - /* Register a handler for machine check exceptions. */ typedef void (*x86_mce_vector_t)(struct cpu_user_regs *, long); extern void x86_mce_vector_register(x86_mce_vector_t); @@ -166,12 +157,6 @@ void *x86_mcinfo_add(struct mc_info *mi, void *x86_mcinfo_reserve(struct mc_info *mi, int size); void x86_mcinfo_dump(struct mc_info *mi); -int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d, - uint64_t gstatus); -int inject_vmce(struct domain *d); -int vmce_domain_inject(struct mcinfo_bank *bank, struct domain *d, - struct mcinfo_global *global); - static inline int mce_vendor_bank_msr(const struct vcpu *v, uint32_t msr) { switch (boot_cpu_data.x86_vendor) { diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/mce_intel.c --- a/xen/arch/x86/cpu/mcheck/mce_intel.c +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c @@ -18,6 +18,7 @@ #include "x86_mca.h" #include "barrier.h" #include "util.h" +#include "vmce.h" DEFINE_PER_CPU(struct mca_banks *, mce_banks_owned); DEFINE_PER_CPU(struct mca_banks *, no_cmci_banks); @@ -980,7 +981,7 @@ enum mcheck_type intel_mcheck_init(struc } /* intel specific MCA MSR */ -int intel_mce_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val) +int vmce_intel_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val) { int ret = 0; @@ -995,7 +996,7 @@ int intel_mce_wrmsr(struct vcpu *v, uint return ret; } -int intel_mce_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val) +int vmce_intel_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val) { int ret = 0; diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/non-fatal.c --- a/xen/arch/x86/cpu/mcheck/non-fatal.c +++ b/xen/arch/x86/cpu/mcheck/non-fatal.c @@ -21,6 +21,7 @@ #include #include "mce.h" +#include "vmce.h" DEFINE_PER_CPU(struct mca_banks *, poll_bankmask); static struct timer mce_timer; diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/vmce.c --- a/xen/arch/x86/cpu/mcheck/vmce.c +++ b/xen/arch/x86/cpu/mcheck/vmce.c @@ -16,8 +16,10 @@ #include #include #include + #include "mce.h" #include "x86_mca.h" +#include "vmce.h" /* * Emulate 2 banks for guest @@ -27,7 +29,7 @@ * Bank1: used to transfer error info to guest */ #define GUEST_BANK_NUM 2 -#define GUEST_MCG_CAP (MCG_TES_P | MCG_SER_P | GUEST_BANK_NUM) +#define GUEST_MCG_CAP (GUEST_BANK_NUM) #define dom_vmce(x) ((x)->arch.vmca_msrs) @@ -138,7 +140,10 @@ static int bank_mce_rdmsr(const struct v switch ( boot_cpu_data.x86_vendor ) { case X86_VENDOR_INTEL: - ret = intel_mce_rdmsr(v, msr, val); + ret = vmce_intel_rdmsr(v, msr, val); + break; + case X86_VENDOR_AMD: + ret = vmce_amd_rdmsr(v, msr, val); break; default: ret = 0; @@ -193,7 +198,7 @@ int vmce_rdmsr(uint32_t msr, uint64_t *v return ret; } -static int bank_mce_wrmsr(struct vcpu *v, u32 msr, u64 val) +static int bank_mce_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val) { int ret = 1; unsigned int bank = (msr - MSR_IA32_MC0_CTL) / 4; @@ -266,7 +271,10 @@ static int bank_mce_wrmsr(struct vcpu *v switch ( boot_cpu_data.x86_vendor ) { case X86_VENDOR_INTEL: - ret = intel_mce_wrmsr(v, msr, val); + ret = vmce_intel_wrmsr(v, msr, val); + break; + case X86_VENDOR_AMD: + ret = vmce_amd_wrmsr(v, msr, val); break; default: ret = 0; @@ -283,7 +291,7 @@ static int bank_mce_wrmsr(struct vcpu *v * = 0: Not handled, should be handled by other components * > 0: Success */ -int vmce_wrmsr(u32 msr, u64 val) +int vmce_wrmsr(uint32_t msr, uint64_t val) { struct vcpu *cur = current; struct bank_entry *entry = NULL; diff -r fc4140ec1d59 -r 77837828f6c3 xen/arch/x86/cpu/mcheck/vmce.h --- /dev/null +++ b/xen/arch/x86/cpu/mcheck/vmce.h @@ -0,0 +1,25 @@ +#ifndef _MCHECK_VMCE_H +#define _MCHECK_VMCE_H + +#include "x86_mca.h" + +int vmce_init(struct cpuinfo_x86 *c); + +#define dom0_vmce_enabled() (dom0 && dom0->max_vcpus && dom0->vcpu[0] \ + && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) + +int is_vmce_ready(struct mcinfo_bank *bank, struct domain *d); +int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn); + +int vmce_intel_rdmsr(const struct vcpu *, uint32_t msr, uint64_t *val); +int vmce_intel_wrmsr(struct vcpu *, uint32_t msr, uint64_t val); +int vmce_amd_rdmsr(const struct vcpu *, uint32_t msr, uint64_t *val); +int vmce_amd_wrmsr(struct vcpu *, uint32_t msr, uint64_t val); + +int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d, + uint64_t gstatus); +int inject_vmce(struct domain *d); +int vmce_domain_inject(struct mcinfo_bank *bank, struct domain *d, + struct mcinfo_global *global); + +#endif