Skip to content
  • Sean Christopherson's avatar
    KVM: x86: Perform non-canonical checks in 32-bit KVM · de761ea7
    Sean Christopherson authored
    
    
    Remove the CONFIG_X86_64 condition from the low level non-canonical
    helpers to effectively enable non-canonical checks on 32-bit KVM.
    Non-canonical checks are performed by hardware if the CPU *supports*
    64-bit mode, whether or not the CPU is actually in 64-bit mode is
    irrelevant.
    
    For the most part, skipping non-canonical checks on 32-bit KVM is ok-ish
    because 32-bit KVM always (hopefully) drops bits 63:32 of whatever value
    it's checking before propagating it to hardware, and architecturally,
    the expected behavior for the guest is a bit of a grey area since the
    vCPU itself doesn't support 64-bit mode.  I.e. a 32-bit KVM guest can
    observe the missed checks in several paths, e.g. INVVPID and VM-Enter,
    but it's debatable whether or not the missed checks constitute a bug
    because technically the vCPU doesn't support 64-bit mode.
    
    The primary motivation for enabling the non-canonical checks is defense
    in depth.  As mentioned above, a guest can trigger a missed check via
    INVVPID or VM-Enter.  INVVPID is straightforward as it takes a 64-bit
    virtual address as part of its 128-bit INVVPID descriptor and fails if
    the address is non-canonical, even if INVVPID is executed in 32-bit PM.
    Nested VM-Enter is a bit more convoluted as it requires the guest to
    write natural width VMCS fields via memory accesses and then VMPTRLD the
    VMCS, but it's still possible.  In both cases, KVM is saved from a true
    bug only because its flows that propagate values to hardware (correctly)
    take "unsigned long" parameters and so drop bits 63:32 of the bad value.
    
    Explicitly performing the non-canonical checks makes it less likely that
    a bad value will be propagated to hardware, e.g. in the INVVPID case,
    if __invvpid() didn't implicitly drop bits 63:32 then KVM would BUG() on
    the resulting unexpected INVVPID failure due to hardware rejecting the
    non-canonical address.
    
    The only downside to enabling the non-canonical checks is that it adds a
    relatively small amount of overhead, but the affected flows are not hot
    paths, i.e. the overhead is negligible.
    
    Note, KVM technically could gate the non-canonical checks on 32-bit KVM
    with static_cpu_has(X86_FEATURE_LM), but on bare metal that's an even
    bigger waste of code for everyone except the 0.00000000000001% of the
    population running on Yonah, and nested 32-bit on 64-bit already fudges
    things with respect to 64-bit CPU behavior.
    
    Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
    [Also do so in nested_vmx_check_host_state as reported by Krish. - Paolo]
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    de761ea7