From patchwork Tue Aug 1 21:00:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Matlack X-Patchwork-Id: 9875559 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 3AB1760390 for ; Tue, 1 Aug 2017 21:00:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E33128743 for ; Tue, 1 Aug 2017 21:00:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 22ED028748; Tue, 1 Aug 2017 21:00:56 +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.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham 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 BA77828743 for ; Tue, 1 Aug 2017 21:00:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752220AbdHAVAx (ORCPT ); Tue, 1 Aug 2017 17:00:53 -0400 Received: from mail-pf0-f176.google.com ([209.85.192.176]:36251 "EHLO mail-pf0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751983AbdHAVAr (ORCPT ); Tue, 1 Aug 2017 17:00:47 -0400 Received: by mail-pf0-f176.google.com with SMTP id z129so12416693pfb.3 for ; Tue, 01 Aug 2017 14:00:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Sh6J3+9hzPjFHTh2+1DSWlpmMQyO8puKpQFJOwXpHlM=; b=c5te/cC6rGZoo4Zf9F3F/kjF66LOCs5tgfSeiq8ooD72vx/m2BDLv7KdXHHqh6t40D lsjcNzGSo26rk58j28gLThyUhVsGqoVJ5+26kS+aY674HkBWg2jeHC/b/5bY1p1Od74O cKso5fqMexJn0yGx8pHL2qde19cS8wZbMA/jsX0NOywFk8nITJAYPjHdmI9PLb//ekPb 7O7BAbol2WxgJkWlRXIdIHa+L90VCB6DzrpxTNVbzShmQmg66ZfGmWa+HmpNFvcHsWve ANrHIZYOMTi1aRTKX1Qd65l8tdMSbzwW1BRdfnctGcmWZ7wIPceHSjuSlViZ6aovUp0z c/vw== 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:in-reply-to :references; bh=Sh6J3+9hzPjFHTh2+1DSWlpmMQyO8puKpQFJOwXpHlM=; b=jzppsuLWPRDV1RzCZThgeKb94LosdXB26ZxUMf/lE12Nu/e5HAQeqkJEK8QEILIepT M8n4/ekNB1y+IJfO8aUXemcC73PAwQ7Ip7biH2hRrGV7YoAjK/yGt3rY9QQUkf0a42gf qcm+LII1wMK17r1Jy9PxW0FnHxexXAOndAp3/C148FMZsHKcUuy0zkcHnUzrLtNAMiIZ PL14dOH4yspQHV39BsUrEZMypmyviFR9V/a2C7EandAKRvaVnMJphLNLFl2mV4LGCnMq FeIbPqYKGneFFy8Mb7lj+981m2x7auZNeIzrMfY1HvkdddvU/RFjzzbEg8swArkjr9lt i/ow== X-Gm-Message-State: AIVw112YAe9dbiccckPRlnOeQ4SeawKvdG9x8ngpzd7ZHFxdYkloUbUW FNUfSo4vX3fyBGXS59bxdA== X-Received: by 10.101.86.72 with SMTP id m8mr20149451pgs.94.1501621246490; Tue, 01 Aug 2017 14:00:46 -0700 (PDT) Received: from dmatlack.sea.corp.google.com ([100.100.206.118]) by smtp.gmail.com with ESMTPSA id p126sm50008691pfp.28.2017.08.01.14.00.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 01 Aug 2017 14:00:45 -0700 (PDT) From: David Matlack To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, David Matlack Subject: [PATCH 2/2] KVM: nVMX: mark vmcs12 pages dirty on L2 exit Date: Tue, 1 Aug 2017 14:00:40 -0700 Message-Id: <20170801210040.10295-2-dmatlack@google.com> X-Mailer: git-send-email 2.14.0.rc1.383.gd1ce394fe2-goog In-Reply-To: <20170801210040.10295-1-dmatlack@google.com> References: <20170801210040.10295-1-dmatlack@google.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The host physical addresses of L1's Virtual APIC Page and Posted Interrupt descriptor are loaded into the VMCS02. The CPU may write to these pages via their host physical address while L2 is running, bypassing address-translation-based dirty tracking (e.g. EPT write protection). Mark them dirty on every exit from L2 to prevent them from getting out of sync with dirty tracking. Also mark the virtual APIC page and the posted interrupt descriptor dirty when KVM is virtualizing posted interrupt processing. Signed-off-by: David Matlack Reviewed-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 07d2198db225..b277a0409563 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4952,6 +4952,28 @@ static bool vmx_get_enable_apicv(void) return enable_apicv; } +static void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu) +{ + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + gfn_t gfn; + + /* + * Don't need to mark the APIC access page dirty; it is never + * written to by the CPU during APIC virtualization. + */ + + if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) { + gfn = vmcs12->virtual_apic_page_addr >> PAGE_SHIFT; + kvm_vcpu_mark_page_dirty(vcpu, gfn); + } + + if (nested_cpu_has_posted_intr(vmcs12)) { + gfn = vmcs12->posted_intr_desc_addr >> PAGE_SHIFT; + kvm_vcpu_mark_page_dirty(vcpu, gfn); + } +} + + static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -4959,18 +4981,15 @@ static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu) void *vapic_page; u16 status; - if (vmx->nested.pi_desc && - vmx->nested.pi_pending) { - vmx->nested.pi_pending = false; - if (!pi_test_and_clear_on(vmx->nested.pi_desc)) - return; - - max_irr = find_last_bit( - (unsigned long *)vmx->nested.pi_desc->pir, 256); + if (!vmx->nested.pi_desc || !vmx->nested.pi_pending) + return; - if (max_irr == 256) - return; + vmx->nested.pi_pending = false; + if (!pi_test_and_clear_on(vmx->nested.pi_desc)) + return; + max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256); + if (max_irr != 256) { vapic_page = kmap(vmx->nested.virtual_apic_page); __kvm_apic_update_irr(vmx->nested.pi_desc->pir, vapic_page); kunmap(vmx->nested.virtual_apic_page); @@ -4982,6 +5001,8 @@ static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu) vmcs_write16(GUEST_INTR_STATUS, status); } } + + nested_mark_vmcs12_pages_dirty(vcpu); } static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu, @@ -8029,6 +8050,18 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) vmcs_read32(VM_EXIT_INTR_ERROR_CODE), KVM_ISA_VMX); + /* + * The host physical addresses of some pages of guest memory + * are loaded into VMCS02 (e.g. L1's Virtual APIC Page). The CPU + * may write to these pages via their host physical address while + * L2 is running, bypassing any address-translation-based dirty + * tracking (e.g. EPT write protection). + * + * Mark them dirty on every exit from L2 to prevent them from + * getting out of sync with dirty tracking. + */ + nested_mark_vmcs12_pages_dirty(vcpu); + if (vmx->nested.nested_run_pending) return false;