ia64/xen-unstable
changeset 19428:cc60defe5b96
Implements Guest MCE# MSR read/write virtualization
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Ke, Liping <liping.ke@intel.com>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Ke, Liping <liping.ke@intel.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Fri Mar 20 17:24:53 2009 +0000 (2009-03-20) |
parents | c44c963ea162 |
children | 891af2c54155 |
files | xen/arch/x86/cpu/mcheck/mce_intel.c xen/arch/x86/traps.c xen/include/asm-x86/msr-index.h |
line diff
1.1 --- a/xen/arch/x86/cpu/mcheck/mce_intel.c Fri Mar 20 17:24:29 2009 +0000 1.2 +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Fri Mar 20 17:24:53 2009 +0000 1.3 @@ -812,3 +812,260 @@ int intel_mcheck_init(struct cpuinfo_x86 1.4 open_softirq(MACHINE_CHECK_SOFTIRQ, mce_softirq); 1.5 return 1; 1.6 } 1.7 + 1.8 +/* Guest vMCE# MSRs virtualization ops (rdmsr/wrmsr) */ 1.9 +int intel_mce_wrmsr(u32 msr, u32 lo, u32 hi) 1.10 +{ 1.11 + struct domain *d = current->domain; 1.12 + struct bank_entry *entry = NULL; 1.13 + uint64_t value = (u64)hi << 32 | lo; 1.14 + int ret = 0; 1.15 + 1.16 + spin_lock(&mce_locks); 1.17 + switch(msr) 1.18 + { 1.19 + case MSR_IA32_MCG_CTL: 1.20 + if (value != (u64)~0x0 && value != 0x0) { 1.21 + printk(KERN_ERR "MCE: value writen to MCG_CTL" 1.22 + "should be all 0s or 1s\n"); 1.23 + ret = -1; 1.24 + break; 1.25 + } 1.26 + if (!d || is_idle_domain(d)) { 1.27 + printk(KERN_ERR "MCE: wrmsr not in DOM context, skip\n"); 1.28 + break; 1.29 + } 1.30 + d->arch.vmca_msrs.mcg_ctl = value; 1.31 + break; 1.32 + case MSR_IA32_MCG_STATUS: 1.33 + if (!d || is_idle_domain(d)) { 1.34 + printk(KERN_ERR "MCE: wrmsr not in DOM context, skip\n"); 1.35 + break; 1.36 + } 1.37 + d->arch.vmca_msrs.mcg_status = value; 1.38 + printk(KERN_DEBUG "MCE: wrmsr MCG_CTL %lx\n", value); 1.39 + break; 1.40 + case MSR_IA32_MC0_CTL2: 1.41 + case MSR_IA32_MC1_CTL2: 1.42 + case MSR_IA32_MC2_CTL2: 1.43 + case MSR_IA32_MC3_CTL2: 1.44 + case MSR_IA32_MC4_CTL2: 1.45 + case MSR_IA32_MC5_CTL2: 1.46 + case MSR_IA32_MC6_CTL2: 1.47 + case MSR_IA32_MC7_CTL2: 1.48 + case MSR_IA32_MC8_CTL2: 1.49 + printk(KERN_ERR "We have disabled CMCI capability, " 1.50 + "Guest should not write this MSR!\n"); 1.51 + break; 1.52 + case MSR_IA32_MC0_CTL: 1.53 + case MSR_IA32_MC1_CTL: 1.54 + case MSR_IA32_MC2_CTL: 1.55 + case MSR_IA32_MC3_CTL: 1.56 + case MSR_IA32_MC4_CTL: 1.57 + case MSR_IA32_MC5_CTL: 1.58 + case MSR_IA32_MC6_CTL: 1.59 + case MSR_IA32_MC7_CTL: 1.60 + case MSR_IA32_MC8_CTL: 1.61 + if (value != (u64)~0x0 && value != 0x0) { 1.62 + printk(KERN_ERR "MCE: value writen to MCi_CTL" 1.63 + "should be all 0s or 1s\n"); 1.64 + ret = -1; 1.65 + break; 1.66 + } 1.67 + if (!d || is_idle_domain(d)) { 1.68 + printk(KERN_ERR "MCE: wrmsr not in DOM context, skip\n"); 1.69 + break; 1.70 + } 1.71 + d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4] = value; 1.72 + break; 1.73 + case MSR_IA32_MC0_STATUS: 1.74 + case MSR_IA32_MC1_STATUS: 1.75 + case MSR_IA32_MC2_STATUS: 1.76 + case MSR_IA32_MC3_STATUS: 1.77 + case MSR_IA32_MC4_STATUS: 1.78 + case MSR_IA32_MC5_STATUS: 1.79 + case MSR_IA32_MC6_STATUS: 1.80 + case MSR_IA32_MC7_STATUS: 1.81 + case MSR_IA32_MC8_STATUS: 1.82 + if (!d || is_idle_domain(d)) { 1.83 + /* Just skip */ 1.84 + printk(KERN_ERR "mce wrmsr: not in domain context!\n"); 1.85 + break; 1.86 + } 1.87 + /* Give the first entry of the list, it corresponds to current 1.88 + * vMCE# injection. When vMCE# is finished processing by the 1.89 + * the guest, this node will be deleted. 1.90 + * Only error bank is written. Non-error bank simply return. 1.91 + */ 1.92 + if ( !list_empty(&d->arch.vmca_msrs.impact_header) ) { 1.93 + entry = list_entry(d->arch.vmca_msrs.impact_header.next, 1.94 + struct bank_entry, list); 1.95 + if ( entry->bank == (msr - MSR_IA32_MC0_STATUS)/4 ) { 1.96 + entry->mci_status = value; 1.97 + } 1.98 + printk(KERN_DEBUG "MCE: wmrsr mci_status in vMCE# context\n"); 1.99 + } 1.100 + printk(KERN_DEBUG "MCE: wrmsr mci_status val:%lx\n", value); 1.101 + break; 1.102 + } 1.103 + spin_unlock(&mce_locks); 1.104 + return ret; 1.105 +} 1.106 + 1.107 +int intel_mce_rdmsr(u32 msr, u32 *lo, u32 *hi) 1.108 +{ 1.109 + struct domain *d = current->domain; 1.110 + int ret = 0; 1.111 + struct bank_entry *entry = NULL; 1.112 + 1.113 + *lo = *hi = 0x0; 1.114 + spin_lock(&mce_locks); 1.115 + switch(msr) 1.116 + { 1.117 + case MSR_IA32_MCG_STATUS: 1.118 + if (!d || is_idle_domain(d)) { 1.119 + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); 1.120 + *lo = *hi = 0x0; 1.121 + break; 1.122 + } 1.123 + *lo = (u32)d->arch.vmca_msrs.mcg_status; 1.124 + *hi = (u32)(d->arch.vmca_msrs.mcg_status >> 32); 1.125 + printk(KERN_DEBUG "MCE: rd MCG_STATUS lo %x hi %x\n", *lo, *hi); 1.126 + break; 1.127 + case MSR_IA32_MCG_CAP: 1.128 + if (!d || is_idle_domain(d)) { 1.129 + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); 1.130 + *lo = *hi = 0x0; 1.131 + break; 1.132 + } 1.133 + *lo = (u32)d->arch.vmca_msrs.mcg_cap; 1.134 + *hi = (u32)(d->arch.vmca_msrs.mcg_cap >> 32); 1.135 + printk(KERN_DEBUG "MCE: rdmsr MCG_CAP lo %x hi %x\n", *lo, *hi); 1.136 + break; 1.137 + case MSR_IA32_MCG_CTL: 1.138 + if (!d || is_idle_domain(d)) { 1.139 + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); 1.140 + *lo = *hi = 0x0; 1.141 + break; 1.142 + } 1.143 + *lo = (u32)d->arch.vmca_msrs.mcg_ctl; 1.144 + *hi = (u32)(d->arch.vmca_msrs.mcg_ctl >> 32); 1.145 + printk(KERN_DEBUG "MCE: rdmsr MCG_CTL lo %x hi %x\n", *lo, *hi); 1.146 + break; 1.147 + case MSR_IA32_MC0_CTL2: 1.148 + case MSR_IA32_MC1_CTL2: 1.149 + case MSR_IA32_MC2_CTL2: 1.150 + case MSR_IA32_MC3_CTL2: 1.151 + case MSR_IA32_MC4_CTL2: 1.152 + case MSR_IA32_MC5_CTL2: 1.153 + case MSR_IA32_MC6_CTL2: 1.154 + case MSR_IA32_MC7_CTL2: 1.155 + case MSR_IA32_MC8_CTL2: 1.156 + printk(KERN_WARNING "We have disabled CMCI capability, " 1.157 + "Guest should not read this MSR!\n"); 1.158 + break; 1.159 + case MSR_IA32_MC0_CTL: 1.160 + case MSR_IA32_MC1_CTL: 1.161 + case MSR_IA32_MC2_CTL: 1.162 + case MSR_IA32_MC3_CTL: 1.163 + case MSR_IA32_MC4_CTL: 1.164 + case MSR_IA32_MC5_CTL: 1.165 + case MSR_IA32_MC6_CTL: 1.166 + case MSR_IA32_MC7_CTL: 1.167 + case MSR_IA32_MC8_CTL: 1.168 + if (!d || is_idle_domain(d)) { 1.169 + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); 1.170 + *lo = *hi = 0x0; 1.171 + break; 1.172 + } 1.173 + *lo = (u32)d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4]; 1.174 + *hi = 1.175 + (u32)(d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4] 1.176 + >> 32); 1.177 + printk(KERN_DEBUG "MCE: rdmsr MCi_CTL lo %x hi %x\n", *lo, *hi); 1.178 + break; 1.179 + case MSR_IA32_MC0_STATUS: 1.180 + case MSR_IA32_MC1_STATUS: 1.181 + case MSR_IA32_MC2_STATUS: 1.182 + case MSR_IA32_MC3_STATUS: 1.183 + case MSR_IA32_MC4_STATUS: 1.184 + case MSR_IA32_MC5_STATUS: 1.185 + case MSR_IA32_MC6_STATUS: 1.186 + case MSR_IA32_MC7_STATUS: 1.187 + case MSR_IA32_MC8_STATUS: 1.188 + /* Only error bank is read. Non-error bank simply return */ 1.189 + *lo = *hi = 0x0; 1.190 + printk(KERN_DEBUG "MCE: rdmsr mci_status\n"); 1.191 + if (!d || is_idle_domain(d)) { 1.192 + printk(KERN_ERR "mce_rdmsr: not in domain context!\n"); 1.193 + break; 1.194 + } 1.195 + if (!list_empty(&d->arch.vmca_msrs.impact_header)) { 1.196 + entry = list_entry(d->arch.vmca_msrs.impact_header.next, 1.197 + struct bank_entry, list); 1.198 + if ( entry->bank == (msr - MSR_IA32_MC0_STATUS)/4 ) { 1.199 + *lo = entry->mci_status; 1.200 + *hi = entry->mci_status >> 32; 1.201 + printk(KERN_DEBUG "MCE: rdmsr MCi_STATUS in vmCE# context " 1.202 + "lo %x hi %x\n", *lo, *hi); 1.203 + } 1.204 + } 1.205 + break; 1.206 + case MSR_IA32_MC0_ADDR: 1.207 + case MSR_IA32_MC1_ADDR: 1.208 + case MSR_IA32_MC2_ADDR: 1.209 + case MSR_IA32_MC3_ADDR: 1.210 + case MSR_IA32_MC4_ADDR: 1.211 + case MSR_IA32_MC5_ADDR: 1.212 + case MSR_IA32_MC6_ADDR: 1.213 + case MSR_IA32_MC7_ADDR: 1.214 + case MSR_IA32_MC8_ADDR: 1.215 + *lo = *hi = 0x0; 1.216 + if (!d || is_idle_domain(d)) { 1.217 + printk(KERN_ERR "mce_rdmsr: not in domain context!\n"); 1.218 + break; 1.219 + } 1.220 + if (!list_empty(&d->arch.vmca_msrs.impact_header)) { 1.221 + entry = list_entry(d->arch.vmca_msrs.impact_header.next, 1.222 + struct bank_entry, list); 1.223 + if ( entry->bank == (msr - MSR_IA32_MC0_ADDR)/4 ) { 1.224 + *lo = entry->mci_addr; 1.225 + *hi = entry->mci_addr >> 32; 1.226 + printk(KERN_DEBUG "MCE: rdmsr MCi_ADDR in vMCE# context " 1.227 + "lo %x hi %x\n", *lo, *hi); 1.228 + } 1.229 + } 1.230 + break; 1.231 + case MSR_IA32_MC0_MISC: 1.232 + case MSR_IA32_MC1_MISC: 1.233 + case MSR_IA32_MC2_MISC: 1.234 + case MSR_IA32_MC3_MISC: 1.235 + case MSR_IA32_MC4_MISC: 1.236 + case MSR_IA32_MC5_MISC: 1.237 + case MSR_IA32_MC6_MISC: 1.238 + case MSR_IA32_MC7_MISC: 1.239 + case MSR_IA32_MC8_MISC: 1.240 + *lo = *hi = 0x0; 1.241 + if (!d || is_idle_domain(d)) { 1.242 + printk(KERN_ERR "MCE: rdmsr not in domain context!\n"); 1.243 + break; 1.244 + } 1.245 + if (!list_empty(&d->arch.vmca_msrs.impact_header)) { 1.246 + entry = list_entry(d->arch.vmca_msrs.impact_header.next, 1.247 + struct bank_entry, list); 1.248 + if ( entry->bank == (msr - MSR_IA32_MC0_MISC)/4 ) { 1.249 + *lo = entry->mci_misc; 1.250 + *hi = entry->mci_misc >> 32; 1.251 + printk(KERN_DEBUG "MCE: rdmsr MCi_MISC in vMCE# context " 1.252 + " lo %x hi %x\n", *lo, *hi); 1.253 + } 1.254 + } 1.255 + break; 1.256 + default: 1.257 + break; 1.258 + } 1.259 + spin_unlock(&mce_locks); 1.260 + return ret; 1.261 +} 1.262 + 1.263 +
2.1 --- a/xen/arch/x86/traps.c Fri Mar 20 17:24:29 2009 +0000 2.2 +++ b/xen/arch/x86/traps.c Fri Mar 20 17:24:53 2009 +0000 2.3 @@ -728,8 +728,6 @@ static void pv_cpuid(struct cpu_user_reg 2.4 if ( !opt_allow_hugepage ) 2.5 __clear_bit(X86_FEATURE_PSE, &d); 2.6 __clear_bit(X86_FEATURE_PGE, &d); 2.7 - __clear_bit(X86_FEATURE_MCE, &d); 2.8 - __clear_bit(X86_FEATURE_MCA, &d); 2.9 __clear_bit(X86_FEATURE_PSE36, &d); 2.10 } 2.11 switch ( (uint32_t)regs->eax ) 2.12 @@ -1639,6 +1637,10 @@ static int is_cpufreq_controller(struct 2.13 (d->domain_id == 0)); 2.14 } 2.15 2.16 +/*Intel vMCE MSRs virtualization*/ 2.17 +extern int intel_mce_wrmsr(u32 msr, u32 lo, u32 hi); 2.18 +extern int intel_mce_rdmsr(u32 msr, u32 *lo, u32 *hi); 2.19 + 2.20 static int emulate_privileged_op(struct cpu_user_regs *regs) 2.21 { 2.22 struct vcpu *v = current; 2.23 @@ -2206,6 +2208,15 @@ static int emulate_privileged_op(struct 2.24 default: 2.25 if ( wrmsr_hypervisor_regs(regs->ecx, eax, edx) ) 2.26 break; 2.27 + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { 2.28 + if ( intel_mce_wrmsr(regs->ecx, eax, edx) != 0) { 2.29 + gdprintk(XENLOG_ERR, "MCE: vMCE MSRS(%lx) Write" 2.30 + " (%x:%x) Fails! ", regs->ecx, edx, eax); 2.31 + goto fail; 2.32 + } 2.33 + break; 2.34 + } 2.35 + 2.36 if ( (rdmsr_safe(regs->ecx, l, h) != 0) || 2.37 (eax != l) || (edx != h) ) 2.38 invalid: 2.39 @@ -2289,6 +2300,12 @@ static int emulate_privileged_op(struct 2.40 _p(regs->ecx));*/ 2.41 if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) ) 2.42 goto fail; 2.43 + 2.44 + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { 2.45 + if ( intel_mce_rdmsr(regs->ecx, &eax, &edx) != 0) 2.46 + printk(KERN_ERR "MCE: Not MCE MSRs %lx\n", regs->ecx); 2.47 + } 2.48 + 2.49 break; 2.50 } 2.51 break;
3.1 --- a/xen/include/asm-x86/msr-index.h Fri Mar 20 17:24:29 2009 +0000 3.2 +++ b/xen/include/asm-x86/msr-index.h Fri Mar 20 17:24:53 2009 +0000 3.3 @@ -96,30 +96,54 @@ 3.4 #define CMCI_EN (1UL<<30) 3.5 #define CMCI_THRESHOLD_MASK 0x7FFF 3.6 3.7 +#define MSR_IA32_MC1_CTL 0x00000404 3.8 +#define MSR_IA32_MC1_CTL2 0x00000281 3.9 #define MSR_IA32_MC1_STATUS 0x00000405 3.10 #define MSR_IA32_MC1_ADDR 0x00000406 3.11 #define MSR_IA32_MC1_MISC 0x00000407 3.12 3.13 #define MSR_IA32_MC2_CTL 0x00000408 3.14 +#define MSR_IA32_MC2_CTL2 0x00000282 3.15 #define MSR_IA32_MC2_STATUS 0x00000409 3.16 #define MSR_IA32_MC2_ADDR 0x0000040A 3.17 #define MSR_IA32_MC2_MISC 0x0000040B 3.18 3.19 +#define MSR_IA32_MC3_CTL2 0x00000283 3.20 #define MSR_IA32_MC3_CTL 0x0000040C 3.21 #define MSR_IA32_MC3_STATUS 0x0000040D 3.22 #define MSR_IA32_MC3_ADDR 0x0000040E 3.23 #define MSR_IA32_MC3_MISC 0x0000040F 3.24 3.25 +#define MSR_IA32_MC4_CTL2 0x00000284 3.26 #define MSR_IA32_MC4_CTL 0x00000410 3.27 #define MSR_IA32_MC4_STATUS 0x00000411 3.28 #define MSR_IA32_MC4_ADDR 0x00000412 3.29 #define MSR_IA32_MC4_MISC 0x00000413 3.30 3.31 +#define MSR_IA32_MC5_CTL2 0x00000285 3.32 #define MSR_IA32_MC5_CTL 0x00000414 3.33 #define MSR_IA32_MC5_STATUS 0x00000415 3.34 #define MSR_IA32_MC5_ADDR 0x00000416 3.35 #define MSR_IA32_MC5_MISC 0x00000417 3.36 3.37 +#define MSR_IA32_MC6_CTL2 0x00000286 3.38 +#define MSR_IA32_MC6_CTL 0x00000418 3.39 +#define MSR_IA32_MC6_STATUS 0x00000419 3.40 +#define MSR_IA32_MC6_ADDR 0x0000041A 3.41 +#define MSR_IA32_MC6_MISC 0x0000041B 3.42 + 3.43 +#define MSR_IA32_MC7_CTL2 0x00000287 3.44 +#define MSR_IA32_MC7_CTL 0x0000041C 3.45 +#define MSR_IA32_MC7_STATUS 0x0000041D 3.46 +#define MSR_IA32_MC7_ADDR 0x0000041E 3.47 +#define MSR_IA32_MC7_MISC 0x0000041F 3.48 + 3.49 +#define MSR_IA32_MC8_CTL2 0x00000288 3.50 +#define MSR_IA32_MC8_CTL 0x00000420 3.51 +#define MSR_IA32_MC8_STATUS 0x00000421 3.52 +#define MSR_IA32_MC8_ADDR 0x00000422 3.53 +#define MSR_IA32_MC8_MISC 0x00000423 3.54 + 3.55 #define MSR_P6_PERFCTR0 0x000000c1 3.56 #define MSR_P6_PERFCTR1 0x000000c2 3.57 #define MSR_P6_EVNTSEL0 0x00000186