From: Doug Cook <[email protected]> whpx_get_supported_msr_feature() had two bugs in how it reports the VMX control MSRs:
- MSR_IA32_VMX_TRUE_PINBASED_CTLS and MSR_IA32_VMX_TRUE_PROCBASED_CTLS were queried using the non-TRUE capability codes (WHvCapabilityCodeVmxPinbasedCtls and WHvCapabilityCodeVmxProcbasedCtls). - For PROCBASED_CTLS2 and the four TRUE_* control MSRs, the raw allowed-0/allowed-1 pair was returned. The feature-word code expects only the bits that may be 1 but are not required to be 1. Apply the same transformation as kvm_arch_get_supported_msr_feature(); make_vmx_msr_value() adds the must-be-one bits back afterwards. As a result, with +vmx QEMU treated many VMX features the host does support (secondary controls, EPT, VPID, MSR bitmaps, ...) as missing, warned about each of them, and dropped them from the CPU model. The guest itself reads the VMX MSRs from the hypervisor, not from QEMU, so this did not change what the guest saw. Signed-off-by: Doug Cook <[email protected]> --- target/i386/whpx/whpx-all.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index bc6c1e00a2..8fd6b3ce2b 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -1516,10 +1516,10 @@ uint64_t whpx_get_supported_msr_feature(uint32_t index) cap = WHvCapabilityCodeVmxEptVpidCap; break; case MSR_IA32_VMX_TRUE_PINBASED_CTLS: - cap = WHvCapabilityCodeVmxPinbasedCtls; + cap = WHvCapabilityCodeVmxTruePinbasedCtls; break; case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: - cap = WHvCapabilityCodeVmxProcbasedCtls; + cap = WHvCapabilityCodeVmxTrueProcbasedCtls; break; case MSR_IA32_VMX_TRUE_ENTRY_CTLS: cap = WHvCapabilityCodeVmxTrueEntryCtls; @@ -1538,6 +1538,31 @@ uint64_t whpx_get_supported_msr_feature(uint32_t index) if (FAILED(hr)) { return 0; } + + switch (index) { + case MSR_IA32_VMX_PROCBASED_CTLS2: + case MSR_IA32_VMX_TRUE_PINBASED_CTLS: + case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: + case MSR_IA32_VMX_TRUE_ENTRY_CTLS: + case MSR_IA32_VMX_TRUE_EXIT_CTLS: { + /* + * These MSRs hold the allowed-0 settings in the low half and the + * allowed-1 settings in the high half. QEMU's feature words want + * only the bits that can be one but do not have to be one, so + * apply the same transformation as + * kvm_arch_get_supported_msr_feature(); make_vmx_msr_value() + * restores the must-be-one bits later. + */ + uint32_t must_be_one = (uint32_t)val; + uint32_t can_be_one = (uint32_t)(val >> 32); + + val = can_be_one & ~must_be_one; + break; + } + default: + break; + } + return val; } return 0; -- 2.55.0.vfs.0.8
