From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LS9RI-0001Yo-4R for qemu-devel@nongnu.org; Wed, 28 Jan 2009 07:22:40 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LS9RF-0001To-Iv for qemu-devel@nongnu.org; Wed, 28 Jan 2009 07:22:39 -0500 Received: from [199.232.76.173] (port=59162 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LS9RF-0001Ta-FP for qemu-devel@nongnu.org; Wed, 28 Jan 2009 07:22:37 -0500 Received: from mx2.redhat.com ([66.187.237.31]:35214) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LS9RF-0003x2-3W for qemu-devel@nongnu.org; Wed, 28 Jan 2009 07:22:37 -0500 From: Glauber Costa Date: Wed, 28 Jan 2009 07:22:31 -0500 Message-Id: <1233145351-22380-1-git-send-email-glommer@redhat.com> Subject: [Qemu-devel] [PATCH] expose paravirt feature list to cpuid 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 Expose the paravirt features provided by the host to the guest. The features exposed uses qemu just as a medium, since they only depend on a negotiation between the host and guest directly. As a direct result, we're now able to run the kvm pvclock in qemu based kvm guests. Signed-off-by: Glauber Costa --- kvm.h | 1 + target-i386/kvm.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 0 deletions(-) diff --git a/kvm.h b/kvm.h index efce145..db58baa 100644 --- a/kvm.h +++ b/kvm.h @@ -17,6 +17,7 @@ #include "config.h" #ifdef CONFIG_KVM +#include extern int kvm_allowed; #define kvm_enabled() (kvm_allowed) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 2412ae4..3c62df5 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -33,6 +33,35 @@ do { } while (0) #endif +struct kvm_para_features { + int cap; + int feature; +} para_features[] = { +#ifdef KVM_CAP_CLOCKSOURCE + { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE }, +#endif +#ifdef KVM_CAP_NOP_IO_DELAY + { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, +#endif +#ifdef KVM_CAP_PV_MMU + { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, +#endif +#ifdef KVM_CAP_CR3_CACHE + { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE }, +#endif +}; + +static int get_para_features(CPUState *env) +{ + int i, features = 0; + + for (i = 0; i < ARRAY_SIZE(para_features); i++) { + if (kvm_ioctl(env->kvm_state, KVM_CHECK_EXTENSION, para_features[i].cap)) + features |= (1 << para_features[i].feature); + } + + return features; +} int kvm_arch_init_vcpu(CPUState *env) { struct { @@ -41,8 +70,29 @@ int kvm_arch_init_vcpu(CPUState *env) } __attribute__((packed)) cpuid_data; uint32_t limit, i, cpuid_i; uint32_t eax, ebx, ecx, edx; +#ifdef KVM_CPUID_SIGNATURE + struct kvm_cpuid_entry *pv_ent; + uint32_t signature[3]; +#endif cpuid_i = 0; +#ifdef KVM_CPUID_SIGNATURE + /* Paravirtualization CPUIDs */ + memcpy(signature, "KVMKVMKVM\0\0\0", 12); + pv_ent = &cpuid_data.entries[cpuid_i++]; + memset(pv_ent, 0, sizeof(*pv_ent)); + pv_ent->function = KVM_CPUID_SIGNATURE; + pv_ent->eax = 0; + pv_ent->ebx = signature[0]; + pv_ent->ecx = signature[1]; + pv_ent->edx = signature[2]; + + pv_ent = &cpuid_data.entries[cpuid_i++]; + memset(pv_ent, 0, sizeof(*pv_ent)); + pv_ent->function = KVM_CPUID_FEATURES; + pv_ent->eax = get_para_features(env); +#endif + cpu_x86_cpuid(env, 0, &eax, &ebx, &ecx, &edx); limit = eax; -- 1.5.6.5