| From ef85b67385436ddc1998f45f1d6a210f935b3388 Mon Sep 17 00:00:00 2001 |
| From: Jim Mattson <jmattson@google.com> |
| Date: Mon, 12 Dec 2016 11:01:37 -0800 |
| Subject: kvm: nVMX: Allow L1 to intercept software exceptions (#BP and #OF) |
| |
| From: Jim Mattson <jmattson@google.com> |
| |
| commit ef85b67385436ddc1998f45f1d6a210f935b3388 upstream. |
| |
| When L2 exits to L0 due to "exception or NMI", software exceptions |
| (#BP and #OF) for which L1 has requested an intercept should be |
| handled by L1 rather than L0. Previously, only hardware exceptions |
| were forwarded to L1. |
| |
| Signed-off-by: Jim Mattson <jmattson@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kvm/vmx.c | 11 +++++------ |
| 1 file changed, 5 insertions(+), 6 deletions(-) |
| |
| --- a/arch/x86/kvm/vmx.c |
| +++ b/arch/x86/kvm/vmx.c |
| @@ -1336,10 +1336,10 @@ static inline bool nested_cpu_has_posted |
| return vmcs12->pin_based_vm_exec_control & PIN_BASED_POSTED_INTR; |
| } |
| |
| -static inline bool is_exception(u32 intr_info) |
| +static inline bool is_nmi(u32 intr_info) |
| { |
| return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) |
| - == (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK); |
| + == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK); |
| } |
| |
| static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, |
| @@ -5467,7 +5467,7 @@ static int handle_exception(struct kvm_v |
| if (is_machine_check(intr_info)) |
| return handle_machine_check(vcpu); |
| |
| - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR) |
| + if (is_nmi(intr_info)) |
| return 1; /* already handled by vmx_vcpu_run() */ |
| |
| if (is_no_device(intr_info)) { |
| @@ -7974,7 +7974,7 @@ static bool nested_vmx_exit_handled(stru |
| |
| switch (exit_reason) { |
| case EXIT_REASON_EXCEPTION_NMI: |
| - if (!is_exception(intr_info)) |
| + if (is_nmi(intr_info)) |
| return false; |
| else if (is_page_fault(intr_info)) |
| return enable_ept; |
| @@ -8572,8 +8572,7 @@ static void vmx_complete_atomic_exit(str |
| kvm_machine_check(); |
| |
| /* We need to handle NMIs before interrupts are enabled */ |
| - if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR && |
| - (exit_intr_info & INTR_INFO_VALID_MASK)) { |
| + if (is_nmi(exit_intr_info)) { |
| kvm_before_handle_nmi(&vmx->vcpu); |
| asm("int $2"); |
| kvm_after_handle_nmi(&vmx->vcpu); |