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>
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