> On 28. Sep 2026, at 22:00, Doug Cook (WINDOWS) <[email protected]> wrote:
>
> 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]>
Reviewed-by: Mohamed Mediouni <[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
>