lkml.org 
[lkml]   [2022]   [Aug]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v5 02/27] KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
    From
    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>
    ---
    arch/x86/kvm/vmx/nested.c | 11 ++++++++++-
    arch/x86/kvm/vmx/vmx.c | 12 +++++++++++-
    2 files changed, 21 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
    index ca07d4ce4383..2ca8f1ad9c59 100644
    --- a/arch/x86/kvm/vmx/nested.c
    +++ b/arch/x86/kvm/vmx/nested.c
    @@ -3827,7 +3827,16 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu,
    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;
    }

    diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
    index c9b49a09e6b5..7f3581960eb5 100644
    --- a/arch/x86/kvm/vmx/vmx.c
    +++ b/arch/x86/kvm/vmx/vmx.c
    @@ -1695,7 +1695,17 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu)
    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;
    }

    --
    2.37.2.672.g94769d06f0-goog
    \
     
     \ /
      Last update: 2022-08-31 01:18    [W:3.520 / U:1.140 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site