diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index c2edb64..5c85492 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -778,6 +778,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) hyperv_enable_relaxed_timing(true); } else if (!strcmp(featurestr, "hv_vapic")) { hyperv_enable_vapic_recommended(true); + } else if (!strcmp(featurestr, "hv_refcnt")) { + hyperv_enable_ref_count(true); } else { fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); goto error; diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c index f284e99..13a1cb7 100644 --- a/target-i386/hyperv.c +++ b/target-i386/hyperv.c @@ -15,6 +15,7 @@ static bool hyperv_vapic; static bool hyperv_relaxed_timing; static int hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; +static bool hyperv_ref_count; void hyperv_enable_vapic_recommended(bool val) { @@ -34,9 +35,17 @@ void hyperv_set_spinlock_retries(int val) } } +void hyperv_enable_ref_count(bool val) +{ + hyperv_ref_count = val; +} + bool hyperv_enabled(void) { - return hyperv_hypercall_available() || hyperv_relaxed_timing_enabled(); + return hyperv_hypercall_available() || + hyperv_relaxed_timing_enabled() || + hyperv_ref_counter_enabled(); } bool hyperv_hypercall_available(void) @@ -62,3 +71,9 @@ int hyperv_get_spinlock_retries(void) { return hyperv_spinlock_attempts; } + +bool hyperv_ref_counter_enabled(void) +{ + return hyperv_ref_count; +} diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h index bacb1d4..a65aa5f 100644 --- a/target-i386/hyperv.h +++ b/target-i386/hyperv.h @@ -30,10 +30,12 @@ void hyperv_enable_vapic_recommended(bool val); void hyperv_enable_relaxed_timing(bool val); void hyperv_set_spinlock_retries(int val); +void hyperv_enable_ref_count(bool 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) { } +static inline void hyperv_enable_ref_count(bool val) {} #endif bool hyperv_enabled(void); @@ -41,5 +43,5 @@ bool hyperv_hypercall_available(void); bool hyperv_vapic_recommended(void); bool hyperv_relaxed_timing_enabled(void); int hyperv_get_spinlock_retries(void); - +bool hyperv_ref_counter_enabled(void); #endif /* QEMU_HW_HYPERV_H */ diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 9a73207..31ca04a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -414,7 +414,12 @@ int kvm_arch_init_vcpu(CPUState *env) c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE; } - + if (hyperv_ref_counter_enabled()) { + c->eax |= HV_X64_MSR_TIME_REF_COUNT_AVAILABLE; + c->eax |= 0x200; + } c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;