summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2009-07-20 10:00:53 +0800
committerMarcelo Tosatti <mtosatti@redhat.com>2009-07-20 12:37:47 -0300
commitc68b2374c9048812f488e00ffb95db66c0bc07a7 (patch)
tree799e2a2cb6250b117462bcb955cef8e1bf1fbdbb /qemu-kvm-x86.c
parentreplace qemu_kvm_cpu_env (diff)
downloadqemu-kvm-c68b2374c9048812f488e00ffb95db66c0bc07a7.tar.gz
qemu-kvm-c68b2374c9048812f488e00ffb95db66c0bc07a7.tar.bz2
qemu-kvm-c68b2374c9048812f488e00ffb95db66c0bc07a7.zip
Add MCE simulation support to qemu/kvm
KVM ioctls are used to initialize MCE simulation and inject MCE. The real MCE simulation is implemented in Linux kernel. The Kernel part has been merged. ChangeLog: v7: - Re-based on qemu-kvm.git/next branch v6: - Re-based on latest qemu-kvm.git v5: - Re-based on latest qemu-kvm.git v3: - Re-based on qemu/tcg MCE support patch v2: - Use new kernel MCE capability exportion interface. Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'qemu-kvm-x86.c')
-rw-r--r--qemu-kvm-x86.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 350f272d7..df40aaee8 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -432,6 +432,39 @@ int kvm_set_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
return r;
}
+int kvm_get_mce_cap_supported(kvm_context_t kvm, uint64_t *mce_cap,
+ int *max_banks)
+{
+#ifdef KVM_CAP_MCE
+ int r;
+
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_MCE);
+ if (r > 0) {
+ *max_banks = r;
+ return ioctl(kvm->fd, KVM_X86_GET_MCE_CAP_SUPPORTED, mce_cap);
+ }
+#endif
+ return -ENOSYS;
+}
+
+int kvm_setup_mce(kvm_vcpu_context_t vcpu, uint64_t *mcg_cap)
+{
+#ifdef KVM_CAP_MCE
+ return ioctl(vcpu->fd, KVM_X86_SETUP_MCE, mcg_cap);
+#else
+ return -ENOSYS;
+#endif
+}
+
+int kvm_set_mce(kvm_vcpu_context_t vcpu, struct kvm_x86_mce *m)
+{
+#ifdef KVM_CAP_MCE
+ return ioctl(vcpu->fd, KVM_X86_SET_MCE, m);
+#else
+ return -ENOSYS;
+#endif
+}
+
static void print_seg(FILE *file, const char *name, struct kvm_segment *seg)
{
fprintf(stderr,
@@ -1285,6 +1318,28 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
kvm_setup_cpuid2(cenv->kvm_cpu_state.vcpu_ctx, cpuid_nent, cpuid_ent);
+#ifdef KVM_CAP_MCE
+ if (((cenv->cpuid_version >> 8)&0xF) >= 6
+ && (cenv->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)
+ && kvm_check_extension(kvm_context, KVM_CAP_MCE) > 0) {
+ uint64_t mcg_cap;
+ int banks;
+
+ if (kvm_get_mce_cap_supported(kvm_context, &mcg_cap, &banks))
+ perror("kvm_get_mce_cap_supported FAILED");
+ else {
+ if (banks > MCE_BANKS_DEF)
+ banks = MCE_BANKS_DEF;
+ mcg_cap &= MCE_CAP_DEF;
+ mcg_cap |= banks;
+ if (kvm_setup_mce(cenv->kvm_cpu_state.vcpu_ctx, &mcg_cap))
+ perror("kvm_setup_mce FAILED");
+ else
+ cenv->mcg_cap = mcg_cap;
+ }
+ }
+#endif
+
return 0;
}