From 7013c77826898860e23f40c9b5cf87896c70dcf2 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 18 Jul 2011 19:46:07 -0300 Subject: [RHEL6 qemu-kvm PATCH 02/11] use kernel-provided para_features instead of statically coming up with new capabilities RH-Author: Eduardo Habkost Message-id: <1311018370-5930-2-git-send-email-ehabkost@redhat.com> Patchwork-id: 29965 O-Subject: [RHEL6 qemu-kvm PATCH 1/4] use kernel-provided para_features instead of statically coming up with new capabilities Bugzilla: 624983 RH-Acked-by: Jes Sorensen RH-Acked-by: Gleb Natapov RH-Acked-by: Juan Quintela RH-Acked-by: Zachary Amsden From: Glauber Costa Upstream-Status: applied(qemu.git master), 0c31b744f606d1c19b698041480eb195b8801747 Bugzilla: 624983 According to Avi's comments over my last submission, I decided to take a different, and more correct direction - we hope. This patch is now using the features provided by KVM_GET_SUPPORTED_CPUID directly to mask out features from guest-visible cpuid. The old get_para_features() mechanism is kept for older kernels that do not implement it. Signed-off-by: Glauber Costa Signed-off-by: Eduardo Habkost --- qemu-kvm-x86.c | 90 ++++++++++++++++++++++++++++++------------------------- 1 files changed, 49 insertions(+), 41 deletions(-) Signed-off-by: Eduardo Habkost --- qemu-kvm-x86.c | 90 ++++++++++++++++++++++++++++++------------------------- 1 files changed, 49 insertions(+), 41 deletions(-) diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 8d8956d..81cb90a 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -661,14 +661,51 @@ static struct kvm_cpuid2 *try_get_cpuid(kvm_context_t kvm, int max) #define R_EBP 5 #define R_ESI 6 #define R_EDI 7 +#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 + { -1, -1 } +}; + +static int get_para_features(kvm_context_t kvm_context) +{ + int i, features = 0; + + for (i = 0; i < ARRAY_SIZE(para_features)-1; i++) { + if (kvm_check_extension(kvm_state, para_features[i].cap)) + features |= (1 << para_features[i].feature); + } + + return features; +} + uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg) { + uint32_t ret = -1; + int has_kvm_features = 0; +#ifdef KVM_CAP_EXT_CPUID struct kvm_cpuid2 *cpuid; int i, max; - uint32_t ret = 0; uint32_t cpuid_1_edx; + ret = 0; + if (!kvm_check_extension(kvm_state, KVM_CAP_EXT_CPUID)) { return -1U; } @@ -680,6 +717,10 @@ uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg) for (i = 0; i < cpuid->nent; ++i) { if (cpuid->entries[i].function == function) { + if (cpuid->entries[i].function == KVM_CPUID_FEATURES) { + has_kvm_features = 1; + } + switch (reg) { case R_EAX: ret = cpuid->entries[i].eax; @@ -715,18 +756,15 @@ uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg) } free(cpuid); +#endif + /* fallback for older kernels */ + if (!has_kvm_features && (function == KVM_CPUID_FEATURES)) { + ret = get_para_features(kvm); + } return ret; } -#else - -uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg) -{ - return -1U; -} - -#endif int kvm_qemu_create_memory_alias(uint64_t phys_start, uint64_t len, uint64_t target_phys) @@ -1240,37 +1278,6 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function, e->edx = env->regs[R_EDX]; } -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 - { -1, -1 } -}; - -static int get_para_features(kvm_context_t kvm_context) -{ - int i, features = 0; - - for (i = 0; i < ARRAY_SIZE(para_features)-1; i++) { - if (kvm_check_extension(kvm_state, para_features[i].cap)) - features |= (1 << para_features[i].feature); - } - - return features; -} - static void kvm_trim_features(uint32_t *features, uint32_t supported) { int i; @@ -1322,7 +1329,8 @@ int kvm_arch_init_vcpu(CPUState *cenv) pv_ent = &cpuid_ent[cpuid_nent++]; memset(pv_ent, 0, sizeof(*pv_ent)); pv_ent->function = KVM_CPUID_FEATURES; - pv_ent->eax = cenv->cpuid_kvm_features & get_para_features(kvm_context); + pv_ent->eax = cenv->cpuid_kvm_features & kvm_arch_get_supported_cpuid(cenv, + KVM_CPUID_FEATURES, R_EAX); #endif kvm_trim_features(&cenv->cpuid_features, -- 1.7.3.2