i386/kvm: expose HV_CPUID_ENLIGHTMENT_INFO.EAX and HV_CPUID_NESTED_FEATURES.EAX as feature words
It was found that QMP users of QEMU (e.g. libvirt) may need HV_CPUID_ENLIGHTMENT_INFO.EAX/HV_CPUID_NESTED_FEATURES.EAX information. In particular, 'hv_tlbflush' and 'hv_evmcs' enlightenments are only exposed in HV_CPUID_ENLIGHTMENT_INFO.EAX. HV_CPUID_NESTED_FEATURES.EAX is exposed for two reasons: convenience (we don't need to export it from hyperv_handle_properties() and as future-proof for Enlightened MSR-Bitmap, PV EPT invalidation and direct virtual flush features. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Message-Id: <20181126135958.20956-1-vkuznets@redhat.com> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
7260438b70
commit
a2b107dbbd
@ -980,6 +980,36 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|||||||
},
|
},
|
||||||
.cpuid = { .eax = 0x40000003, .reg = R_EDX, },
|
.cpuid = { .eax = 0x40000003, .reg = R_EDX, },
|
||||||
},
|
},
|
||||||
|
[FEAT_HV_RECOMM_EAX] = {
|
||||||
|
.type = CPUID_FEATURE_WORD,
|
||||||
|
.feat_names = {
|
||||||
|
NULL /* hv_recommend_pv_as_switch */,
|
||||||
|
NULL /* hv_recommend_pv_tlbflush_local */,
|
||||||
|
NULL /* hv_recommend_pv_tlbflush_remote */,
|
||||||
|
NULL /* hv_recommend_msr_apic_access */,
|
||||||
|
NULL /* hv_recommend_msr_reset */,
|
||||||
|
NULL /* hv_recommend_relaxed_timing */,
|
||||||
|
NULL /* hv_recommend_dma_remapping */,
|
||||||
|
NULL /* hv_recommend_int_remapping */,
|
||||||
|
NULL /* hv_recommend_x2apic_msrs */,
|
||||||
|
NULL /* hv_recommend_autoeoi_deprecation */,
|
||||||
|
NULL /* hv_recommend_pv_ipi */,
|
||||||
|
NULL /* hv_recommend_ex_hypercalls */,
|
||||||
|
NULL /* hv_hypervisor_is_nested */,
|
||||||
|
NULL /* hv_recommend_int_mbec */,
|
||||||
|
NULL /* hv_recommend_evmcs */,
|
||||||
|
NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
},
|
||||||
|
.cpuid = { .eax = 0x40000004, .reg = R_EAX, },
|
||||||
|
},
|
||||||
|
[FEAT_HV_NESTED_EAX] = {
|
||||||
|
.type = CPUID_FEATURE_WORD,
|
||||||
|
.cpuid = { .eax = 0x4000000A, .reg = R_EAX, },
|
||||||
|
},
|
||||||
[FEAT_SVM] = {
|
[FEAT_SVM] = {
|
||||||
.type = CPUID_FEATURE_WORD,
|
.type = CPUID_FEATURE_WORD,
|
||||||
.feat_names = {
|
.feat_names = {
|
||||||
|
@ -497,6 +497,8 @@ typedef enum FeatureWord {
|
|||||||
FEAT_HYPERV_EAX, /* CPUID[4000_0003].EAX */
|
FEAT_HYPERV_EAX, /* CPUID[4000_0003].EAX */
|
||||||
FEAT_HYPERV_EBX, /* CPUID[4000_0003].EBX */
|
FEAT_HYPERV_EBX, /* CPUID[4000_0003].EBX */
|
||||||
FEAT_HYPERV_EDX, /* CPUID[4000_0003].EDX */
|
FEAT_HYPERV_EDX, /* CPUID[4000_0003].EDX */
|
||||||
|
FEAT_HV_RECOMM_EAX, /* CPUID[4000_0004].EAX */
|
||||||
|
FEAT_HV_NESTED_EAX, /* CPUID[4000_000A].EAX */
|
||||||
FEAT_SVM, /* CPUID[8000_000A].EDX */
|
FEAT_SVM, /* CPUID[8000_000A].EDX */
|
||||||
FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */
|
FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */
|
||||||
FEAT_6_EAX, /* CPUID[6].EAX */
|
FEAT_6_EAX, /* CPUID[6].EAX */
|
||||||
|
@ -798,6 +798,48 @@ static int hyperv_handle_properties(CPUState *cs)
|
|||||||
}
|
}
|
||||||
env->features[FEAT_HYPERV_EAX] |= HV_SYNTIMERS_AVAILABLE;
|
env->features[FEAT_HYPERV_EAX] |= HV_SYNTIMERS_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
if (cpu->hyperv_relaxed_timing) {
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_RELAXED_TIMING_RECOMMENDED;
|
||||||
|
}
|
||||||
|
if (cpu->hyperv_vapic) {
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_APIC_ACCESS_RECOMMENDED;
|
||||||
|
}
|
||||||
|
if (cpu->hyperv_tlbflush) {
|
||||||
|
if (kvm_check_extension(cs->kvm_state,
|
||||||
|
KVM_CAP_HYPERV_TLBFLUSH) <= 0) {
|
||||||
|
fprintf(stderr, "Hyper-V TLB flush support "
|
||||||
|
"(requested by 'hv-tlbflush' cpu flag) "
|
||||||
|
" is not supported by kernel\n");
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_REMOTE_TLB_FLUSH_RECOMMENDED;
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
|
||||||
|
}
|
||||||
|
if (cpu->hyperv_ipi) {
|
||||||
|
if (kvm_check_extension(cs->kvm_state,
|
||||||
|
KVM_CAP_HYPERV_SEND_IPI) <= 0) {
|
||||||
|
fprintf(stderr, "Hyper-V IPI send support "
|
||||||
|
"(requested by 'hv-ipi' cpu flag) "
|
||||||
|
" is not supported by kernel\n");
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_CLUSTER_IPI_RECOMMENDED;
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
|
||||||
|
}
|
||||||
|
if (cpu->hyperv_evmcs) {
|
||||||
|
uint16_t evmcs_version;
|
||||||
|
|
||||||
|
if (kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0,
|
||||||
|
(uintptr_t)&evmcs_version)) {
|
||||||
|
fprintf(stderr, "Hyper-V Enlightened VMCS "
|
||||||
|
"(requested by 'hv-evmcs' cpu flag) "
|
||||||
|
"is not supported by kernel\n");
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
env->features[FEAT_HV_RECOMM_EAX] |= HV_ENLIGHTENED_VMCS_RECOMMENDED;
|
||||||
|
env->features[FEAT_HV_NESTED_EAX] = evmcs_version;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -879,7 +921,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
uint32_t unused;
|
uint32_t unused;
|
||||||
struct kvm_cpuid_entry2 *c;
|
struct kvm_cpuid_entry2 *c;
|
||||||
uint32_t signature[3];
|
uint32_t signature[3];
|
||||||
uint16_t evmcs_version;
|
|
||||||
int kvm_base = KVM_CPUID_SIGNATURE;
|
int kvm_base = KVM_CPUID_SIGNATURE;
|
||||||
int r;
|
int r;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@ -954,44 +995,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
|
|
||||||
c = &cpuid_data.entries[cpuid_i++];
|
c = &cpuid_data.entries[cpuid_i++];
|
||||||
c->function = HV_CPUID_ENLIGHTMENT_INFO;
|
c->function = HV_CPUID_ENLIGHTMENT_INFO;
|
||||||
if (cpu->hyperv_relaxed_timing) {
|
|
||||||
c->eax |= HV_RELAXED_TIMING_RECOMMENDED;
|
c->eax = env->features[FEAT_HV_RECOMM_EAX];
|
||||||
}
|
|
||||||
if (cpu->hyperv_vapic) {
|
|
||||||
c->eax |= HV_APIC_ACCESS_RECOMMENDED;
|
|
||||||
}
|
|
||||||
if (cpu->hyperv_tlbflush) {
|
|
||||||
if (kvm_check_extension(cs->kvm_state,
|
|
||||||
KVM_CAP_HYPERV_TLBFLUSH) <= 0) {
|
|
||||||
fprintf(stderr, "Hyper-V TLB flush support "
|
|
||||||
"(requested by 'hv-tlbflush' cpu flag) "
|
|
||||||
" is not supported by kernel\n");
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
c->eax |= HV_REMOTE_TLB_FLUSH_RECOMMENDED;
|
|
||||||
c->eax |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
|
|
||||||
}
|
|
||||||
if (cpu->hyperv_ipi) {
|
|
||||||
if (kvm_check_extension(cs->kvm_state,
|
|
||||||
KVM_CAP_HYPERV_SEND_IPI) <= 0) {
|
|
||||||
fprintf(stderr, "Hyper-V IPI send support "
|
|
||||||
"(requested by 'hv-ipi' cpu flag) "
|
|
||||||
" is not supported by kernel\n");
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
c->eax |= HV_CLUSTER_IPI_RECOMMENDED;
|
|
||||||
c->eax |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
|
|
||||||
}
|
|
||||||
if (cpu->hyperv_evmcs) {
|
|
||||||
if (kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, 0,
|
|
||||||
(uintptr_t)&evmcs_version)) {
|
|
||||||
fprintf(stderr, "Hyper-V Enlightened VMCS "
|
|
||||||
"(requested by 'hv-evmcs' cpu flag) "
|
|
||||||
"is not supported by kernel\n");
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
c->eax |= HV_ENLIGHTENED_VMCS_RECOMMENDED;
|
|
||||||
}
|
|
||||||
c->ebx = cpu->hyperv_spinlock_attempts;
|
c->ebx = cpu->hyperv_spinlock_attempts;
|
||||||
|
|
||||||
c = &cpuid_data.entries[cpuid_i++];
|
c = &cpuid_data.entries[cpuid_i++];
|
||||||
@ -1015,7 +1020,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
|
|
||||||
c = &cpuid_data.entries[cpuid_i++];
|
c = &cpuid_data.entries[cpuid_i++];
|
||||||
c->function = HV_CPUID_NESTED_FEATURES;
|
c->function = HV_CPUID_NESTED_FEATURES;
|
||||||
c->eax = evmcs_version;
|
c->eax = env->features[FEAT_HV_NESTED_EAX];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user