From patchwork Fri Oct 28 15:29:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Mattson X-Patchwork-Id: 9402129 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 A959660588 for ; Fri, 28 Oct 2016 15:30:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B33A2A84A for ; Fri, 28 Oct 2016 15:30:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8FFFD2A84C; Fri, 28 Oct 2016 15:30:32 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID 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 1D6C02A84A for ; Fri, 28 Oct 2016 15:30:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933956AbcJ1PaZ (ORCPT ); Fri, 28 Oct 2016 11:30:25 -0400 Received: from mail-pf0-f175.google.com ([209.85.192.175]:33530 "EHLO mail-pf0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759993AbcJ1PaY (ORCPT ); Fri, 28 Oct 2016 11:30:24 -0400 Received: by mail-pf0-f175.google.com with SMTP id 197so39333212pfu.0 for ; Fri, 28 Oct 2016 08:30:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZWV1AGOohzzli52GVRi8ZCrF9M0NZwlKvcLk1LeshVk=; b=U9DTpdYRZuaU2GCNdlAyFckbgZfr8nc6XvjcoQe7UdAn5pYHtimh1MyhFf1H8+428H phTAA9yPaDxHt9vBQ/dDdytJVtIuSa0cTgYWz35N/fc31yUTfjzonPd8fLipRhgSa0ET kBiV3vbrdFi0KX9/QknrK645YjKvyb737XG+/0DJbT5wJc9jFqy+Ufj1oVq+iFSkfiVG su6QWI3tm32zRGwA97onKMsVHSF+/LljBaYqAu3yLvJF0XeSiNWqss2e40EndVH3qe/2 5j/OVTCUJEbxS8sdWiXN0ueFR3dy85nMQKzcfWOMZEIEbCMGKtQagm11k8Vt/Nx0tmlN t21Q== 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:in-reply-to :references; bh=ZWV1AGOohzzli52GVRi8ZCrF9M0NZwlKvcLk1LeshVk=; b=DsMZRmJYcydX5aCyHpmVR+BZFVHD4V8SwKXvwWmhl7rC72H57G7Kd6yuArfvBZS1wO Xh3jlFba4/Bsnt00pbOS05aZL4UdPrHJrAix/h0lQVhpLQxjvGtjLnsQsM+Q9pG5Udh4 iY4NkqRV2jXF7Sq4aKJv9kchuR6lU02sez+FuUJ3v4hKFgr9UgeeIOlA/kU+7BdBNrUp FFmHB/CoMdc6bOJIV0dDFXG4o106hRFKRbFbbxXe6Lg59V+c0qmCzdxoxeMC1Hz10Ucu M2lhyTcVQkzfU2t0Z0vJaqY9/azuwVT/bfa5QCBuFG0cHsN3tfyksg7+e3Z/9c5/0VIa PsfQ== X-Gm-Message-State: ABUngves2YvjAkWwJTpwoppP6OLDaBeH5mDhEF7w3tR5WFUcUS6AEk8v9YY4VefXb71R71le X-Received: by 10.99.2.214 with SMTP id 205mr21632584pgc.1.1477668623276; Fri, 28 Oct 2016 08:30:23 -0700 (PDT) Received: from jmattson.sea.corp.google.com ([100.100.206.154]) by smtp.gmail.com with ESMTPSA id dh9sm19839785pac.14.2016.10.28.08.30.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 28 Oct 2016 08:30:22 -0700 (PDT) From: Jim Mattson To: kvm@vger.kernel.org, Bandan Das , Paolo Bonzini , David Matlack , Peter Feiner Cc: Jim Mattson Subject: [PATCH v2] kvm: nVMX: VMCLEAR an active shadow VMCS after last use Date: Fri, 28 Oct 2016 08:29:39 -0700 Message-Id: <1477668579-22555-1-git-send-email-jmattson@google.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 In-Reply-To: References: Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP After a successful VM-entry with the "VMCS shadowing" VM-execution control set, the shadow VMCS referenced by the VMCS link pointer field in the current VMCS becomes active on the logical processor. A VMCS that is made active on more than one logical processor may become corrupted. Therefore, before an active VMCS can be migrated to another logical processor, the first logical processor must execute a VMCLEAR for the active VMCS. VMCLEAR both ensures that all VMCS data are written to memory and makes the VMCS inactive. Signed-off-by: Jim Mattson Reviewed-By: David Matlack --- arch/x86/kvm/vmx.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index cf0b7be..046b03f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -187,6 +187,7 @@ struct vmcs { */ struct loaded_vmcs { struct vmcs *vmcs; + struct vmcs *shadow_vmcs; int cpu; int launched; struct list_head loaded_vmcss_on_cpu_link; @@ -411,7 +412,6 @@ struct nested_vmx { * memory during VMXOFF, VMCLEAR, VMPTRLD. */ struct vmcs12 *cached_vmcs12; - struct vmcs *current_shadow_vmcs; /* * Indicates if the shadow vmcs must be updated with the * data hold by vmcs12 @@ -1419,6 +1419,8 @@ static void vmcs_clear(struct vmcs *vmcs) static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs) { vmcs_clear(loaded_vmcs->vmcs); + if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched) + vmcs_clear(loaded_vmcs->shadow_vmcs); loaded_vmcs->cpu = -1; loaded_vmcs->launched = 0; } @@ -3562,6 +3564,7 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) loaded_vmcs_clear(loaded_vmcs); free_vmcs(loaded_vmcs->vmcs); loaded_vmcs->vmcs = NULL; + WARN_ON(loaded_vmcs->shadow_vmcs != NULL); } static void free_kvm_area(void) @@ -6696,6 +6699,7 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx) if (!item) return NULL; item->vmcs02.vmcs = alloc_vmcs(); + item->vmcs02.shadow_vmcs = NULL; if (!item->vmcs02.vmcs) { kfree(item); return NULL; @@ -7072,7 +7076,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu) shadow_vmcs->revision_id |= (1u << 31); /* init shadow vmcs */ vmcs_clear(shadow_vmcs); - vmx->nested.current_shadow_vmcs = shadow_vmcs; + vmx->vmcs01.shadow_vmcs = shadow_vmcs; } INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool)); @@ -7174,8 +7178,11 @@ static void free_nested(struct vcpu_vmx *vmx) free_page((unsigned long)vmx->nested.msr_bitmap); vmx->nested.msr_bitmap = NULL; } - if (enable_shadow_vmcs) - free_vmcs(vmx->nested.current_shadow_vmcs); + if (enable_shadow_vmcs) { + vmcs_clear(vmx->vmcs01.shadow_vmcs); + free_vmcs(vmx->vmcs01.shadow_vmcs); + vmx->vmcs01.shadow_vmcs = NULL; + } kfree(vmx->nested.cached_vmcs12); /* Unpin physical memory we referred to in current vmcs02 */ if (vmx->nested.apic_access_page) { @@ -7352,7 +7359,7 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx) int i; unsigned long field; u64 field_value; - struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; + struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs; const unsigned long *fields = shadow_read_write_fields; const int num_fields = max_shadow_read_write_fields; @@ -7401,7 +7408,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx) int i, q; unsigned long field; u64 field_value = 0; - struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; + struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs; vmcs_load(shadow_vmcs); @@ -7591,7 +7598,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_SHADOW_VMCS); vmcs_write64(VMCS_LINK_POINTER, - __pa(vmx->nested.current_shadow_vmcs)); + __pa(vmx->vmcs01.shadow_vmcs)); vmx->nested.sync_shadow_vmcs = true; } } @@ -9156,6 +9163,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) vmx->loaded_vmcs = &vmx->vmcs01; vmx->loaded_vmcs->vmcs = alloc_vmcs(); + vmx->loaded_vmcs->shadow_vmcs = NULL; if (!vmx->loaded_vmcs->vmcs) goto free_msrs; if (!vmm_exclusive)