From patchwork Thu Sep 22 03:34:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wanpeng Li X-Patchwork-Id: 9344443 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1E05860B16 for ; Thu, 22 Sep 2016 03:34:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C8DA2A34F for ; Thu, 22 Sep 2016 03:34:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 013F32A31B; Thu, 22 Sep 2016 03:34:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 316BA2A31B for ; Thu, 22 Sep 2016 03:34:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934208AbcIVDee (ORCPT ); Wed, 21 Sep 2016 23:34:34 -0400 Received: from mail-pf0-f174.google.com ([209.85.192.174]:35414 "EHLO mail-pf0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933973AbcIVDec (ORCPT ); Wed, 21 Sep 2016 23:34:32 -0400 Received: by mail-pf0-f174.google.com with SMTP id z123so25770534pfz.2; Wed, 21 Sep 2016 20:34:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=2UlbpUrUeFQGE1sMJqQS3LQjLT+gqLgPS1tQpI/1wbw=; b=vdYU3gV1iQDnHaEupHfk1A/LX52OU5q2meDj2q1eB5DJ+zr1GQweDAnwfucejcw0bv 6rJOLlyX+6jBYK0nh6SEzqxEpVFF/N50o0c+BHlpT/KeFwk5/viaSIpYKtA9+Z5FdHNf fD07g5q/AJJV9jefugeWt7DXaKZYbvAfnm8MwzKVt0ydpxWoeutp1D+/dif4pRrPmuaL 1j3Ao9iF5/Bs0Lfu8HKRP3+v8F/3kEB1kRUR5b0NX/3XONxMvlA0toyUD2BHYPmL4p/Z WSIgKCwVoDTqDKfSoqpvpaGgInfry5cSjkYiS4gmLNio0Ybubn52/cOdKK2P4QPGg2Rh aLcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=2UlbpUrUeFQGE1sMJqQS3LQjLT+gqLgPS1tQpI/1wbw=; b=E9ZCyeeihYALPzjyFyYB+gNFMX7WZqysoaiX14dVVlnQdEQCLpf/uUmYe3K2yitA7n AI8NLDdzpVT4RW/J3VHHUy0ORIQqTNwWqueFuQC9P79OyZ5n4AfLrF5Q3ba/zAcGM12G gDTs5NjUjKf6YldCR09656d0Haa1DW3C1+e0m3/5JBRYibV74ZtdUJAwn3GRzyAwifyb 4Ix9BRtzB3u6YLV+QmYE7v5nHrtB7xYEOq3V4Uf0HEu6QmeUz5F7Ki9YnsY1Orp2Awxq 6RfGR18f1yJ0A7HHqOCbVkSSf/vR0Luff6weXGv1f5WX4W7P2yLl/z5zxkMnuhqE32ow xlRg== X-Gm-Message-State: AE9vXwPQ27HwRGRvi7dLL78ym56H/cJRk6rqqOzXObgG36lq0UWUGQr0irK6Bkob7laJKA== X-Received: by 10.98.159.194 with SMTP id v63mr70529182pfk.91.1474515271167; Wed, 21 Sep 2016 20:34:31 -0700 (PDT) Received: from kernel.kingsoft.cn ([114.255.44.132]) by smtp.gmail.com with ESMTPSA id h123sm948428pfe.87.2016.09.21.20.34.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 21 Sep 2016 20:34:30 -0700 (PDT) From: Wanpeng Li X-Google-Original-From: Wanpeng Li To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Wanpeng Li , Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Jan Kiszka , Bandan Das Subject: [PATCH] KVM: nVMX: Fix the NMI IDT-vectoring info handling Date: Thu, 22 Sep 2016 11:34:19 +0800 Message-Id: <1474515259-3197-1-git-send-email-wanpeng.li@hotmail.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Wanpeng Li Run kvm-unit-tests/eventinj.flat in L1: Sending NMI to self After NMI to self FAIL: NMI This test scenario is to test whether VMM can handle NMI IDT-vectoring info correctly. At the beginning, L2 writes LAPIC to send a self NMI, the EPT page tables on both L1 and L0 are empty so: - The L2 accesses memory can generate EPT violation which can be intercepted by L0. The EPT violation vmexit occurred during delivery of this NMI, and the NMI info is recorded in vmcs02's IDT-vectoring info. - L0 walks L1's EPT12 and L0 sees the mapping is invalid, it injects the EPT violation into L1. The vmcs02's IDT-vectoring info is reflected to vmcs12's IDT-vectoring info since it is a nested vmexit. - L1 receives the EPT violation, then fixes its EPT12. - L1 executes VMRESUME to resume L2 which generates vmexit and causes L1 exits to L0. - L0 emulates VMRESUME which is called from L1, then return to L2. L0 merges the requirement of vmcs12's IDT-vectoring info and injects it to L2 through vmcs02. - The L2 re-executes the fault instruction and cause EPT violation again. - Since the L1's EPT12 is valid, L0 can fix its EPT02 - L0 resume L2 The EPT violation vmexit occurred during delivery of this NMI again, and the NMI info is recorded in vmcs02's IDT-vectoring info. L0 should inject the NMI through vmentry event injection since it is caused by EPT02's EPT violation. However, vmx_inject_nmi() refuses to inject NMI from IDT-vectoring info if vCPU is in guest mode, this patch fix it by permitting to inject NMI from IDT-vectoring if it is the L0's responsibility to inject NMI from IDT-vectoring info to L2. Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Jan Kiszka Cc: Bandan Das Signed-off-by: Wanpeng Li --- arch/x86/kvm/vmx.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 813658d..c883d73 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5309,28 +5309,27 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); - if (is_guest_mode(vcpu)) - return; - - if (!cpu_has_virtual_nmis()) { - /* - * Tracking the NMI-blocked state in software is built upon - * finding the next open IRQ window. This, in turn, depends on - * well-behaving guests: They have to keep IRQs disabled at - * least as long as the NMI handler runs. Otherwise we may - * cause NMI nesting, maybe breaking the guest. But as this is - * highly unlikely, we can live with the residual risk. - */ - vmx->soft_vnmi_blocked = 1; - vmx->vnmi_blocked_time = 0; - } + if (!is_guest_mode(vcpu)) { + if (!cpu_has_virtual_nmis()) { + /* + * Tracking the NMI-blocked state in software is built upon + * finding the next open IRQ window. This, in turn, depends on + * well-behaving guests: They have to keep IRQs disabled at + * least as long as the NMI handler runs. Otherwise we may + * cause NMI nesting, maybe breaking the guest. But as this is + * highly unlikely, we can live with the residual risk. + */ + vmx->soft_vnmi_blocked = 1; + vmx->vnmi_blocked_time = 0; + } - ++vcpu->stat.nmi_injections; - vmx->nmi_known_unmasked = false; - if (vmx->rmode.vm86_active) { - if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != EMULATE_DONE) - kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); - return; + ++vcpu->stat.nmi_injections; + vmx->nmi_known_unmasked = false; + if (vmx->rmode.vm86_active) { + if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != EMULATE_DONE) + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + return; + } } vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);