ia64/xen-unstable

changeset 19469:f9501b0bcc1b

x86 mce: fix and clean up c/s 19423

- fix inverted return value check for intel_mce_{rd,wr}msr()
- fix broken initialization of d->arch.vmca_msrs.mci_ctl
- remove pointless (!d || is_idle_domain(d)) checks
- eliminate hard-coded limit to 9 banks
- avoid redundant gdprintk()s

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 31 13:17:48 2009 +0100 (2009-03-31)
parents cc4a2290c224
children 156093ff8067
files xen/arch/x86/cpu/mcheck/mce_intel.c xen/arch/x86/domain.c xen/arch/x86/traps.c xen/include/asm-x86/traps.h
line diff
     1.1 --- a/xen/arch/x86/cpu/mcheck/mce_intel.c	Tue Mar 31 13:14:10 2009 +0100
     1.2 +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c	Tue Mar 31 13:17:48 2009 +0100
     1.3 @@ -742,7 +742,7 @@ void mce_intel_feature_init(struct cpuin
     1.4      intel_init_cmci(c);
     1.5  }
     1.6  
     1.7 -uint64_t g_mcg_cap;
     1.8 +static uint64_t g_mcg_cap;
     1.9  static void mce_cap_init(struct cpuinfo_x86 *c)
    1.10  {
    1.11      u32 l, h;
    1.12 @@ -754,9 +754,12 @@ static void mce_cap_init(struct cpuinfo_
    1.13      if ((l & MCG_CMCI_P) && cpu_has_apic)
    1.14          cmci_support = 1;
    1.15  
    1.16 -    nr_mce_banks = l & 0xff;
    1.17 +    nr_mce_banks = l & MCG_CAP_COUNT;
    1.18      if (nr_mce_banks > MAX_NR_BANKS)
    1.19 +    {
    1.20          printk(KERN_WARNING "MCE: exceed max mce banks\n");
    1.21 +        g_mcg_cap = (g_mcg_cap & ~MCG_CAP_COUNT) | MAX_NR_BANKS;
    1.22 +    }
    1.23      if (l & MCG_EXT_P)
    1.24      {
    1.25          nr_intel_ext_msrs = (l >> MCG_EXT_CNT) & 0xff;
    1.26 @@ -828,11 +831,22 @@ int intel_mcheck_init(struct cpuinfo_x86
    1.27  }
    1.28  
    1.29  /* Guest vMCE# MSRs virtualization ops (rdmsr/wrmsr) */
    1.30 -int intel_mce_wrmsr(u32 msr, u32 lo, u32 hi)
    1.31 +void intel_mce_init_msr(struct domain *d)
    1.32 +{
    1.33 +    d->arch.vmca_msrs.mcg_status = 0x0;
    1.34 +    d->arch.vmca_msrs.mcg_cap = g_mcg_cap;
    1.35 +    d->arch.vmca_msrs.mcg_ctl = (uint64_t)~0x0;
    1.36 +    d->arch.vmca_msrs.nr_injection = 0;
    1.37 +    memset(d->arch.vmca_msrs.mci_ctl, ~0,
    1.38 +           sizeof(d->arch.vmca_msrs.mci_ctl));
    1.39 +    INIT_LIST_HEAD(&d->arch.vmca_msrs.impact_header);
    1.40 +}
    1.41 +
    1.42 +int intel_mce_wrmsr(u32 msr, u64 value)
    1.43  {
    1.44      struct domain *d = current->domain;
    1.45      struct bank_entry *entry = NULL;
    1.46 -    uint64_t value = (u64)hi << 32 | lo;
    1.47 +    unsigned int bank;
    1.48      int ret = 1;
    1.49  
    1.50      spin_lock(&mce_locks);
    1.51 @@ -840,86 +854,71 @@ int intel_mce_wrmsr(u32 msr, u32 lo, u32
    1.52      {
    1.53      case MSR_IA32_MCG_CTL:
    1.54          if (value != (u64)~0x0 && value != 0x0) {
    1.55 -            gdprintk(XENLOG_WARNING, "MCE: value writen to MCG_CTL"
    1.56 +            gdprintk(XENLOG_WARNING, "MCE: value written to MCG_CTL"
    1.57                       "should be all 0s or 1s\n");
    1.58              ret = -1;
    1.59              break;
    1.60          }
    1.61 -        if (!d || is_idle_domain(d)) {
    1.62 -            gdprintk(XENLOG_WARNING, "MCE: wrmsr not in DOM context, skip\n");
    1.63 -            break;
    1.64 -        }
    1.65          d->arch.vmca_msrs.mcg_ctl = value;
    1.66          break;
    1.67      case MSR_IA32_MCG_STATUS:
    1.68 -        if (!d || is_idle_domain(d)) {
    1.69 -            gdprintk(XENLOG_WARNING, "MCE: wrmsr not in DOM context, skip\n");
    1.70 -            break;
    1.71 -        }
    1.72          d->arch.vmca_msrs.mcg_status = value;
    1.73          gdprintk(XENLOG_DEBUG, "MCE: wrmsr MCG_CTL %"PRIx64"\n", value);
    1.74          break;
    1.75 -    case MSR_IA32_MC0_CTL2:
    1.76 -    case MSR_IA32_MC1_CTL2:
    1.77 -    case MSR_IA32_MC2_CTL2:
    1.78 -    case MSR_IA32_MC3_CTL2:
    1.79 -    case MSR_IA32_MC4_CTL2:
    1.80 -    case MSR_IA32_MC5_CTL2:
    1.81 -    case MSR_IA32_MC6_CTL2:
    1.82 -    case MSR_IA32_MC7_CTL2:
    1.83 -    case MSR_IA32_MC8_CTL2:
    1.84 +    case MSR_IA32_MCG_CAP:
    1.85 +        gdprintk(XENLOG_WARNING, "MCE: MCG_CAP is read-only\n");
    1.86 +        ret = -1;
    1.87 +        break;
    1.88 +    case MSR_IA32_MC0_CTL2 ... MSR_IA32_MC0_CTL2 + MAX_NR_BANKS - 1:
    1.89          gdprintk(XENLOG_WARNING, "We have disabled CMCI capability, "
    1.90                   "Guest should not write this MSR!\n");
    1.91          break;
    1.92 -    case MSR_IA32_MC0_CTL:
    1.93 -    case MSR_IA32_MC1_CTL:
    1.94 -    case MSR_IA32_MC2_CTL:
    1.95 -    case MSR_IA32_MC3_CTL:
    1.96 -    case MSR_IA32_MC4_CTL:
    1.97 -    case MSR_IA32_MC5_CTL:
    1.98 -    case MSR_IA32_MC6_CTL:
    1.99 -    case MSR_IA32_MC7_CTL:
   1.100 -    case MSR_IA32_MC8_CTL:
   1.101 -        if (value != (u64)~0x0 && value != 0x0) {
   1.102 -            gdprintk(XENLOG_WARNING, "MCE: value writen to MCi_CTL"
   1.103 -                     "should be all 0s or 1s\n");
   1.104 +    case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * MAX_NR_BANKS - 1:
   1.105 +        bank = (msr - MSR_IA32_MC0_CTL) / 4;
   1.106 +        if (bank >= (d->arch.vmca_msrs.mcg_cap & MCG_CAP_COUNT)) {
   1.107 +            gdprintk(XENLOG_WARNING, "MCE: bank %u does not exist\n", bank);
   1.108              ret = -1;
   1.109              break;
   1.110          }
   1.111 -        if (!d || is_idle_domain(d)) {
   1.112 -            gdprintk(XENLOG_WARNING, "MCE: wrmsr not in DOM context, skip\n");
   1.113 +        switch (msr & (MSR_IA32_MC0_CTL | 3))
   1.114 +        {
   1.115 +        case MSR_IA32_MC0_CTL:
   1.116 +            if (value != (u64)~0x0 && value != 0x0) {
   1.117 +                gdprintk(XENLOG_WARNING, "MCE: value written to MC%u_CTL"
   1.118 +                         "should be all 0s or 1s (is %"PRIx64")\n",
   1.119 +                         bank, value);
   1.120 +                ret = -1;
   1.121 +                break;
   1.122 +            }
   1.123 +            d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4] = value;
   1.124 +            break;
   1.125 +        case MSR_IA32_MC0_STATUS:
   1.126 +            /* Give the first entry of the list, it corresponds to current
   1.127 +             * vMCE# injection. When vMCE# is finished processing by the
   1.128 +             * the guest, this node will be deleted.
   1.129 +             * Only error bank is written. Non-error banks simply return.
   1.130 +             */
   1.131 +            if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.132 +                entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.133 +                                   struct bank_entry, list);
   1.134 +                if ( entry->bank == bank )
   1.135 +                    entry->mci_status = value;
   1.136 +                gdprintk(XENLOG_DEBUG,
   1.137 +                         "MCE: wr MC%u_STATUS %"PRIx64" in vMCE#\n",
   1.138 +                         bank, value);
   1.139 +            } else
   1.140 +                gdprintk(XENLOG_DEBUG,
   1.141 +                         "MCE: wr MC%u_STATUS %"PRIx64"\n", bank, value);
   1.142 +            break;
   1.143 +        case MSR_IA32_MC0_ADDR:
   1.144 +            gdprintk(XENLOG_WARNING, "MCE: MC%u_ADDR is read-only\n", bank);
   1.145 +            ret = -1;
   1.146 +            break;
   1.147 +        case MSR_IA32_MC0_MISC:
   1.148 +            gdprintk(XENLOG_WARNING, "MCE: MC%u_MISC is read-only\n", bank);
   1.149 +            ret = -1;
   1.150              break;
   1.151          }
   1.152 -        d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4] = value;
   1.153 -        break;
   1.154 -    case MSR_IA32_MC0_STATUS:
   1.155 -    case MSR_IA32_MC1_STATUS:
   1.156 -    case MSR_IA32_MC2_STATUS:
   1.157 -    case MSR_IA32_MC3_STATUS:
   1.158 -    case MSR_IA32_MC4_STATUS:
   1.159 -    case MSR_IA32_MC5_STATUS:
   1.160 -    case MSR_IA32_MC6_STATUS:
   1.161 -    case MSR_IA32_MC7_STATUS:
   1.162 -    case MSR_IA32_MC8_STATUS:
   1.163 -        if (!d || is_idle_domain(d)) {
   1.164 -            /* Just skip */
   1.165 -            gdprintk(XENLOG_WARNING, "mce wrmsr: not in domain context!\n");
   1.166 -            break;
   1.167 -        }
   1.168 -        /* Give the first entry of the list, it corresponds to current
   1.169 -         * vMCE# injection. When vMCE# is finished processing by the
   1.170 -         * the guest, this node will be deleted.
   1.171 -         * Only error bank is written. Non-error bank simply return.
   1.172 -         */
   1.173 -        if ( !list_empty(&d->arch.vmca_msrs.impact_header) ) {
   1.174 -            entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.175 -                               struct bank_entry, list);
   1.176 -            if ( entry->bank == (msr - MSR_IA32_MC0_STATUS)/4 ) {
   1.177 -                entry->mci_status = value;
   1.178 -            }
   1.179 -            gdprintk(XENLOG_DEBUG, "MCE: wmrsr mci_status in vMCE# context\n");
   1.180 -        }
   1.181 -        gdprintk(XENLOG_DEBUG, "MCE: wrmsr mci_status val:%"PRIx64"\n", value);
   1.182          break;
   1.183      default:
   1.184          ret = 0;
   1.185 @@ -933,6 +932,7 @@ int intel_mce_rdmsr(u32 msr, u32 *lo, u3
   1.186  {
   1.187      struct domain *d = current->domain;
   1.188      int ret = 1;
   1.189 +    unsigned int bank;
   1.190      struct bank_entry *entry = NULL;
   1.191  
   1.192      *lo = *hi = 0x0;
   1.193 @@ -940,142 +940,82 @@ int intel_mce_rdmsr(u32 msr, u32 *lo, u3
   1.194      switch(msr)
   1.195      {
   1.196      case MSR_IA32_MCG_STATUS:
   1.197 -        if (!d || is_idle_domain(d)) {
   1.198 -            gdprintk(XENLOG_WARNING, "MCE: rdmsr not in domain context!\n");
   1.199 -            *lo = *hi = 0x0;
   1.200 -            break;
   1.201 -        }
   1.202          *lo = (u32)d->arch.vmca_msrs.mcg_status;
   1.203          *hi = (u32)(d->arch.vmca_msrs.mcg_status >> 32);
   1.204          gdprintk(XENLOG_DEBUG, "MCE: rd MCG_STATUS lo %x hi %x\n", *lo, *hi);
   1.205          break;
   1.206      case MSR_IA32_MCG_CAP:
   1.207 -        if (!d || is_idle_domain(d)) {
   1.208 -            gdprintk(XENLOG_WARNING, "MCE: rdmsr not in domain context!\n");
   1.209 -            *lo = *hi = 0x0;
   1.210 -            break;
   1.211 -        }
   1.212          *lo = (u32)d->arch.vmca_msrs.mcg_cap;
   1.213          *hi = (u32)(d->arch.vmca_msrs.mcg_cap >> 32);
   1.214          gdprintk(XENLOG_DEBUG, "MCE: rdmsr MCG_CAP lo %x hi %x\n", *lo, *hi);
   1.215          break;
   1.216      case MSR_IA32_MCG_CTL:
   1.217 -        if (!d || is_idle_domain(d)) {
   1.218 -            gdprintk(XENLOG_WARNING, "MCE: rdmsr not in domain context!\n");
   1.219 -            *lo = *hi = 0x0;
   1.220 -            break;
   1.221 -        }
   1.222          *lo = (u32)d->arch.vmca_msrs.mcg_ctl;
   1.223          *hi = (u32)(d->arch.vmca_msrs.mcg_ctl >> 32);
   1.224          gdprintk(XENLOG_DEBUG, "MCE: rdmsr MCG_CTL lo %x hi %x\n", *lo, *hi);
   1.225          break;
   1.226 -    case MSR_IA32_MC0_CTL2:
   1.227 -    case MSR_IA32_MC1_CTL2:
   1.228 -    case MSR_IA32_MC2_CTL2:
   1.229 -    case MSR_IA32_MC3_CTL2:
   1.230 -    case MSR_IA32_MC4_CTL2:
   1.231 -    case MSR_IA32_MC5_CTL2:
   1.232 -    case MSR_IA32_MC6_CTL2:
   1.233 -    case MSR_IA32_MC7_CTL2:
   1.234 -    case MSR_IA32_MC8_CTL2:
   1.235 +    case MSR_IA32_MC0_CTL2 ... MSR_IA32_MC0_CTL2 + MAX_NR_BANKS - 1:
   1.236          gdprintk(XENLOG_WARNING, "We have disabled CMCI capability, "
   1.237                   "Guest should not read this MSR!\n");
   1.238          break;
   1.239 -    case MSR_IA32_MC0_CTL:
   1.240 -    case MSR_IA32_MC1_CTL:
   1.241 -    case MSR_IA32_MC2_CTL:
   1.242 -    case MSR_IA32_MC3_CTL:
   1.243 -    case MSR_IA32_MC4_CTL:
   1.244 -    case MSR_IA32_MC5_CTL:
   1.245 -    case MSR_IA32_MC6_CTL:
   1.246 -    case MSR_IA32_MC7_CTL:
   1.247 -    case MSR_IA32_MC8_CTL:
   1.248 -        if (!d || is_idle_domain(d)) {
   1.249 -            gdprintk(XENLOG_WARNING, "MCE: rdmsr not in domain context!\n");
   1.250 -            *lo = *hi = 0x0;
   1.251 -            break;
   1.252 -        }
   1.253 -        *lo = (u32)d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4];
   1.254 -        *hi =
   1.255 -            (u32)(d->arch.vmca_msrs.mci_ctl[(msr - MSR_IA32_MC0_CTL)/4]
   1.256 -                  >> 32);
   1.257 -        gdprintk(XENLOG_DEBUG, "MCE: rdmsr MCi_CTL lo %x hi %x\n", *lo, *hi);
   1.258 -        break;
   1.259 -    case MSR_IA32_MC0_STATUS:
   1.260 -    case MSR_IA32_MC1_STATUS:
   1.261 -    case MSR_IA32_MC2_STATUS:
   1.262 -    case MSR_IA32_MC3_STATUS:
   1.263 -    case MSR_IA32_MC4_STATUS:
   1.264 -    case MSR_IA32_MC5_STATUS:
   1.265 -    case MSR_IA32_MC6_STATUS:
   1.266 -    case MSR_IA32_MC7_STATUS:
   1.267 -    case MSR_IA32_MC8_STATUS:
   1.268 -        /* Only error bank is read. Non-error bank simply return */
   1.269 -        *lo = *hi = 0x0;
   1.270 -        gdprintk(XENLOG_DEBUG, "MCE: rdmsr mci_status\n");
   1.271 -        if (!d || is_idle_domain(d)) {
   1.272 -            gdprintk(XENLOG_WARNING, "mce_rdmsr: not in domain context!\n");
   1.273 +    case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * MAX_NR_BANKS - 1:
   1.274 +        bank = (msr - MSR_IA32_MC0_CTL) / 4;
   1.275 +        if (bank >= (d->arch.vmca_msrs.mcg_cap & MCG_CAP_COUNT)) {
   1.276 +            gdprintk(XENLOG_WARNING, "MCE: bank %u does not exist\n", bank);
   1.277 +            ret = -1;
   1.278              break;
   1.279          }
   1.280 -        if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.281 -            entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.282 -                               struct bank_entry, list);
   1.283 -            if ( entry->bank == (msr - MSR_IA32_MC0_STATUS)/4 ) {
   1.284 -                *lo = entry->mci_status;
   1.285 -                *hi = entry->mci_status >> 32;
   1.286 -                gdprintk(XENLOG_DEBUG, "MCE: rdmsr MCi_STATUS in vmCE# context "
   1.287 -                         "lo %x hi %x\n", *lo, *hi);
   1.288 -            }
   1.289 -        }
   1.290 -        break;
   1.291 -    case MSR_IA32_MC0_ADDR:
   1.292 -    case MSR_IA32_MC1_ADDR:
   1.293 -    case MSR_IA32_MC2_ADDR:
   1.294 -    case MSR_IA32_MC3_ADDR:
   1.295 -    case MSR_IA32_MC4_ADDR:
   1.296 -    case MSR_IA32_MC5_ADDR:
   1.297 -    case MSR_IA32_MC6_ADDR:
   1.298 -    case MSR_IA32_MC7_ADDR:
   1.299 -    case MSR_IA32_MC8_ADDR:
   1.300 -        *lo = *hi = 0x0;
   1.301 -        if (!d || is_idle_domain(d)) {
   1.302 -            gdprintk(XENLOG_WARNING, "mce_rdmsr: not in domain context!\n");
   1.303 +        switch (msr & (MSR_IA32_MC0_CTL | 3))
   1.304 +        {
   1.305 +        case MSR_IA32_MC0_CTL:
   1.306 +            *lo = (u32)d->arch.vmca_msrs.mci_ctl[bank];
   1.307 +            *hi = (u32)(d->arch.vmca_msrs.mci_ctl[bank] >> 32);
   1.308 +            gdprintk(XENLOG_DEBUG, "MCE: rd MC%u_CTL lo %x hi %x\n",
   1.309 +                     bank, *lo, *hi);
   1.310              break;
   1.311 -        }
   1.312 -        if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.313 -            entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.314 -                               struct bank_entry, list);
   1.315 -            if ( entry->bank == (msr - MSR_IA32_MC0_ADDR)/4 ) {
   1.316 -                *lo = entry->mci_addr;
   1.317 -                *hi = entry->mci_addr >> 32;
   1.318 -                gdprintk(XENLOG_DEBUG, "MCE: rdmsr MCi_ADDR in vMCE# context "
   1.319 -                         "lo %x hi %x\n", *lo, *hi);
   1.320 +        case MSR_IA32_MC0_STATUS:
   1.321 +            /* Only error bank is read. Non-error banks simply return. */
   1.322 +            if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.323 +                entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.324 +                                   struct bank_entry, list);
   1.325 +                if (entry->bank == bank) {
   1.326 +                    *lo = entry->mci_status;
   1.327 +                    *hi = entry->mci_status >> 32;
   1.328 +                    gdprintk(XENLOG_DEBUG,
   1.329 +                             "MCE: rd MC%u_STATUS in vmCE# context "
   1.330 +                             "lo %x hi %x\n", bank, *lo, *hi);
   1.331 +                } else
   1.332 +                    entry = NULL;
   1.333              }
   1.334 -        }
   1.335 -        break;
   1.336 -    case MSR_IA32_MC0_MISC:
   1.337 -    case MSR_IA32_MC1_MISC:
   1.338 -    case MSR_IA32_MC2_MISC:
   1.339 -    case MSR_IA32_MC3_MISC:
   1.340 -    case MSR_IA32_MC4_MISC:
   1.341 -    case MSR_IA32_MC5_MISC:
   1.342 -    case MSR_IA32_MC6_MISC:
   1.343 -    case MSR_IA32_MC7_MISC:
   1.344 -    case MSR_IA32_MC8_MISC:
   1.345 -        *lo = *hi = 0x0;
   1.346 -        if (!d || is_idle_domain(d)) {
   1.347 -            gdprintk(XENLOG_WARNING, "MCE: rdmsr not in domain context!\n");
   1.348 +            if (!entry)
   1.349 +                gdprintk(XENLOG_DEBUG, "MCE: rd MC%u_STATUS\n", bank);
   1.350              break;
   1.351 -        }
   1.352 -        if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.353 -            entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.354 -                               struct bank_entry, list);
   1.355 -            if ( entry->bank == (msr - MSR_IA32_MC0_MISC)/4 ) {
   1.356 -                *lo = entry->mci_misc;
   1.357 -                *hi = entry->mci_misc >> 32;
   1.358 -                gdprintk(XENLOG_DEBUG, "MCE: rdmsr MCi_MISC in vMCE# context "
   1.359 -                         " lo %x hi %x\n", *lo, *hi);
   1.360 +        case MSR_IA32_MC0_ADDR:
   1.361 +            if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.362 +                entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.363 +                                   struct bank_entry, list);
   1.364 +                if (entry->bank == bank) {
   1.365 +                    *lo = entry->mci_addr;
   1.366 +                    *hi = entry->mci_addr >> 32;
   1.367 +                    gdprintk(XENLOG_DEBUG,
   1.368 +                             "MCE: rd MC%u_ADDR in vMCE# context lo %x hi %x\n",
   1.369 +                             bank, *lo, *hi);
   1.370 +                }
   1.371              }
   1.372 +            break;
   1.373 +        case MSR_IA32_MC0_MISC:
   1.374 +            if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
   1.375 +                entry = list_entry(d->arch.vmca_msrs.impact_header.next,
   1.376 +                                   struct bank_entry, list);
   1.377 +                if (entry->bank == bank) {
   1.378 +                    *lo = entry->mci_misc;
   1.379 +                    *hi = entry->mci_misc >> 32;
   1.380 +                    gdprintk(XENLOG_DEBUG,
   1.381 +                             "MCE: rd MC%u_MISC in vMCE# context lo %x hi %x\n",
   1.382 +                             bank, *lo, *hi);
   1.383 +                }
   1.384 +            }
   1.385 +            break;
   1.386          }
   1.387          break;
   1.388      default:
     2.1 --- a/xen/arch/x86/domain.c	Tue Mar 31 13:14:10 2009 +0100
     2.2 +++ b/xen/arch/x86/domain.c	Tue Mar 31 13:17:48 2009 +0100
     2.3 @@ -46,6 +46,7 @@
     2.4  #include <asm/hvm/support.h>
     2.5  #include <asm/debugreg.h>
     2.6  #include <asm/msr.h>
     2.7 +#include <asm/traps.h>
     2.8  #include <asm/nmi.h>
     2.9  #include <xen/numa.h>
    2.10  #include <xen/iommu.h>
    2.11 @@ -373,7 +374,6 @@ void vcpu_destroy(struct vcpu *v)
    2.12          hvm_vcpu_destroy(v);
    2.13  }
    2.14  
    2.15 -extern uint64_t g_mcg_cap;
    2.16  int arch_domain_create(struct domain *d, unsigned int domcr_flags)
    2.17  {
    2.18  #ifdef __x86_64__
    2.19 @@ -458,14 +458,8 @@ int arch_domain_create(struct domain *d,
    2.20              goto fail;
    2.21  
    2.22          /* For Guest vMCE MSRs virtualization */
    2.23 -        d->arch.vmca_msrs.mcg_status = 0x0;
    2.24 -        d->arch.vmca_msrs.mcg_cap = g_mcg_cap;
    2.25 -        d->arch.vmca_msrs.mcg_ctl = (uint64_t)~0x0;
    2.26 -        d->arch.vmca_msrs.nr_injection = 0;
    2.27 -        memset(d->arch.vmca_msrs.mci_ctl, 0x1,
    2.28 -            sizeof(d->arch.vmca_msrs.mci_ctl));
    2.29 -        INIT_LIST_HEAD(&d->arch.vmca_msrs.impact_header);
    2.30 -
    2.31 +        if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
    2.32 +            intel_mce_init_msr(d);
    2.33      }
    2.34  
    2.35      if ( is_hvm_domain(d) )
     3.1 --- a/xen/arch/x86/traps.c	Tue Mar 31 13:14:10 2009 +0100
     3.2 +++ b/xen/arch/x86/traps.c	Tue Mar 31 13:17:48 2009 +0100
     3.3 @@ -1637,10 +1637,6 @@ static int is_cpufreq_controller(struct 
     3.4              (d->domain_id == 0));
     3.5  }
     3.6  
     3.7 -/*Intel vMCE MSRs virtualization*/
     3.8 -extern int intel_mce_wrmsr(u32 msr, u32 lo,  u32 hi);
     3.9 -extern int intel_mce_rdmsr(u32 msr, u32 *lo,  u32 *hi);
    3.10 -
    3.11  static int emulate_privileged_op(struct cpu_user_regs *regs)
    3.12  {
    3.13      struct vcpu *v = current;
    3.14 @@ -2210,10 +2206,10 @@ static int emulate_privileged_op(struct 
    3.15                  break;
    3.16              if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
    3.17              {
    3.18 -                int rc = intel_mce_wrmsr(regs->ecx, eax, edx);
    3.19 -                if ( rc == -1 )
    3.20 +                int rc = intel_mce_wrmsr(regs->ecx, res);
    3.21 +                if ( rc < 0 )
    3.22                      goto fail;
    3.23 -                if ( rc == 0 )
    3.24 +                if ( rc )
    3.25                      break;
    3.26              }
    3.27  
    3.28 @@ -2291,25 +2287,27 @@ static int emulate_privileged_op(struct 
    3.29          default:
    3.30              if ( rdmsr_hypervisor_regs(regs->ecx, &l, &h) )
    3.31              {
    3.32 + rdmsr_writeback:
    3.33                  regs->eax = l;
    3.34                  regs->edx = h;
    3.35                  break;
    3.36              }
    3.37 +
    3.38 +            if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
    3.39 +            {
    3.40 +                int rc = intel_mce_rdmsr(regs->ecx, &l, &h);
    3.41 +
    3.42 +                if ( rc < 0 )
    3.43 +                    goto fail;
    3.44 +                if ( rc )
    3.45 +                    goto rdmsr_writeback;
    3.46 +            }
    3.47 +
    3.48              /* Everyone can read the MSR space. */
    3.49              /* gdprintk(XENLOG_WARNING,"Domain attempted RDMSR %p.\n",
    3.50                          _p(regs->ecx));*/
    3.51              if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
    3.52                  goto fail;
    3.53 -
    3.54 -            if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
    3.55 -            {
    3.56 -                int rc = intel_mce_rdmsr(regs->ecx, &eax, &edx);
    3.57 -                if ( rc == -1 )
    3.58 -                    goto fail;
    3.59 -                if ( rc == 0 )
    3.60 -                    break;
    3.61 -            }
    3.62 -
    3.63              break;
    3.64          }
    3.65          break;
     4.1 --- a/xen/include/asm-x86/traps.h	Tue Mar 31 13:14:10 2009 +0100
     4.2 +++ b/xen/include/asm-x86/traps.h	Tue Mar 31 13:17:48 2009 +0100
     4.3 @@ -47,4 +47,9 @@ extern int guest_has_trap_callback(struc
     4.4  extern int send_guest_trap(struct domain *d, uint16_t vcpuid,
     4.5  				unsigned int trap_nr);
     4.6  
     4.7 +/* Intel vMCE MSRs virtualization */
     4.8 +extern void intel_mce_init_msr(struct domain *d);
     4.9 +extern int intel_mce_wrmsr(u32 msr, u64 value);
    4.10 +extern int intel_mce_rdmsr(u32 msr, u32 *lo, u32 *hi);
    4.11 +
    4.12  #endif /* ASM_TRAP_H */