lkml.org 
[lkml]   [2020]   [Nov]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 45/67] KVM: VMX: Move NMI/exception handler to common helper
    Date
    From: Sean Christopherson <sean.j.christopherson@intel.com>

    Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
    ---
    arch/x86/kvm/vmx/common.h | 54 +++++++++++++++++++++++++++++++++++++++
    arch/x86/kvm/vmx/vmx.c | 42 +++++-------------------------
    2 files changed, 60 insertions(+), 36 deletions(-)
    create mode 100644 arch/x86/kvm/vmx/common.h

    diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h
    new file mode 100644
    index 000000000000..146f1da9c88d
    --- /dev/null
    +++ b/arch/x86/kvm/vmx/common.h
    @@ -0,0 +1,54 @@
    +// SPDX-License-Identifier: GPL-2.0-only
    +#ifndef __KVM_X86_VMX_COMMON_H
    +#define __KVM_X86_VMX_COMMON_H
    +
    +#include <linux/kvm_host.h>
    +
    +#include <asm/traps.h>
    +
    +#include "vmcs.h"
    +#include "x86.h"
    +
    +void vmx_handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu, u32 intr_info);
    +
    +/*
    + * Trigger machine check on the host. We assume all the MSRs are already set up
    + * by the CPU and that we still run on the same CPU as the MCE occurred on.
    + * We pass a fake environment to the machine check handler because we want
    + * the guest to be always treated like user space, no matter what context
    + * it used internally.
    + */
    +static inline void kvm_machine_check(void)
    +{
    +#if defined(CONFIG_X86_MCE)
    + struct pt_regs regs = {
    + .cs = 3, /* Fake ring 3 no matter what the guest ran on */
    + .flags = X86_EFLAGS_IF,
    + };
    +
    + do_machine_check(&regs);
    +#endif
    +}
    +
    +static inline void vmx_handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
    + u32 intr_info)
    +{
    + if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
    + "KVM: unexpected VM-Exit interrupt info: 0x%x", intr_info))
    + return;
    +
    + vmx_handle_interrupt_nmi_irqoff(vcpu, intr_info);
    +}
    +
    +static inline void vmx_handle_exception_nmi_irqoff(struct kvm_vcpu *vcpu,
    + u32 intr_info)
    +{
    + /* Handle machine checks before interrupts are enabled */
    + if (is_machine_check(intr_info))
    + kvm_machine_check();
    + /* We need to handle NMIs before interrupts are enabled */
    + else if (is_nmi(intr_info))
    + vmx_handle_interrupt_nmi_irqoff(vcpu, intr_info);
    +}
    +
    +#endif /* __KVM_X86_VMX_COMMON_H */
    diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
    index 5d6c3a50230d..e8b60d447e27 100644
    --- a/arch/x86/kvm/vmx/vmx.c
    +++ b/arch/x86/kvm/vmx/vmx.c
    @@ -49,6 +49,7 @@
    #include <asm/vmx.h>

    #include "capabilities.h"
    +#include "common.h"
    #include "cpuid.h"
    #include "evmcs.h"
    #include "irq.h"
    @@ -4708,25 +4709,6 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
    return 1;
    }

    -/*
    - * Trigger machine check on the host. We assume all the MSRs are already set up
    - * by the CPU and that we still run on the same CPU as the MCE occurred on.
    - * We pass a fake environment to the machine check handler because we want
    - * the guest to be always treated like user space, no matter what context
    - * it used internally.
    - */
    -static void kvm_machine_check(void)
    -{
    -#if defined(CONFIG_X86_MCE)
    - struct pt_regs regs = {
    - .cs = 3, /* Fake ring 3 no matter what the guest ran on */
    - .flags = X86_EFLAGS_IF,
    - };
    -
    - do_machine_check(&regs);
    -#endif
    -}
    -
    static int handle_machine_check(struct kvm_vcpu *vcpu)
    {
    /* handled by vmx_vcpu_run() */
    @@ -6348,7 +6330,7 @@ static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)

    void vmx_do_interrupt_nmi_irqoff(unsigned long entry);

    -static void handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
    +void vmx_handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
    {
    unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
    gate_desc *desc = (gate_desc *)host_idt_base + vector;
    @@ -6363,21 +6345,8 @@ static void handle_exception_nmi_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
    /* if exit due to PF check for async PF */
    if (is_page_fault(intr_info))
    vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
    - /* Handle machine checks before interrupts are enabled */
    - else if (is_machine_check(intr_info))
    - kvm_machine_check();
    - /* We need to handle NMIs before interrupts are enabled */
    - else if (is_nmi(intr_info))
    - handle_interrupt_nmi_irqoff(vcpu, intr_info);
    -}
    -
    -static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
    -{
    - if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
    - "KVM: unexpected VM-Exit interrupt info: 0x%x", intr_info))
    - return;
    -
    - handle_interrupt_nmi_irqoff(vcpu, intr_info);
    + else
    + vmx_handle_exception_nmi_irqoff(vcpu, intr_info);
    }

    static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
    @@ -6385,7 +6354,8 @@ static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
    struct vcpu_vmx *vmx = to_vmx(vcpu);

    if (vmx->exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT)
    - handle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));
    + vmx_handle_external_interrupt_irqoff(vcpu,
    + vmx_get_intr_info(vcpu));
    else if (vmx->exit_reason == EXIT_REASON_EXCEPTION_NMI)
    handle_exception_nmi_irqoff(vcpu, vmx_get_intr_info(vcpu));
    }
    --
    2.17.1
    \
     
     \ /
      Last update: 2020-11-16 19:39    [W:4.200 / U:1.528 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site