On Fri, Jan 07, 2022, Vitaly Kuznetsov wrote: > Hyper-V TLFS explicitly forbids VMREAD and VMWRITE instructions when > Enlightened VMCS interface is in use: > > "Any VMREAD or VMWRITE instructions while an enlightened VMCS is > active is unsupported and can result in unexpected behavior."" > > Windows 11 + WSL2 seems to ignore this, attempts to VMREAD VMCS field > 0x4404 ("VM-exit interruption information") are observed. Failing > these attempts with nested_vmx_failInvalid() makes such guests > unbootable. > > Microsoft confirms this is a Hyper-V bug and claims that it'll get fixed > eventually but for the time being we need a workaround. (Temporary) allow > VMREAD to get data from the currently loaded Enlightened VMCS. > > Note: VMWRITE instructions remain forbidden, it is not clear how to > handle them properly and hopefully won't ever be needed. > > Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> > --- Reviewed-by: Sean Christopherson <seanjc@xxxxxxxxxx> > + /* > + * Hyper-V TLFS (as of 6.0b) explicitly states, that while an > + * enlightened VMCS is active VMREAD/VMWRITE instructions are > + * unsupported. Unfortunately, certain versions of Windows 11 > + * don't comply with this requirement which is not enforced in > + * genuine Hyper-V so KVM has implement a workaround allowing to Nit, missing a "to". But rather say what KVM "has" to do, maybe this? * genuine Hyper-V. Allow VMREAD from an enlightened VMCS as a * workaround, as misbehaving guests will panic on VM-Fail. > + * read from enlightened VMCS with VMREAD. > + * Note, enlightened VMCS is incompatible with shadow VMCS so > + * all VMREADs from L2 should go to L1. > + */ > + if (WARN_ON_ONCE(is_guest_mode(vcpu))) > + return nested_vmx_failInvalid(vcpu); > > - /* Read the field, zero-extended to a u64 value */ > - value = vmcs12_read_any(vmcs12, field, offset); > + offset = evmcs_field_offset(field, NULL); > + if (offset < 0) > + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); > + > + /* Read the field, zero-extended to a u64 value */ > + value = evmcs_read_any(vmx->nested.hv_evmcs, field, offset); > + } > > /* > * Now copy part of this value to register or memory, as requested. > -- > 2.33.1 >