From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LSFfv-0006CJ-1E for qemu-devel@nongnu.org; Wed, 28 Jan 2009 14:02:11 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LSFft-0006AO-AM for qemu-devel@nongnu.org; Wed, 28 Jan 2009 14:02:10 -0500 Received: from [199.232.76.173] (port=40911 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LSFft-0006A3-2h for qemu-devel@nongnu.org; Wed, 28 Jan 2009 14:02:09 -0500 Received: from mx2.redhat.com ([66.187.237.31]:51337) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LSFfs-0006f8-6Y for qemu-devel@nongnu.org; Wed, 28 Jan 2009 14:02:08 -0500 From: Glauber Costa Date: Wed, 28 Jan 2009 14:02:05 -0500 Message-Id: <1233169325-5487-4-git-send-email-glommer@redhat.com> In-Reply-To: <1233169325-5487-3-git-send-email-glommer@redhat.com> References: <1233169325-5487-1-git-send-email-glommer@redhat.com> <1233169325-5487-2-git-send-email-glommer@redhat.com> <1233169325-5487-3-git-send-email-glommer@redhat.com> Subject: [Qemu-devel] [PATCH 3/3] mask out forbidden cpuid features Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aliguori@us.ibm.com KVM has a (so far unused) ioctl to inform userspace about supported cpuid bits in the current host. The lack of this kind of checking can lead to bugs in which a cpuid bit is exposed but not supported by the host kernel (an example is fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=481274) Signed-off-by: Glauber Costa --- target-i386/kvm.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 files changed, 39 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 87ddff5..08584dd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -68,8 +68,18 @@ int kvm_arch_init_vcpu(CPUState *env) struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; } __attribute__((packed)) cpuid_data; - uint32_t limit, i, cpuid_i = 0; + + struct { + struct kvm_cpuid2 cpuid; + struct kvm_cpuid_entry2 entries[100]; + } __attribute__((packed)) cpuid_base_data; + + uint32_t limit, i, r, cpuid_i = 0; uint32_t eax, ebx, ecx, edx; + struct kvm_cpuid_entry2 *func1 = NULL; + struct kvm_cpuid_entry2 *ext_func1 = NULL; + uint32_t ecx_mask = ~0U; + uint32_t edx_mask = ~0U; #ifdef KVM_CPUID_SIGNATURE struct kvm_cpuid_entry2 *pv_ent; @@ -89,32 +99,56 @@ int kvm_arch_init_vcpu(CPUState *env) #endif + cpuid_base_data.cpuid.nent = 100; + r = kvm_ioctl(env->kvm_state, KVM_GET_SUPPORTED_CPUID, &cpuid_base_data); + if (r == -1) + cpuid_base_data.cpuid.nent = 0; + + for (i = 0; i < cpuid_base_data.cpuid.nent; i++) { + if (cpuid_base_data.entries[i].function == 1) + func1 = &cpuid_base_data.entries[i]; + if (cpuid_base_data.entries[i].function == 0x80000001) + ext_func1 = &cpuid_base_data.entries[i]; + } + cpu_x86_cpuid(env, 0, &eax, &ebx, &ecx, &edx); limit = eax; for (i = 0; i <= limit; i++) { struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; + if (func1 && (i == 1)) { + ecx_mask = func1->ecx; + edx_mask = func1->edx; + } else + ecx_mask = edx_mask = ~0U; + cpu_x86_cpuid(env, i, &eax, &ebx, &ecx, &edx); c->function = i; c->eax = eax; c->ebx = ebx; - c->ecx = ecx; - c->edx = edx; + c->ecx = ecx & ecx_mask; + c->edx = edx & edx_mask; } cpu_x86_cpuid(env, 0x80000000, &eax, &ebx, &ecx, &edx); limit = eax; for (i = 0x80000000; i <= limit; i++) { + struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; + if (ext_func1 && (i == 0x80000001)) { + ecx_mask = ext_func1->ecx; + edx_mask = ext_func1->edx; + } else + ecx_mask = edx_mask = ~0U; cpu_x86_cpuid(env, i, &eax, &ebx, &ecx, &edx); c->function = i; c->eax = eax; c->ebx = ebx; - c->ecx = ecx; - c->edx = edx; + c->ecx = ecx & ecx_mask; + c->edx = edx & edx_mask; } cpuid_data.cpuid.nent = cpuid_i; -- 1.5.6.5