From patchwork Thu Sep 22 09:55:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wanpeng Li X-Patchwork-Id: 9344919 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 C5CF16077A for ; Thu, 22 Sep 2016 09:56:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B65052A933 for ; Thu, 22 Sep 2016 09:56:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AAABA2A94B; Thu, 22 Sep 2016 09:56:07 +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 E0ED22A93B for ; Thu, 22 Sep 2016 09:56:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757013AbcIVJ4D (ORCPT ); Thu, 22 Sep 2016 05:56:03 -0400 Received: from mail-pf0-f177.google.com ([209.85.192.177]:33070 "EHLO mail-pf0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753840AbcIVJ4B (ORCPT ); Thu, 22 Sep 2016 05:56:01 -0400 Received: by mail-pf0-f177.google.com with SMTP id 21so29155769pfy.0; Thu, 22 Sep 2016 02:56:00 -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=9pjVIktFWuRoqVaNDCug9rZHUvtzHl4uX8/JkaTGYeQ=; b=uzGMoJrMIv4Y9B0GVGL0N9P/jVjdNe1Z5MPB7YUeFkWoNBnSKfMITcIKf3mkDV8L3h pdTcPc/QsP2lz4UT/DmP5aMCQ3y9x2WqE2cRoCycJjDI/MXCSOKE53QczZK3Vf3gB1tM K9zOP4CZcxxg215BGs5I+ABLvMVUTUUYT2ODk2DZHVz1UFsaGFCHXyYuOilJJMiQ/Hy5 9GIOfYEcq9sADO1x8a7V9aGgxF8oZwyjyspqykqhzGRxNd0zCZ8ufwVHXnyVpnKsCPGF qRM+15cBOYJL5ktfviutMvh0BxsH1CQX/dlGhSw1fguDQI81Uf7GoSAB0M8eV/lehbaI J38w== 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=9pjVIktFWuRoqVaNDCug9rZHUvtzHl4uX8/JkaTGYeQ=; b=dDfSlZo8BY9SBchZWe64PfXZs7HJs5GBazjiMX7Nx+9/A+j2/Ep9+l1hmFOXzQiZMm Aey5R58wprF2VN1bFUbmLyXqtT+SoQ/sc5zBFFpJVDkWieEstipGNqDpC80bLh2h3hYC zQY/s7JWEYKM8x8SDfVATr3bFnBlrWyWMS6a7sXIIjJRQUBp7XTR+rQLn64mOG6hRAUB ahsl0xQjutIRr3Kuhb38tMGHKI90PkjevzclLqFPxJRBDNYUmbLS8Z5wTw2P9qho/vS2 RfeDc+h718uBp/9K2HaJsw7z4YlaKNnarCpB6JvCIr4oaKw+OsOCSPQiKt7WWKy+6UWQ cb+w== X-Gm-Message-State: AE9vXwOdOwrTlZnD/itbrFnNxgiKt5KYgTGdGmPGea450XkoQyV0a1V7MmnXtUb7HSfBfg== X-Received: by 10.98.149.82 with SMTP id p79mr1810244pfd.150.1474538160303; Thu, 22 Sep 2016 02:56:00 -0700 (PDT) Received: from kernel.kingsoft.cn ([114.255.44.132]) by smtp.gmail.com with ESMTPSA id 19sm2671188pfk.58.2016.09.22.02.55.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 22 Sep 2016 02:55:59 -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 v2] KVM: nVMX: Fix the NMI IDT-vectoring handling Date: Thu, 22 Sep 2016 17:55:54 +0800 Message-Id: <1474538154-14119-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 Reviewed-by: Paolo Bonzini --- v1 -> v2: * move the if (vmx->rmode.vm86_active) part out if (!is_guest_mode()) arch/x86/kvm/vmx.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 813658d..5429a43 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5309,29 +5309,30 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); - if (is_guest_mode(vcpu)) - return; + 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; + } - 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; } - ++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); }