diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 57282246c6..413f57df36 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1136,7 +1136,7 @@ static bool hyperv_feature_supported(CPUState *cs, int feature) return true; } -static int hv_cpuid_check_and_set(CPUState *cs, int feature) +static int hv_cpuid_check_and_set(CPUState *cs, int feature, Error **errp) { X86CPU *cpu = X86_CPU(cs); uint64_t deps; @@ -1150,20 +1150,18 @@ static int hv_cpuid_check_and_set(CPUState *cs, int feature) while (deps) { dep_feat = ctz64(deps); if (!(hyperv_feat_enabled(cpu, dep_feat))) { - fprintf(stderr, - "Hyper-V %s requires Hyper-V %s\n", - kvm_hyperv_properties[feature].desc, - kvm_hyperv_properties[dep_feat].desc); - return 1; + error_setg(errp, "Hyper-V %s requires Hyper-V %s", + kvm_hyperv_properties[feature].desc, + kvm_hyperv_properties[dep_feat].desc); + return 1; } deps &= ~(1ull << dep_feat); } if (!hyperv_feature_supported(cs, feature)) { if (hyperv_feat_enabled(cpu, feature)) { - fprintf(stderr, - "Hyper-V %s is not supported by kernel\n", - kvm_hyperv_properties[feature].desc); + error_setg(errp, "Hyper-V %s is not supported by kernel", + kvm_hyperv_properties[feature].desc); return 1; } else { return 0; @@ -1210,13 +1208,12 @@ static uint32_t hv_build_cpuid_leaf(CPUState *cs, uint32_t func, int reg) * of 'hv_passthrough' mode and fills the environment with all supported * Hyper-V features. */ -static int hyperv_expand_features(CPUState *cs) +static void hyperv_expand_features(CPUState *cs, Error **errp) { X86CPU *cpu = X86_CPU(cs); - int r; if (!hyperv_enabled(cpu)) - return 0; + return; if (cpu->hyperv_passthrough) { cpu->hyperv_vendor_id[0] = @@ -1263,37 +1260,60 @@ static int hyperv_expand_features(CPUState *cs) } /* Features */ - r = hv_cpuid_check_and_set(cs, HYPERV_FEAT_RELAXED); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_VAPIC); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_TIME); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_CRASH); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_RESET); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_VPINDEX); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_RUNTIME); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_SYNIC); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_STIMER); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_FREQUENCIES); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_REENLIGHTENMENT); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_TLBFLUSH); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_EVMCS); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_IPI); - r |= hv_cpuid_check_and_set(cs, HYPERV_FEAT_STIMER_DIRECT); + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_RELAXED, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_VAPIC, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_TIME, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_CRASH, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_RESET, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_VPINDEX, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_RUNTIME, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_SYNIC, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_STIMER, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_FREQUENCIES, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_REENLIGHTENMENT, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_TLBFLUSH, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_EVMCS, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_IPI, errp)) { + return; + } + if (hv_cpuid_check_and_set(cs, HYPERV_FEAT_STIMER_DIRECT, errp)) { + return; + } /* Additional dependencies not covered by kvm_hyperv_properties[] */ if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNIC) && !cpu->hyperv_synic_kvm_only && !hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX)) { - fprintf(stderr, "Hyper-V %s requires Hyper-V %s\n", - kvm_hyperv_properties[HYPERV_FEAT_SYNIC].desc, - kvm_hyperv_properties[HYPERV_FEAT_VPINDEX].desc); - r |= 1; + error_setg(errp, "Hyper-V %s requires Hyper-V %s", + kvm_hyperv_properties[HYPERV_FEAT_SYNIC].desc, + kvm_hyperv_properties[HYPERV_FEAT_VPINDEX].desc); } - - if (r) { - return -ENOSYS; - } - - return 0; } /* @@ -1528,9 +1548,10 @@ int kvm_arch_init_vcpu(CPUState *cs) env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY; /* Paravirtualization CPUIDs */ - r = hyperv_expand_features(cs); - if (r < 0) { - return r; + hyperv_expand_features(cs, &local_err); + if (local_err) { + error_report_err(local_err); + return -ENOSYS; } if (hyperv_enabled(cpu)) {