From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LzS1w-0004te-7S for qemu-devel@nongnu.org; Thu, 30 Apr 2009 04:54:08 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LzS1r-0004t1-HJ for qemu-devel@nongnu.org; Thu, 30 Apr 2009 04:54:07 -0400 Received: from [199.232.76.173] (port=59353 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LzS1r-0004sy-Af for qemu-devel@nongnu.org; Thu, 30 Apr 2009 04:54:03 -0400 Received: from mga01.intel.com ([192.55.52.88]:25246) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LzS1q-0004D6-Mg for qemu-devel@nongnu.org; Thu, 30 Apr 2009 04:54:03 -0400 From: Huang Ying Content-Type: multipart/signed; micalg="pgp-sha1"; protocol="application/pgp-signature"; boundary="=-vSwIjNug6lfnhStzrSig" Date: Thu, 30 Apr 2009 16:54:00 +0800 Message-Id: <1241081640.6797.8.camel@yhuang-dev.sh.intel.com> Mime-Version: 1.0 Subject: [Qemu-devel] [RFC 2/2] Add MCE simulation support to qemu/kvm List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Avi Kivity , Anthony Liguori , Andi Kleen Cc: qemu-devel@nongnu.org, "kvm@vger.kernel.org" --=-vSwIjNug6lfnhStzrSig Content-Type: text/plain Content-Transfer-Encoding: quoted-printable MCE features are detected, initialized and injected via the corresponding KVM ioctl. Signed-off-by: Huang Ying --- kvm-all.c | 24 ++++++++++++++++++ kvm.h | 4 +++ target-i386/helper.c | 8 +++++- target-i386/kvm.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++= ++++- 4 files changed, 101 insertions(+), 2 deletions(-) --- a/kvm-all.c +++ b/kvm-all.c @@ -765,6 +765,30 @@ int kvm_has_sync_mmu(void) return 0; } =20 +int kvm_has_mce(void) +{ +#ifdef KVM_CAP_MCE + KVMState *s =3D kvm_state; + int r; + + r =3D kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_MCE); + if (r > 0) + return r; +#endif + return 0; +} + +int kvm_get_mce_cap_supported(uint64_t *mce_cap) +{ +#ifdef KVM_CAP_MCE + KVMState *s =3D kvm_state; + + return kvm_ioctl(s, KVM_X86_GET_MCE_CAP_SUPPORTED, mce_cap); +#else + return -ENOSYS; +#endif +} + #ifdef KVM_CAP_SET_GUEST_DEBUG struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env, target_ulong pc) --- a/kvm.h +++ b/kvm.h @@ -47,6 +47,10 @@ int kvm_log_start(target_phys_addr_t phy int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); =20 int kvm_has_sync_mmu(void); +int kvm_has_mce(void); +int kvm_get_mce_cap_supported(uint64_t *mce_cap); +void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, + uint64_t mcg_status, uint64_t addr, uint64_t misc)= ; =20 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1440,6 +1440,11 @@ void cpu_inject_x86_mce(CPUState *cenv,=20 unsigned bank_num =3D mcg_cap & 0xff; uint64_t *banks =3D cenv->mce_banks; =20 + if (kvm_enabled()) { + kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc); + return; + } + if (bank >=3D bank_num || !(status & MCI_STATUS_VAL)) return; =20 @@ -1757,7 +1762,8 @@ CPUX86State *cpu_x86_init(const char *cp cpu_x86_close(env); return NULL; } - mce_init(env); + if (!kvm_enabled()) + mce_init(env); cpu_reset(env); #ifdef CONFIG_KQEMU kqemu_init(env); --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -34,6 +34,42 @@ do { } while (0) #endif =20 +static void kvm_arch_setup_mce(CPUState *env) +{ + int banks; + int ret; + uint64_t mcg_cap; + +#ifdef KVM_CAP_MCE + if (((env->cpuid_version >> 8) & 0xf) < 6) + return; + + if ((env->cpuid_features & (CPUID_MCE|CPUID_MCA)) !=3D (CPUID_MCE|CPUI= D_MCA)) + return; + + banks =3D kvm_has_mce(); + if (banks <=3D 0) + return; + + ret =3D kvm_get_mce_cap_supported(&mcg_cap); + if (ret) { + fprintf(stderr, "kvm_get_mce_cap_supported FAILED\n"); + return; + } + + if (banks > MCE_BANKS_DEF) + banks =3D MCE_BANKS_DEF; + mcg_cap &=3D MCE_CAP_DEF; + mcg_cap |=3D banks; + + if (kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, &mcg_cap)) { + fprintf(stderr, "kvm: setup mce FAILED\n"); + return; + } + env->mcg_cap =3D mcg_cap; +#endif +} + int kvm_arch_init_vcpu(CPUState *env) { struct { @@ -42,6 +78,7 @@ int kvm_arch_init_vcpu(CPUState *env) } __attribute__((packed)) cpuid_data; uint32_t limit, i, j, cpuid_i; uint32_t unused; + int ret; =20 cpuid_i =3D 0; =20 @@ -107,7 +144,13 @@ int kvm_arch_init_vcpu(CPUState *env) =20 cpuid_data.cpuid.nent =3D cpuid_i; =20 - return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); + ret =3D kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); + if (ret < 0) + return ret; + + kvm_arch_setup_mce(env); + + return 0; } =20 static int kvm_has_msr_star(CPUState *env) @@ -665,6 +708,28 @@ int kvm_arch_handle_exit(CPUState *env,=20 return ret; } =20 +void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, + uint64_t mcg_status, uint64_t addr, uint64_t misc) +{ +#ifdef KVM_CAP_MCE + struct kvm_x86_mce mce =3D { + .bank =3D bank, + .status =3D status, + .mcg_status =3D mcg_status, + .addr =3D addr, + .misc =3D misc, + }; + int ret; + + if (kvm_has_mce() <=3D 0) + return; + + ret =3D kvm_vcpu_ioctl(cenv, KVM_X86_SET_MCE, &mce); + if (ret < 0) + fprintf(stderr, "kvm: inject mce FAILED\n"); +#endif +} + #ifdef KVM_CAP_SET_GUEST_DEBUG int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint = *bp) { --=-vSwIjNug6lfnhStzrSig Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEABECAAYFAkn5ZyUACgkQKhFGF+eHlpiT1QCfeYB1N9X/ALGJScMz8rTkhRqw foIAn2pHDaPIorDlr9CcflUrT2eqK1/l =0dW5 -----END PGP SIGNATURE----- --=-vSwIjNug6lfnhStzrSig--