lkml.org 
[lkml]   [2022]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6.0 178/862] KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
    Date
    From: Sean Christopherson <seanjc@google.com>

    commit eba9799b5a6efe2993cf92529608e4aa8163d73b upstream.

    Deliberately truncate the exception error code when shoving it into the
    VMCS (VM-Entry field for vmcs01 and vmcs02, VM-Exit field for vmcs12).
    Intel CPUs are incapable of handling 32-bit error codes and will never
    generate an error code with bits 31:16, but userspace can provide an
    arbitrary error code via KVM_SET_VCPU_EVENTS. Failure to drop the bits
    on exception injection results in failed VM-Entry, as VMX disallows
    setting bits 31:16. Setting the bits on VM-Exit would at best confuse
    L1, and at worse induce a nested VM-Entry failure, e.g. if L1 decided to
    reinject the exception back into L2.

    Cc: stable@vger.kernel.org
    Signed-off-by: Sean Christopherson <seanjc@google.com>
    Reviewed-by: Jim Mattson <jmattson@google.com>
    Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
    Link: https://lore.kernel.org/r/20220830231614.3580124-3-seanjc@google.com
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/x86/kvm/vmx/nested.c | 11 ++++++++++-
    arch/x86/kvm/vmx/vmx.c | 12 +++++++++++-
    2 files changed, 21 insertions(+), 2 deletions(-)

    --- a/arch/x86/kvm/vmx/nested.c
    +++ b/arch/x86/kvm/vmx/nested.c
    @@ -3832,7 +3832,16 @@ static void nested_vmx_inject_exception_
    u32 intr_info = nr | INTR_INFO_VALID_MASK;

    if (vcpu->arch.exception.has_error_code) {
    - vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code;
    + /*
    + * Intel CPUs do not generate error codes with bits 31:16 set,
    + * and more importantly VMX disallows setting bits 31:16 in the
    + * injected error code for VM-Entry. Drop the bits to mimic
    + * hardware and avoid inducing failure on nested VM-Entry if L1
    + * chooses to inject the exception back to L2. AMD CPUs _do_
    + * generate "full" 32-bit error codes, so KVM allows userspace
    + * to inject exception error codes with bits 31:16 set.
    + */
    + vmcs12->vm_exit_intr_error_code = (u16)vcpu->arch.exception.error_code;
    intr_info |= INTR_INFO_DELIVER_CODE_MASK;
    }

    --- a/arch/x86/kvm/vmx/vmx.c
    +++ b/arch/x86/kvm/vmx/vmx.c
    @@ -1695,7 +1695,17 @@ static void vmx_queue_exception(struct k
    kvm_deliver_exception_payload(vcpu);

    if (has_error_code) {
    - vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
    + /*
    + * Despite the error code being architecturally defined as 32
    + * bits, and the VMCS field being 32 bits, Intel CPUs and thus
    + * VMX don't actually supporting setting bits 31:16. Hardware
    + * will (should) never provide a bogus error code, but AMD CPUs
    + * do generate error codes with bits 31:16 set, and so KVM's
    + * ABI lets userspace shove in arbitrary 32-bit values. Drop
    + * the upper bits to avoid VM-Fail, losing information that
    + * does't really exist is preferable to killing the VM.
    + */
    + vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, (u16)error_code);
    intr_info |= INTR_INFO_DELIVER_CODE_MASK;
    }


    \
     
     \ /
      Last update: 2022-10-19 10:51    [W:4.041 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site