From patchwork Tue Jul 25 10:40:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wanpeng Li X-Patchwork-Id: 9861727 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 281F0601A1 for ; Tue, 25 Jul 2017 10:41:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 06B2E2861B for ; Tue, 25 Jul 2017 10:41:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EFB0228623; Tue, 25 Jul 2017 10:41:25 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI 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 996902861B for ; Tue, 25 Jul 2017 10:41:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751571AbdGYKlM (ORCPT ); Tue, 25 Jul 2017 06:41:12 -0400 Received: from mail-pf0-f196.google.com ([209.85.192.196]:36789 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750908AbdGYKky (ORCPT ); Tue, 25 Jul 2017 06:40:54 -0400 Received: by mail-pf0-f196.google.com with SMTP id 1so4545910pfi.3; Tue, 25 Jul 2017 03:40:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=i/U1MOueosNPdGWI2Kqvl5tYWfJUfN7tzx9jewclZf0=; b=jpQft1ABYZV7tCVgH7eqQmgI7E1VAfPudsPULQZ/glstWxF7Rwt7paAqvl90kI8dZ9 9TRes0XnR2xk3L49kGGY+2Z155Dz46rAl3Zog1zexbeL/x12tXwVsZi1wlkUfpyNBY+i Lr7LlQwJS3xwd8mBzmbddFfA9a7DetPy1RLGcbU8fFw/hrDY4PfA6NPeUuu3nq1pbcaR +Ov91HjF9EIM5haVr1HUIfNLuaaZ0HI53uE2ouaZss+ZWOBRrn+3xH/2VE/ag+gXQGoH GSt/Bg2DZ1je42WXB8LSCCQnWdwrSdmnIZQ4Rku9k5quKCHwNqsr6oj6t59j/gaBNA2Y UYoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=i/U1MOueosNPdGWI2Kqvl5tYWfJUfN7tzx9jewclZf0=; b=MU8XoIlQTgvta6xcRA3QrVjaSLGjWjm2B3irsUvLVbnA6zIYuH1x9ZjCijw8J3PpdY CwvFvXJuH6IehmgGIsHRiGoN01T0/sY7NlDjdmomCKepOyrqoo6BwpiuFDDOiQ05hfi9 vRU36INz5qed9qpS88CiuSvCc1vAMwJJjjV8r4Lzvdf7ESVvM8Loqu9KtUAeJkZo+7Wk z1TSrcpNG4N1kGIPqhNky7jVdlcxDXF36AZQk2TmU3p/j3nAR5WgKsekRHmZfr9jjuTr qY6hBfQ3oz9B8NeYimKaCRh13TB1M03OiDIx+CiBomhiCOPd/ZOkQKilnuHLVu8vWDaJ e+kg== X-Gm-Message-State: AIVw111bNd1n4lm7gw8daaCmtHxolSIVyM7QU4Dt9tkrpbOz/p5HrdU3 JHWNQs8pO5Wv0H6W X-Received: by 10.99.136.66 with SMTP id l63mr18989473pgd.284.1500979253994; Tue, 25 Jul 2017 03:40:53 -0700 (PDT) Received: from localhost ([203.205.141.123]) by smtp.gmail.com with ESMTPSA id r2sm15528990pgs.85.2017.07.25.03.40.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 25 Jul 2017 03:40:53 -0700 (PDT) From: Wanpeng Li X-Google-Original-From: Wanpeng Li To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Wanpeng Li Subject: [PATCH v2] KVM: nVMX: Fix losing NMI blocking state Date: Tue, 25 Jul 2017 03:40:46 -0700 Message-Id: <1500979246-104432-1-git-send-email-wanpeng.li@hotmail.com> X-Mailer: git-send-email 2.7.4 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 Run kvm-unit-tests/eventinj.flat in L1 w/ ept=0 on both L0 and L1: Before NMI IRET test Sending NMI to self NMI isr running stack 0x461000 Sending nested NMI to self After nested NMI to self Nested NMI isr running rip=40038e After iret After NMI to self FAIL: NMI Reference SDM 31.7.1.2: If the “virtual NMIs” VM-execution control is 1, bit 12 of the VM-exit interruption-information field indicates that the VM exit was due to a fault encountered during an execution of the IRET instruction that removed virtual-NMI blocking. In particular, it provides this indication if the following are both true: - Bit 31 (valid) in the IDT-vectoring information field is 0. - The value of bits 7:0 (vector) of the VM-exit interruption-information field is not 8 (the VM exit is not due to a double-fault exception). If both are true and bit 12 of the VM-exit interruption-information field is 1, there was virtual-NMI blocking before guest software executed the IRET instruction that caused the fault that caused the VM exit. The VMM should set bit 3 (blocking by NMI) in the interruptibility-state field (using VMREAD and VMWRITE) before resuming guest software. Commit 4c4a6f790ee862 (KVM: nVMX: track NMI blocking state separately for each VMCS) tracks NMI blocking state separately for vmcs01 and vmcs02. However it is not enough: - The L2 (kvm-unit-tests/eventinj.flat) generates NMI that will fault on IRET, so the L2 can generate #PF which can be intercepted by L0. - L0 walks L1's guest page table and sees the mapping is invalid, it resumes the L1 guest and injects the #PF into L1. - L1 awares it should set bit 3 (blocking by NMI) in the interruptibility-state field and fix the shadow page table before resuming L2 guest. - L1 executes VMRESUME to resume L2 which generates vmexit and causes L1 exit to L0 - L0 emulates VMRESUME which is called from L1, however, it lost the interruptibility state field which is updated in vmcs12 when prepare vmcs02 - ......... This patch fixes it by updating nmi_known_unmasked when preparing vmcs02 from vmcs12. Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li --- arch/x86/kvm/vmx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 29fd8af..bc999a1 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -10041,6 +10041,8 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, vmcs12->vm_entry_instruction_len); vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, vmcs12->guest_interruptibility_info); + vmx->loaded_vmcs->nmi_known_unmasked = + !(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_NMI); } else { vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); }