diff options
author | Huang Ying <ying.huang@intel.com> | 2009-07-20 10:00:53 +0800 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2009-07-20 12:37:47 -0300 |
commit | c68b2374c9048812f488e00ffb95db66c0bc07a7 (patch) | |
tree | 799e2a2cb6250b117462bcb955cef8e1bf1fbdbb /qemu-kvm-x86.c | |
parent | replace qemu_kvm_cpu_env (diff) | |
download | qemu-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.c | 55 |
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; } |