From patchwork Sun Mar 24 18:44:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 2327081 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 30E4D3FC54 for ; Sun, 24 Mar 2013 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754502Ab3CXSpN (ORCPT ); Sun, 24 Mar 2013 14:45:13 -0400 Received: from mout.web.de ([212.227.17.11]:50463 "EHLO mout.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753976Ab3CXSo7 (ORCPT ); Sun, 24 Mar 2013 14:44:59 -0400 Received: from localhost.localdomain ([95.157.56.37]) by smtp.web.de (mrweb002) with ESMTPSA (Nemesis) id 0MRl2f-1U8WBN0RSr-00SbHp; Sun, 24 Mar 2013 19:44:56 +0100 From: Jan Kiszka To: Gleb Natapov , Marcelo Tosatti Cc: kvm , Paolo Bonzini , Nadav Har'El Subject: [PATCH v3 4/5] KVM: nVMX: Fix conditions for interrupt injection Date: Sun, 24 Mar 2013 19:44:47 +0100 Message-Id: <8d319389dd68794c629b10ce3a071f16119d248b.1364150685.git.jan.kiszka@web.de> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: References: In-Reply-To: References: X-Provags-ID: V02:K0:ze1kj1gzpf8mpP/03QGsGDfJ/aUDyQqbiDYrOmUoggt hxFKQfKPDsxEEYJVSD0DtT7eLMp8WEji4MIY02gM5HvKgrWfv2 KMoN9lPUvmRQjWXH9ZwRngvEfstd9/CujHjTdB3tAmenNpg0dq hkoy65gGB/I6ksNxvpu6H7RQIM7trZ1Y8xBZ7al+h/RG9l9MF8 uPuxSDrYdIyNcv+vztIgw== Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Jan Kiszka If we are in guest mode, L0 can only inject events into L2 if L1 has nothing pending. Otherwise, L0 would overwrite L1's events and they would get lost. But even if no injection of L1 is pending, we do not want L0 to interrupt unnecessarily an on going vmentry with all its side effects on the vmcs. Therefore, injection shall be disallowed during L1->L2 transitions. This check is conceptually independent of nested_exit_on_intr. If L1 traps external interrupts, then we also need to look at L1's idt_vectoring_info_field. If it is empty, we can kick the guest from L2 to L1, just like the previous code worked. Signed-off-by: Jan Kiszka --- arch/x86/kvm/vmx.c | 28 ++++++++++++++++++++-------- 1 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d1bc834..30aa198 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4325,16 +4325,28 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) { - if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) { + if (is_guest_mode(vcpu)) { struct vmcs12 *vmcs12 = get_vmcs12(vcpu); - if (to_vmx(vcpu)->nested.nested_run_pending || - (vmcs12->idt_vectoring_info_field & - VECTORING_INFO_VALID_MASK)) + + if (to_vmx(vcpu)->nested.nested_run_pending) return 0; - nested_vmx_vmexit(vcpu); - vmcs12->vm_exit_reason = EXIT_REASON_EXTERNAL_INTERRUPT; - vmcs12->vm_exit_intr_info = 0; - /* fall through to normal code, but now in L1, not L2 */ + if (nested_exit_on_intr(vcpu)) { + /* + * Check if the idt_vectoring_info_field is free. We + * cannot raise EXIT_REASON_EXTERNAL_INTERRUPT if it + * isn't. + */ + if (vmcs12->idt_vectoring_info_field & + VECTORING_INFO_VALID_MASK) + return 0; + nested_vmx_vmexit(vcpu); + vmcs12->vm_exit_reason = + EXIT_REASON_EXTERNAL_INTERRUPT; + vmcs12->vm_exit_intr_info = 0; + /* + * fall through to normal code, but now in L1, not L2 + */ + } } return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&