diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-01-13 15:25:06 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2010-01-13 17:14:16 -0600 |
commit | bb0300dc57c10b3721451b0ff566a03f9276cc77 (patch) | |
tree | 9f9f59b498ee5d5361e72f618f95169323a06d4f /target-i386/kvm.c | |
parent | 4277906d281e7fd04817782777b90f6d122f4443 (diff) |
Add KVM paravirt cpuid leaf
Initialize KVM paravirt cpuid leaf and allow user to control guest
visible PV features through -cpu flag.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'target-i386/kvm.c')
-rw-r--r-- | target-i386/kvm.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 408450361a..5b093ce3bf 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -25,6 +25,10 @@ #include "gdbstub.h" #include "host-utils.h" +#ifdef CONFIG_KVM_PARA +#include <linux/kvm_para.h> +#endif +// //#define DEBUG_KVM #ifdef DEBUG_KVM @@ -134,6 +138,39 @@ static void kvm_trim_features(uint32_t *features, uint32_t supported) } } +#ifdef CONFIG_KVM_PARA +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(CPUState *env) +{ + int i, features = 0; + + for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) { + if (kvm_check_extension(env->kvm_state, para_features[i].cap)) + features |= (1 << para_features[i].feature); + } + + return features; +} +#endif + int kvm_arch_init_vcpu(CPUState *env) { struct { @@ -142,6 +179,10 @@ int kvm_arch_init_vcpu(CPUState *env) } __attribute__((packed)) cpuid_data; uint32_t limit, i, j, cpuid_i; uint32_t unused; + struct kvm_cpuid_entry2 *c; +#ifdef KVM_CPUID_SIGNATURE + uint32_t signature[3]; +#endif env->mp_state = KVM_MP_STATE_RUNNABLE; @@ -160,10 +201,27 @@ int kvm_arch_init_vcpu(CPUState *env) cpuid_i = 0; +#ifdef CONFIG_KVM_PARA + /* Paravirtualization CPUIDs */ + memcpy(signature, "KVMKVMKVM\0\0\0", 12); + c = &cpuid_data.entries[cpuid_i++]; + memset(c, 0, sizeof(*c)); + c->function = KVM_CPUID_SIGNATURE; + c->eax = 0; + c->ebx = signature[0]; + c->ecx = signature[1]; + c->edx = signature[2]; + + c = &cpuid_data.entries[cpuid_i++]; + memset(c, 0, sizeof(*c)); + c->function = KVM_CPUID_FEATURES; + c->eax = env->cpuid_kvm_features & get_para_features(env); +#endif + cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused); for (i = 0; i <= limit; i++) { - struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; + c = &cpuid_data.entries[cpuid_i++]; switch (i) { case 2: { @@ -213,7 +271,7 @@ int kvm_arch_init_vcpu(CPUState *env) cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused); for (i = 0x80000000; i <= limit; i++) { - struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; + c = &cpuid_data.entries[cpuid_i++]; c->function = i; c->flags = 0; |