[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Implements Guest MCE# MSR read/write virtualization
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1237569893 0 # Node ID cc60defe5b9697ab0e068caa4fd1f8798bfe5104 # Parent c44c963ea1625314aef37487f0bc9e0924f39614 Implements Guest MCE# MSR read/write virtualization Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx> Signed-off-by: Ke, Liping <liping.ke@xxxxxxxxx> --- xen/arch/x86/cpu/mcheck/mce_intel.c | 257 ++++++++++++++++++++++++++++++++++++ xen/arch/x86/traps.c | 21 ++ xen/include/asm-x86/msr-index.h | 24 +++ 3 files changed, 300 insertions(+), 2 deletions(-) diff -r c44c963ea162 -r cc60defe5b96 xen/arch/x86/cpu/mcheck/mce_intel.c --- a/xen/arch/x86/cpu/mcheck/mce_intel.c Fri Mar 20 17:24:29 2009 +0000 +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Fri Mar 20 17:24:53 2009 +0000 @@ -812,3 +812,260 @@ int intel_mcheck_init(struct cpuinfo_x86 open_softirq(MACHINE_CHECK_SOFTIRQ, mce_softirq); return 1; } + +/* Guest vMCE# MSRs virtualization ops (rdmsr/wrmsr) */ +int intel_mce_wrmsr(u32 msr, u32 lo, u32 hi) +{ + struct domain *d = current->domain; + struct bank_entry *entry = NULL; + uint64_t value = (u64)hi << 32 | lo; + int ret = 0; + + spin_lock(&mce_locks); + switch(msr) + { + case MSR_IA32_MCG_CTL: + if (value != (u64)~0x0 && value != 0x0) { + printk(KERN_ERR "MCE: value writen to MCG_CTL" + "should be all 0s or 1s\n"); + ret = -1; + break; + } + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: wrmsr not in DOM context, skip\n"); + break; + } + d->arch.vmca_msrs.mcg_ctl = value; + break; + case MSR_IA32_MCG_STATUS: + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: wrmsr not in DOM context, skip\n"); + break; + } + d->arch.vmca_msrs.mcg_status = value; + printk(KERN_DEBUG "MCE: wrmsr MCG_CTL %lx\n", value); + break; + case MSR_IA32_MC0_CTL2: + case MSR_IA32_MC1_CTL2: + case MSR_IA32_MC2_CTL2: + case MSR_IA32_MC3_CTL2: + case MSR_IA32_MC4_CTL2: + case MSR_IA32_MC5_CTL2: + case MSR_IA32_MC6_CTL2: + case MSR_IA32_MC7_CTL2: + case MSR_IA32_MC8_CTL2: + printk(KERN_ERR "We have disabled CMCI capability, " + "Guest should not write this MSR!\n"); + break; + case MSR_IA32_MC0_CTL: + case MSR_IA32_MC1_CTL: + case MSR_IA32_MC2_CTL: + case MSR_IA32_MC3_CTL: + case MSR_IA32_MC4_CTL: + case MSR_IA32_MC5_CTL: + case MSR_IA32_MC6_CTL: + case MSR_IA32_MC7_CTL: + case MSR_IA32_MC8_CTL: + if (value != (u64)~0x0 && value != 0x0) { + printk(KERN_ERR "MCE: value writen to MCi_CTL" + "should be all 0s or 1s\n"); + ret = -1; + break; + } + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: wrmsr not in DOM context, skip\n"); + break; + } + d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4] = value; + break; + case MSR_IA32_MC0_STATUS: + case MSR_IA32_MC1_STATUS: + case MSR_IA32_MC2_STATUS: + case MSR_IA32_MC3_STATUS: + case MSR_IA32_MC4_STATUS: + case MSR_IA32_MC5_STATUS: + case MSR_IA32_MC6_STATUS: + case MSR_IA32_MC7_STATUS: + case MSR_IA32_MC8_STATUS: + if (!d || is_idle_domain(d)) { + /* Just skip */ + printk(KERN_ERR "mce wrmsr: not in domain context!\n"); + break; + } + /* Give the first entry of the list, it corresponds to current + * vMCE# injection. When vMCE# is finished processing by the + * the guest, this node will be deleted. + * Only error bank is written. Non-error bank simply return. + */ + if ( !list_empty(&d->arch.vmca_msrs.impact_header) ) { + entry = list_entry(d->arch.vmca_msrs.impact_header.next, + struct bank_entry, list); + if ( entry->bank == (msr - MSR_IA32_MC0_STATUS)/4 ) { + entry->mci_status = value; + } + printk(KERN_DEBUG "MCE: wmrsr mci_status in vMCE# context\n"); + } + printk(KERN_DEBUG "MCE: wrmsr mci_status val:%lx\n", value); + break; + } + spin_unlock(&mce_locks); + return ret; +} + +int intel_mce_rdmsr(u32 msr, u32 *lo, u32 *hi) +{ + struct domain *d = current->domain; + int ret = 0; + struct bank_entry *entry = NULL; + + *lo = *hi = 0x0; + spin_lock(&mce_locks); + switch(msr) + { + case MSR_IA32_MCG_STATUS: + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); + *lo = *hi = 0x0; + break; + } + *lo = (u32)d->arch.vmca_msrs.mcg_status; + *hi = (u32)(d->arch.vmca_msrs.mcg_status >> 32); + printk(KERN_DEBUG "MCE: rd MCG_STATUS lo %x hi %x\n", *lo, *hi); + break; + case MSR_IA32_MCG_CAP: + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); + *lo = *hi = 0x0; + break; + } + *lo = (u32)d->arch.vmca_msrs.mcg_cap; + *hi = (u32)(d->arch.vmca_msrs.mcg_cap >> 32); + printk(KERN_DEBUG "MCE: rdmsr MCG_CAP lo %x hi %x\n", *lo, *hi); + break; + case MSR_IA32_MCG_CTL: + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); + *lo = *hi = 0x0; + break; + } + *lo = (u32)d->arch.vmca_msrs.mcg_ctl; + *hi = (u32)(d->arch.vmca_msrs.mcg_ctl >> 32); + printk(KERN_DEBUG "MCE: rdmsr MCG_CTL lo %x hi %x\n", *lo, *hi); + break; + case MSR_IA32_MC0_CTL2: + case MSR_IA32_MC1_CTL2: + case MSR_IA32_MC2_CTL2: + case MSR_IA32_MC3_CTL2: + case MSR_IA32_MC4_CTL2: + case MSR_IA32_MC5_CTL2: + case MSR_IA32_MC6_CTL2: + case MSR_IA32_MC7_CTL2: + case MSR_IA32_MC8_CTL2: + printk(KERN_WARNING "We have disabled CMCI capability, " + "Guest should not read this MSR!\n"); + break; + case MSR_IA32_MC0_CTL: + case MSR_IA32_MC1_CTL: + case MSR_IA32_MC2_CTL: + case MSR_IA32_MC3_CTL: + case MSR_IA32_MC4_CTL: + case MSR_IA32_MC5_CTL: + case MSR_IA32_MC6_CTL: + case MSR_IA32_MC7_CTL: + case MSR_IA32_MC8_CTL: + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); + *lo = *hi = 0x0; + break; + } + *lo = (u32)d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4]; + *hi = + (u32)(d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4] + >> 32); + printk(KERN_DEBUG "MCE: rdmsr MCi_CTL lo %x hi %x\n", *lo, *hi); + break; + case MSR_IA32_MC0_STATUS: + case MSR_IA32_MC1_STATUS: + case MSR_IA32_MC2_STATUS: + case MSR_IA32_MC3_STATUS: + case MSR_IA32_MC4_STATUS: + case MSR_IA32_MC5_STATUS: + case MSR_IA32_MC6_STATUS: + case MSR_IA32_MC7_STATUS: + case MSR_IA32_MC8_STATUS: + /* Only error bank is read. Non-error bank simply return */ + *lo = *hi = 0x0; + printk(KERN_DEBUG "MCE: rdmsr mci_status\n"); + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "mce_rdmsr: not in domain context!\n"); + break; + } + if (!list_empty(&d->arch.vmca_msrs.impact_header)) { + entry = list_entry(d->arch.vmca_msrs.impact_header.next, + struct bank_entry, list); + if ( entry->bank == (msr - MSR_IA32_MC0_STATUS)/4 ) { + *lo = entry->mci_status; + *hi = entry->mci_status >> 32; + printk(KERN_DEBUG "MCE: rdmsr MCi_STATUS in vmCE# context " + "lo %x hi %x\n", *lo, *hi); + } + } + break; + case MSR_IA32_MC0_ADDR: + case MSR_IA32_MC1_ADDR: + case MSR_IA32_MC2_ADDR: + case MSR_IA32_MC3_ADDR: + case MSR_IA32_MC4_ADDR: + case MSR_IA32_MC5_ADDR: + case MSR_IA32_MC6_ADDR: + case MSR_IA32_MC7_ADDR: + case MSR_IA32_MC8_ADDR: + *lo = *hi = 0x0; + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "mce_rdmsr: not in domain context!\n"); + break; + } + if (!list_empty(&d->arch.vmca_msrs.impact_header)) { + entry = list_entry(d->arch.vmca_msrs.impact_header.next, + struct bank_entry, list); + if ( entry->bank == (msr - MSR_IA32_MC0_ADDR)/4 ) { + *lo = entry->mci_addr; + *hi = entry->mci_addr >> 32; + printk(KERN_DEBUG "MCE: rdmsr MCi_ADDR in vMCE# context " + "lo %x hi %x\n", *lo, *hi); + } + } + break; + case MSR_IA32_MC0_MISC: + case MSR_IA32_MC1_MISC: + case MSR_IA32_MC2_MISC: + case MSR_IA32_MC3_MISC: + case MSR_IA32_MC4_MISC: + case MSR_IA32_MC5_MISC: + case MSR_IA32_MC6_MISC: + case MSR_IA32_MC7_MISC: + case MSR_IA32_MC8_MISC: + *lo = *hi = 0x0; + if (!d || is_idle_domain(d)) { + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); + break; + } + if (!list_empty(&d->arch.vmca_msrs.impact_header)) { + entry = list_entry(d->arch.vmca_msrs.impact_header.next, + struct bank_entry, list); + if ( entry->bank == (msr - MSR_IA32_MC0_MISC)/4 ) { + *lo = entry->mci_misc; + *hi = entry->mci_misc >> 32; + printk(KERN_DEBUG "MCE: rdmsr MCi_MISC in vMCE# context " + " lo %x hi %x\n", *lo, *hi); + } + } + break; + default: + break; + } + spin_unlock(&mce_locks); + return ret; +} + + diff -r c44c963ea162 -r cc60defe5b96 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Fri Mar 20 17:24:29 2009 +0000 +++ b/xen/arch/x86/traps.c Fri Mar 20 17:24:53 2009 +0000 @@ -728,8 +728,6 @@ static void pv_cpuid(struct cpu_user_reg if ( !opt_allow_hugepage ) __clear_bit(X86_FEATURE_PSE, &d); __clear_bit(X86_FEATURE_PGE, &d); - __clear_bit(X86_FEATURE_MCE, &d); - __clear_bit(X86_FEATURE_MCA, &d); __clear_bit(X86_FEATURE_PSE36, &d); } switch ( (uint32_t)regs->eax ) @@ -1638,6 +1636,10 @@ static int is_cpufreq_controller(struct return ((cpufreq_controller == FREQCTL_dom0_kernel) && (d->domain_id == 0)); } + +/*Intel vMCE MSRs virtualization*/ +extern int intel_mce_wrmsr(u32 msr, u32 lo, u32 hi); +extern int intel_mce_rdmsr(u32 msr, u32 *lo, u32 *hi); static int emulate_privileged_op(struct cpu_user_regs *regs) { @@ -2206,6 +2208,15 @@ static int emulate_privileged_op(struct default: if ( wrmsr_hypervisor_regs(regs->ecx, eax, edx) ) break; + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { + if ( intel_mce_wrmsr(regs->ecx, eax, edx) != 0) { + gdprintk(XENLOG_ERR, "MCE: vMCE MSRS(%lx) Write" + " (%x:%x) Fails! ", regs->ecx, edx, eax); + goto fail; + } + break; + } + if ( (rdmsr_safe(regs->ecx, l, h) != 0) || (eax != l) || (edx != h) ) invalid: @@ -2289,6 +2300,12 @@ static int emulate_privileged_op(struct _p(regs->ecx));*/ if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) ) goto fail; + + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { + if ( intel_mce_rdmsr(regs->ecx, &eax, &edx) != 0) + printk(KERN_ERR "MCE: Not MCE MSRs %lx\n", regs->ecx); + } + break; } break; diff -r c44c963ea162 -r cc60defe5b96 xen/include/asm-x86/msr-index.h --- a/xen/include/asm-x86/msr-index.h Fri Mar 20 17:24:29 2009 +0000 +++ b/xen/include/asm-x86/msr-index.h Fri Mar 20 17:24:53 2009 +0000 @@ -96,29 +96,53 @@ #define CMCI_EN (1UL<<30) #define CMCI_THRESHOLD_MASK 0x7FFF +#define MSR_IA32_MC1_CTL 0x00000404 +#define MSR_IA32_MC1_CTL2 0x00000281 #define MSR_IA32_MC1_STATUS 0x00000405 #define MSR_IA32_MC1_ADDR 0x00000406 #define MSR_IA32_MC1_MISC 0x00000407 #define MSR_IA32_MC2_CTL 0x00000408 +#define MSR_IA32_MC2_CTL2 0x00000282 #define MSR_IA32_MC2_STATUS 0x00000409 #define MSR_IA32_MC2_ADDR 0x0000040A #define MSR_IA32_MC2_MISC 0x0000040B +#define MSR_IA32_MC3_CTL2 0x00000283 #define MSR_IA32_MC3_CTL 0x0000040C #define MSR_IA32_MC3_STATUS 0x0000040D #define MSR_IA32_MC3_ADDR 0x0000040E #define MSR_IA32_MC3_MISC 0x0000040F +#define MSR_IA32_MC4_CTL2 0x00000284 #define MSR_IA32_MC4_CTL 0x00000410 #define MSR_IA32_MC4_STATUS 0x00000411 #define MSR_IA32_MC4_ADDR 0x00000412 #define MSR_IA32_MC4_MISC 0x00000413 +#define MSR_IA32_MC5_CTL2 0x00000285 #define MSR_IA32_MC5_CTL 0x00000414 #define MSR_IA32_MC5_STATUS 0x00000415 #define MSR_IA32_MC5_ADDR 0x00000416 #define MSR_IA32_MC5_MISC 0x00000417 + +#define MSR_IA32_MC6_CTL2 0x00000286 +#define MSR_IA32_MC6_CTL 0x00000418 +#define MSR_IA32_MC6_STATUS 0x00000419 +#define MSR_IA32_MC6_ADDR 0x0000041A +#define MSR_IA32_MC6_MISC 0x0000041B + +#define MSR_IA32_MC7_CTL2 0x00000287 +#define MSR_IA32_MC7_CTL 0x0000041C +#define MSR_IA32_MC7_STATUS 0x0000041D +#define MSR_IA32_MC7_ADDR 0x0000041E +#define MSR_IA32_MC7_MISC 0x0000041F + +#define MSR_IA32_MC8_CTL2 0x00000288 +#define MSR_IA32_MC8_CTL 0x00000420 +#define MSR_IA32_MC8_STATUS 0x00000421 +#define MSR_IA32_MC8_ADDR 0x00000422 +#define MSR_IA32_MC8_MISC 0x00000423 #define MSR_P6_PERFCTR0 0x000000c1 #define MSR_P6_PERFCTR1 0x000000c2 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |