@@ -803,6 +803,27 @@ static void get_seg(SegmentCache *lhs, c
| (rhs->avl * DESC_AVL_MASK);
}
+static void kvm_load_mce_regs(CPUState *env)
+{
+#ifdef KVM_CAP_MCE
+ struct kvm_msr_entry msrs[100];
+ int rc, n, i;
+
+ if (!env->mcg_cap)
+ return;
+
+ n = 0;
+ set_msr_entry(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
+ set_msr_entry(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
+ for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++)
+ set_msr_entry(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
+
+ rc = kvm_set_msrs(env, msrs, n);
+ if (rc == -1)
+ perror("kvm_set_msrs FAILED");
+#endif
+}
+
void kvm_arch_load_regs(CPUState *env)
{
struct kvm_regs regs;
@@ -922,6 +943,8 @@ void kvm_arch_load_regs(CPUState *env)
if (rc == -1)
perror("kvm_set_msrs FAILED");
+ kvm_load_mce_regs(env);
+
/*
* Kernels before 2.6.33 (which correlates with !kvm_has_vcpu_events())
* overwrote flags.TF injected via SET_GUEST_DEBUG while updating GP regs.
@@ -991,6 +1014,33 @@ void kvm_arch_load_mpstate(CPUState *env
#endif
}
+static void kvm_save_mce_regs(CPUState *env)
+{
+#ifdef KVM_CAP_MCE
+ struct kvm_msr_entry msrs[100];
+ int rc, n, i;
+
+ if (!env->mcg_cap)
+ return;
+
+ msrs[0].index = MSR_MCG_STATUS;
+ msrs[1].index = MSR_MCG_CTL;
+ n = (env->mcg_cap & 0xff) * 4;
+ for (i = 0; i < n; i++)
+ msrs[2 + i].index = MSR_MC0_CTL + i;
+
+ rc = kvm_get_msrs(env, msrs, n + 2);
+ if (rc == -1)
+ perror("kvm_set_msrs FAILED");
+ else {
+ env->mcg_status = msrs[0].data;
+ env->mcg_ctl = msrs[1].data;
+ for (i = 0; i < n; i++)
+ env->mce_banks[i] = msrs[2 + i].data;
+ }
+#endif
+}
+
void kvm_arch_save_regs(CPUState *env)
{
struct kvm_regs regs;
@@ -1148,6 +1198,7 @@ void kvm_arch_save_regs(CPUState *env)
}
}
kvm_arch_save_mpstate(env);
+ kvm_save_mce_regs(env);
}
static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function,
@@ -1385,6 +1436,9 @@ void kvm_arch_push_nmi(void *opaque)
void kvm_arch_cpu_reset(CPUState *env)
{
kvm_arch_reset_vcpu(env);
+ /* MCE registers except MCG_STATUS should be unchanged across reset */
+ kvm_save_mce_regs(env);
+ env->mcg_status = 0;
kvm_arch_load_regs(env);
kvm_put_vcpu_events(env);
if (!cpu_is_bsp(env)) {