Message ID | 1373245434-25502-1-git-send-email-afaerber@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, 8 Jul 2013 03:03:54 +0200 Andreas Färber <afaerber@suse.de> wrote: > From: Igor Mammedov <imammedo@redhat.com> > > - since hyperv_* helper functions are used only in target-i386/kvm.c > move them there as static helpers > > Requested-by: Eduardo Habkost <ehabkost@redhat.com> > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > Signed-off-by: Andreas Färber <afaerber@suse.de> I'm not tested it yet, but it looks good to me. > --- > v8 (imammedo) -> v9: > * Use X86CPU instead of CPUX86State (only used in KVM) > * Changed helper functions to X86CPU argument > * Moved field initialization to QOM instance_init > * Fixed subject (not today's "CPUState") > > target-i386/Makefile.objs | 2 +- > target-i386/cpu-qom.h | 4 +++ > target-i386/cpu.c | 16 ++++++++---- > target-i386/cpu.h | 4 +++ > target-i386/hyperv.c | 64 ----------------------------------------------- > target-i386/hyperv.h | 45 --------------------------------- > target-i386/kvm.c | 36 ++++++++++++++++++-------- > 7 files changed, 46 insertions(+), 125 deletions(-) > delete mode 100644 target-i386/hyperv.c > delete mode 100644 target-i386/hyperv.h > > diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs > index c1d4f05..887dca7 100644 > --- a/target-i386/Makefile.objs > +++ b/target-i386/Makefile.objs > @@ -2,7 +2,7 @@ obj-y += translate.o helper.o cpu.o > obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o > obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o > obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o > -obj-$(CONFIG_KVM) += kvm.o hyperv.o > +obj-$(CONFIG_KVM) += kvm.o > obj-$(CONFIG_NO_KVM) += kvm-stub.o > obj-$(CONFIG_LINUX_USER) += ioport-user.o > obj-$(CONFIG_BSD_USER) += ioport-user.o > diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h > index 7e55e5f..18f08b8 100644 > --- a/target-i386/cpu-qom.h > +++ b/target-i386/cpu-qom.h > @@ -66,6 +66,10 @@ typedef struct X86CPU { > > CPUX86State env; > > + bool hyperv_vapic; > + bool hyperv_relaxed_timing; > + int hyperv_spinlock_attempts; > + > /* Features that were filtered out because of missing host capabilities */ > uint32_t filtered_features[FEATURE_WORDS]; > } X86CPU; > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index e3f75a8..14e9c7e 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -35,8 +35,6 @@ > #include "qapi/visitor.h" > #include "sysemu/arch_init.h" > > -#include "hyperv.h" > - > #include "hw/hw.h" > #if defined(CONFIG_KVM) > #include <linux/kvm_para.h> > @@ -1587,12 +1585,19 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) > object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp); > } else if (!strcmp(featurestr, "hv-spinlocks")) { > char *err; > + const int min = 0xFFF; > numvalue = strtoul(val, &err, 0); > if (!*val || *err) { > error_setg(errp, "bad numerical value %s", val); > goto out; > } > - hyperv_set_spinlock_retries(numvalue); > + if (numvalue < min) { > + fprintf(stderr, "hv-spinlocks value shall always be >= 0x%x" > + ", fixup will be removed in future versions\n", > + min); > + numvalue = min; > + } > + cpu->hyperv_spinlock_attempts = numvalue; > } else { > error_setg(errp, "unrecognized feature %s", featurestr); > goto out; > @@ -1602,9 +1607,9 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) > } else if (!strcmp(featurestr, "enforce")) { > check_cpuid = enforce_cpuid = 1; > } else if (!strcmp(featurestr, "hv_relaxed")) { > - hyperv_enable_relaxed_timing(true); > + cpu->hyperv_relaxed_timing = true; > } else if (!strcmp(featurestr, "hv_vapic")) { > - hyperv_enable_vapic_recommended(true); > + cpu->hyperv_vapic = true; > } else { > error_setg(errp, "feature string `%s' not in format (+feature|" > "-feature|feature=xyz)", featurestr); > @@ -2479,6 +2484,7 @@ static void x86_cpu_initfn(Object *obj) > x86_cpu_get_feature_words, > NULL, NULL, (void *)cpu->filtered_features, NULL); > > + cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; > env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index); > > /* init various static tables used in TCG mode */ > diff --git a/target-i386/cpu.h b/target-i386/cpu.h > index 2d005b3..6c3eb86 100644 > --- a/target-i386/cpu.h > +++ b/target-i386/cpu.h > @@ -549,6 +549,10 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; > #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ > #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ > > +#ifndef HYPERV_SPINLOCK_NEVER_RETRY > +#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF > +#endif > + > #define EXCP00_DIVZ 0 > #define EXCP01_DB 1 > #define EXCP02_NMI 2 > diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c > deleted file mode 100644 > index f284e99..0000000 > --- a/target-i386/hyperv.c > +++ /dev/null > @@ -1,64 +0,0 @@ > -/* > - * QEMU Hyper-V support > - * > - * Copyright Red Hat, Inc. 2011 > - * > - * Author: Vadim Rozenfeld <vrozenfe@redhat.com> > - * > - * This work is licensed under the terms of the GNU GPL, version 2 or later. > - * See the COPYING file in the top-level directory. > - * > - */ > - > -#include "hyperv.h" > - > -static bool hyperv_vapic; > -static bool hyperv_relaxed_timing; > -static int hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; > - > -void hyperv_enable_vapic_recommended(bool val) > -{ > - hyperv_vapic = val; > -} > - > -void hyperv_enable_relaxed_timing(bool val) > -{ > - hyperv_relaxed_timing = val; > -} > - > -void hyperv_set_spinlock_retries(int val) > -{ > - hyperv_spinlock_attempts = val; > - if (hyperv_spinlock_attempts < 0xFFF) { > - hyperv_spinlock_attempts = 0xFFF; > - } > -} > - > -bool hyperv_enabled(void) > -{ > - return hyperv_hypercall_available() || hyperv_relaxed_timing_enabled(); > -} > - > -bool hyperv_hypercall_available(void) > -{ > - if (hyperv_vapic || > - (hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY)) { > - return true; > - } > - return false; > -} > - > -bool hyperv_vapic_recommended(void) > -{ > - return hyperv_vapic; > -} > - > -bool hyperv_relaxed_timing_enabled(void) > -{ > - return hyperv_relaxed_timing; > -} > - > -int hyperv_get_spinlock_retries(void) > -{ > - return hyperv_spinlock_attempts; > -} > diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h > deleted file mode 100644 > index bacb1d4..0000000 > --- a/target-i386/hyperv.h > +++ /dev/null > @@ -1,45 +0,0 @@ > -/* > - * QEMU Hyper-V support > - * > - * Copyright Red Hat, Inc. 2011 > - * > - * Author: Vadim Rozenfeld <vrozenfe@redhat.com> > - * > - * This work is licensed under the terms of the GNU GPL, version 2 or later. > - * See the COPYING file in the top-level directory. > - * > - */ > - > -#ifndef QEMU_HW_HYPERV_H > -#define QEMU_HW_HYPERV_H 1 > - > -#include "qemu-common.h" > -#ifdef CONFIG_KVM > -#include <asm/hyperv.h> > -#endif > - > -#ifndef HYPERV_SPINLOCK_NEVER_RETRY > -#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF > -#endif > - > -#ifndef KVM_CPUID_SIGNATURE_NEXT > -#define KVM_CPUID_SIGNATURE_NEXT 0x40000100 > -#endif > - > -#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_KVM) > -void hyperv_enable_vapic_recommended(bool val); > -void hyperv_enable_relaxed_timing(bool val); > -void hyperv_set_spinlock_retries(int val); > -#else > -static inline void hyperv_enable_vapic_recommended(bool val) { } > -static inline void hyperv_enable_relaxed_timing(bool val) { } > -static inline void hyperv_set_spinlock_retries(int val) { } > -#endif > - > -bool hyperv_enabled(void); > -bool hyperv_hypercall_available(void); > -bool hyperv_vapic_recommended(void); > -bool hyperv_relaxed_timing_enabled(void); > -int hyperv_get_spinlock_retries(void); > - > -#endif /* QEMU_HW_HYPERV_H */ > diff --git a/target-i386/kvm.c b/target-i386/kvm.c > index 935ef63..ded4743 100644 > --- a/target-i386/kvm.c > +++ b/target-i386/kvm.c > @@ -31,7 +31,7 @@ > #include "hw/i386/pc.h" > #include "hw/i386/apic.h" > #include "exec/ioport.h" > -#include "hyperv.h" > +#include <asm/hyperv.h> > #include "hw/pci/pci.h" > > //#define DEBUG_KVM > @@ -420,6 +420,22 @@ unsigned long kvm_arch_vcpu_id(CPUState *cs) > return cpu->env.cpuid_apic_id; > } > > +#ifndef KVM_CPUID_SIGNATURE_NEXT > +#define KVM_CPUID_SIGNATURE_NEXT 0x40000100 > +#endif > + > +static bool hyperv_hypercall_available(X86CPU *cpu) > +{ > + return cpu->hyperv_vapic || > + (cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY); > +} > + > +static bool hyperv_enabled(X86CPU *cpu) > +{ > + return hyperv_hypercall_available(cpu) || > + cpu->hyperv_relaxed_timing; > +} > + > #define KVM_MAX_CPUID_ENTRIES 100 > > int kvm_arch_init_vcpu(CPUState *cs) > @@ -442,7 +458,7 @@ int kvm_arch_init_vcpu(CPUState *cs) > c = &cpuid_data.entries[cpuid_i++]; > memset(c, 0, sizeof(*c)); > c->function = KVM_CPUID_SIGNATURE; > - if (!hyperv_enabled()) { > + if (!hyperv_enabled(cpu)) { > memcpy(signature, "KVMKVMKVM\0\0\0", 12); > c->eax = 0; > } else { > @@ -458,7 +474,7 @@ int kvm_arch_init_vcpu(CPUState *cs) > c->function = KVM_CPUID_FEATURES; > c->eax = env->features[FEAT_KVM]; > > - if (hyperv_enabled()) { > + if (hyperv_enabled(cpu)) { > memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12); > c->eax = signature[0]; > > @@ -471,10 +487,10 @@ int kvm_arch_init_vcpu(CPUState *cs) > c = &cpuid_data.entries[cpuid_i++]; > memset(c, 0, sizeof(*c)); > c->function = HYPERV_CPUID_FEATURES; > - if (hyperv_relaxed_timing_enabled()) { > + if (cpu->hyperv_relaxed_timing) { > c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; > } > - if (hyperv_vapic_recommended()) { > + if (cpu->hyperv_vapic) { > c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; > c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE; > } > @@ -482,13 +498,13 @@ int kvm_arch_init_vcpu(CPUState *cs) > c = &cpuid_data.entries[cpuid_i++]; > memset(c, 0, sizeof(*c)); > c->function = HYPERV_CPUID_ENLIGHTMENT_INFO; > - if (hyperv_relaxed_timing_enabled()) { > + if (cpu->hyperv_relaxed_timing) { > c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED; > } > - if (hyperv_vapic_recommended()) { > + if (cpu->hyperv_vapic) { > c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED; > } > - c->ebx = hyperv_get_spinlock_retries(); > + c->ebx = cpu->hyperv_spinlock_attempts; > > c = &cpuid_data.entries[cpuid_i++]; > memset(c, 0, sizeof(*c)); > @@ -1117,11 +1133,11 @@ static int kvm_put_msrs(X86CPU *cpu, int level) > kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME, > env->steal_time_msr); > } > - if (hyperv_hypercall_available()) { > + if (hyperv_hypercall_available(cpu)) { > kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0); > kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0); > } > - if (hyperv_vapic_recommended()) { > + if (cpu->hyperv_vapic) { > kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0); > } > } -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Am 08.07.2013 14:40, schrieb Igor Mammedov: > On Mon, 8 Jul 2013 03:03:54 +0200 > Andreas Färber <afaerber@suse.de> wrote: > >> From: Igor Mammedov <imammedo@redhat.com> >> >> - since hyperv_* helper functions are used only in target-i386/kvm.c >> move them there as static helpers >> >> Requested-by: Eduardo Habkost <ehabkost@redhat.com> >> Signed-off-by: Igor Mammedov <imammedo@redhat.com> >> Signed-off-by: Andreas Färber <afaerber@suse.de> > I'm not tested it yet, but it looks good to me. Being from you originally and me having confidence in my changes on top, I'm queuing this on qom-cpu-next: https://github.com/afaerber/qemu-cpu/commits/qom-cpu-next Andreas >> --- >> v8 (imammedo) -> v9: >> * Use X86CPU instead of CPUX86State (only used in KVM) >> * Changed helper functions to X86CPU argument >> * Moved field initialization to QOM instance_init >> * Fixed subject (not today's "CPUState") >> >> target-i386/Makefile.objs | 2 +- >> target-i386/cpu-qom.h | 4 +++ >> target-i386/cpu.c | 16 ++++++++---- >> target-i386/cpu.h | 4 +++ >> target-i386/hyperv.c | 64 ----------------------------------------------- >> target-i386/hyperv.h | 45 --------------------------------- >> target-i386/kvm.c | 36 ++++++++++++++++++-------- >> 7 files changed, 46 insertions(+), 125 deletions(-) >> delete mode 100644 target-i386/hyperv.c >> delete mode 100644 target-i386/hyperv.h
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index c1d4f05..887dca7 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -2,7 +2,7 @@ obj-y += translate.o helper.o cpu.o obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o -obj-$(CONFIG_KVM) += kvm.o hyperv.o +obj-$(CONFIG_KVM) += kvm.o obj-$(CONFIG_NO_KVM) += kvm-stub.o obj-$(CONFIG_LINUX_USER) += ioport-user.o obj-$(CONFIG_BSD_USER) += ioport-user.o diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index 7e55e5f..18f08b8 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -66,6 +66,10 @@ typedef struct X86CPU { CPUX86State env; + bool hyperv_vapic; + bool hyperv_relaxed_timing; + int hyperv_spinlock_attempts; + /* Features that were filtered out because of missing host capabilities */ uint32_t filtered_features[FEATURE_WORDS]; } X86CPU; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e3f75a8..14e9c7e 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -35,8 +35,6 @@ #include "qapi/visitor.h" #include "sysemu/arch_init.h" -#include "hyperv.h" - #include "hw/hw.h" #if defined(CONFIG_KVM) #include <linux/kvm_para.h> @@ -1587,12 +1585,19 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp); } else if (!strcmp(featurestr, "hv-spinlocks")) { char *err; + const int min = 0xFFF; numvalue = strtoul(val, &err, 0); if (!*val || *err) { error_setg(errp, "bad numerical value %s", val); goto out; } - hyperv_set_spinlock_retries(numvalue); + if (numvalue < min) { + fprintf(stderr, "hv-spinlocks value shall always be >= 0x%x" + ", fixup will be removed in future versions\n", + min); + numvalue = min; + } + cpu->hyperv_spinlock_attempts = numvalue; } else { error_setg(errp, "unrecognized feature %s", featurestr); goto out; @@ -1602,9 +1607,9 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) } else if (!strcmp(featurestr, "enforce")) { check_cpuid = enforce_cpuid = 1; } else if (!strcmp(featurestr, "hv_relaxed")) { - hyperv_enable_relaxed_timing(true); + cpu->hyperv_relaxed_timing = true; } else if (!strcmp(featurestr, "hv_vapic")) { - hyperv_enable_vapic_recommended(true); + cpu->hyperv_vapic = true; } else { error_setg(errp, "feature string `%s' not in format (+feature|" "-feature|feature=xyz)", featurestr); @@ -2479,6 +2484,7 @@ static void x86_cpu_initfn(Object *obj) x86_cpu_get_feature_words, NULL, NULL, (void *)cpu->filtered_features, NULL); + cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index); /* init various static tables used in TCG mode */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2d005b3..6c3eb86 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -549,6 +549,10 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ +#ifndef HYPERV_SPINLOCK_NEVER_RETRY +#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF +#endif + #define EXCP00_DIVZ 0 #define EXCP01_DB 1 #define EXCP02_NMI 2 diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c deleted file mode 100644 index f284e99..0000000 --- a/target-i386/hyperv.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * QEMU Hyper-V support - * - * Copyright Red Hat, Inc. 2011 - * - * Author: Vadim Rozenfeld <vrozenfe@redhat.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include "hyperv.h" - -static bool hyperv_vapic; -static bool hyperv_relaxed_timing; -static int hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; - -void hyperv_enable_vapic_recommended(bool val) -{ - hyperv_vapic = val; -} - -void hyperv_enable_relaxed_timing(bool val) -{ - hyperv_relaxed_timing = val; -} - -void hyperv_set_spinlock_retries(int val) -{ - hyperv_spinlock_attempts = val; - if (hyperv_spinlock_attempts < 0xFFF) { - hyperv_spinlock_attempts = 0xFFF; - } -} - -bool hyperv_enabled(void) -{ - return hyperv_hypercall_available() || hyperv_relaxed_timing_enabled(); -} - -bool hyperv_hypercall_available(void) -{ - if (hyperv_vapic || - (hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY)) { - return true; - } - return false; -} - -bool hyperv_vapic_recommended(void) -{ - return hyperv_vapic; -} - -bool hyperv_relaxed_timing_enabled(void) -{ - return hyperv_relaxed_timing; -} - -int hyperv_get_spinlock_retries(void) -{ - return hyperv_spinlock_attempts; -} diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h deleted file mode 100644 index bacb1d4..0000000 --- a/target-i386/hyperv.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * QEMU Hyper-V support - * - * Copyright Red Hat, Inc. 2011 - * - * Author: Vadim Rozenfeld <vrozenfe@redhat.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#ifndef QEMU_HW_HYPERV_H -#define QEMU_HW_HYPERV_H 1 - -#include "qemu-common.h" -#ifdef CONFIG_KVM -#include <asm/hyperv.h> -#endif - -#ifndef HYPERV_SPINLOCK_NEVER_RETRY -#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF -#endif - -#ifndef KVM_CPUID_SIGNATURE_NEXT -#define KVM_CPUID_SIGNATURE_NEXT 0x40000100 -#endif - -#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_KVM) -void hyperv_enable_vapic_recommended(bool val); -void hyperv_enable_relaxed_timing(bool val); -void hyperv_set_spinlock_retries(int val); -#else -static inline void hyperv_enable_vapic_recommended(bool val) { } -static inline void hyperv_enable_relaxed_timing(bool val) { } -static inline void hyperv_set_spinlock_retries(int val) { } -#endif - -bool hyperv_enabled(void); -bool hyperv_hypercall_available(void); -bool hyperv_vapic_recommended(void); -bool hyperv_relaxed_timing_enabled(void); -int hyperv_get_spinlock_retries(void); - -#endif /* QEMU_HW_HYPERV_H */ diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 935ef63..ded4743 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -31,7 +31,7 @@ #include "hw/i386/pc.h" #include "hw/i386/apic.h" #include "exec/ioport.h" -#include "hyperv.h" +#include <asm/hyperv.h> #include "hw/pci/pci.h" //#define DEBUG_KVM @@ -420,6 +420,22 @@ unsigned long kvm_arch_vcpu_id(CPUState *cs) return cpu->env.cpuid_apic_id; } +#ifndef KVM_CPUID_SIGNATURE_NEXT +#define KVM_CPUID_SIGNATURE_NEXT 0x40000100 +#endif + +static bool hyperv_hypercall_available(X86CPU *cpu) +{ + return cpu->hyperv_vapic || + (cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY); +} + +static bool hyperv_enabled(X86CPU *cpu) +{ + return hyperv_hypercall_available(cpu) || + cpu->hyperv_relaxed_timing; +} + #define KVM_MAX_CPUID_ENTRIES 100 int kvm_arch_init_vcpu(CPUState *cs) @@ -442,7 +458,7 @@ int kvm_arch_init_vcpu(CPUState *cs) c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_SIGNATURE; - if (!hyperv_enabled()) { + if (!hyperv_enabled(cpu)) { memcpy(signature, "KVMKVMKVM\0\0\0", 12); c->eax = 0; } else { @@ -458,7 +474,7 @@ int kvm_arch_init_vcpu(CPUState *cs) c->function = KVM_CPUID_FEATURES; c->eax = env->features[FEAT_KVM]; - if (hyperv_enabled()) { + if (hyperv_enabled(cpu)) { memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12); c->eax = signature[0]; @@ -471,10 +487,10 @@ int kvm_arch_init_vcpu(CPUState *cs) c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_FEATURES; - if (hyperv_relaxed_timing_enabled()) { + if (cpu->hyperv_relaxed_timing) { c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; } - if (hyperv_vapic_recommended()) { + if (cpu->hyperv_vapic) { c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE; } @@ -482,13 +498,13 @@ int kvm_arch_init_vcpu(CPUState *cs) c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_ENLIGHTMENT_INFO; - if (hyperv_relaxed_timing_enabled()) { + if (cpu->hyperv_relaxed_timing) { c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED; } - if (hyperv_vapic_recommended()) { + if (cpu->hyperv_vapic) { c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED; } - c->ebx = hyperv_get_spinlock_retries(); + c->ebx = cpu->hyperv_spinlock_attempts; c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); @@ -1117,11 +1133,11 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME, env->steal_time_msr); } - if (hyperv_hypercall_available()) { + if (hyperv_hypercall_available(cpu)) { kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0); kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0); } - if (hyperv_vapic_recommended()) { + if (cpu->hyperv_vapic) { kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0); } }