diff options
Diffstat (limited to 'target/i386/kvm')
-rw-r--r-- | target/i386/kvm/kvm.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 346528c649..712285df40 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1108,13 +1108,33 @@ static int hv_cpuid_get_fw(struct kvm_cpuid2 *cpuid, int fw, uint32_t *r) return 0; } +static bool hyperv_feature_supported(struct kvm_cpuid2 *cpuid, int feature) +{ + uint32_t r, fw, bits; + int i; + + for (i = 0; i < ARRAY_SIZE(kvm_hyperv_properties[feature].flags); i++) { + fw = kvm_hyperv_properties[feature].flags[i].fw; + bits = kvm_hyperv_properties[feature].flags[i].bits; + + if (!fw) { + continue; + } + + if (hv_cpuid_get_fw(cpuid, fw, &r) || (r & bits) != bits) { + return false; + } + } + + return true; +} + static int hv_cpuid_check_and_set(CPUState *cs, struct kvm_cpuid2 *cpuid, int feature) { X86CPU *cpu = X86_CPU(cs); - uint32_t r, fw, bits; uint64_t deps; - int i, dep_feat; + int dep_feat; if (!hyperv_feat_enabled(cpu, feature) && !cpu->hyperv_passthrough) { return 0; @@ -1133,23 +1153,14 @@ static int hv_cpuid_check_and_set(CPUState *cs, struct kvm_cpuid2 *cpuid, deps &= ~(1ull << dep_feat); } - for (i = 0; i < ARRAY_SIZE(kvm_hyperv_properties[feature].flags); i++) { - fw = kvm_hyperv_properties[feature].flags[i].fw; - bits = kvm_hyperv_properties[feature].flags[i].bits; - - if (!fw) { - continue; - } - - if (hv_cpuid_get_fw(cpuid, fw, &r) || (r & bits) != bits) { - if (hyperv_feat_enabled(cpu, feature)) { - fprintf(stderr, - "Hyper-V %s is not supported by kernel\n", - kvm_hyperv_properties[feature].desc); - return 1; - } else { - return 0; - } + if (!hyperv_feature_supported(cpuid, feature)) { + if (hyperv_feat_enabled(cpu, feature)) { + fprintf(stderr, + "Hyper-V %s is not supported by kernel\n", + kvm_hyperv_properties[feature].desc); + return 1; + } else { + return 0; } } |