lkml.org 
[lkml]   [2020]   [Mar]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 6/9] kvm: vmx: Extend VMX's #AC interceptor to handle split lock #AC happens in guest
    Date
    There are two types of #AC can be generated in Intel CPUs:
    1. legacy alignment check #AC;
    2. split lock #AC;

    Legacy alignment check #AC can be injected to guest if guest has enabled
    alignemnet check.

    when host enables split lock detectin, i.e., sld_warn or sld_fatal,
    there will be an unexpected #AC in guest and intercepted by KVM because
    KVM doesn't virtualize this feature to guest and hardware value of
    MSR_TEST_CTRL.SLD bit stays unchanged when vcpu is running.

    To handle this unexpected #AC, treat guest just like host usermode that
    calling handle_user_split_lock():
    - If host is sld_warn, it warns and set TIF_SLD so that __switch_to_xtra()
    does the MSR_TEST_CTRL.SLD bit switching when control transfer to/from
    this vcpu.
    - If host is sld_fatal, forward #AC to userspace, the similar as sending
    SIGBUS.

    Suggested-by: Sean Christopherson <sean.j.christopherson@intel.com>
    Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
    ---
    arch/x86/kvm/vmx/vmx.c | 30 +++++++++++++++++++++++++++---
    1 file changed, 27 insertions(+), 3 deletions(-)

    diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
    index 40b1e6138cd5..3fb132ad489d 100644
    --- a/arch/x86/kvm/vmx/vmx.c
    +++ b/arch/x86/kvm/vmx/vmx.c
    @@ -4609,6 +4609,12 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)
    return 1;
    }

    +static inline bool guest_cpu_alignment_check_enabled(struct kvm_vcpu *vcpu)
    +{
    + return vmx_get_cpl(vcpu) == 3 && kvm_read_cr0_bits(vcpu, X86_CR0_AM) &&
    + (kvm_get_rflags(vcpu) & X86_EFLAGS_AC);
    +}
    +
    static int handle_exception_nmi(struct kvm_vcpu *vcpu)
    {
    struct vcpu_vmx *vmx = to_vmx(vcpu);
    @@ -4674,9 +4680,6 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
    return handle_rmode_exception(vcpu, ex_no, error_code);

    switch (ex_no) {
    - case AC_VECTOR:
    - kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
    - return 1;
    case DB_VECTOR:
    dr6 = vmcs_readl(EXIT_QUALIFICATION);
    if (!(vcpu->guest_debug &
    @@ -4705,6 +4708,27 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
    kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
    kvm_run->debug.arch.exception = ex_no;
    break;
    + case AC_VECTOR:
    + /*
    + * Reflect #AC to the guest if it's expecting the #AC, i.e. has
    + * legacy alignment check enabled. Pre-check host split lock
    + * support to avoid the VMREADs needed to check legacy #AC,
    + * i.e. reflect the #AC if the only possible source is legacy
    + * alignment checks.
    + */
    + if (!split_lock_detect_on() ||
    + guest_cpu_alignment_check_enabled(vcpu)) {
    + kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
    + return 1;
    + }
    +
    + /*
    + * Forward the #AC to userspace if kernel policy does not allow
    + * temporarily disabling split lock detection.
    + */
    + if (handle_user_split_lock(kvm_rip_read(vcpu)))
    + return 1;
    + fallthrough;
    default:
    kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
    kvm_run->ex.exception = ex_no;
    --
    2.20.1
    \
     
     \ /
      Last update: 2020-03-15 06:23    [W:4.038 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site