Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp631708pxk; Wed, 23 Sep 2020 11:47:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxYLi/x0TqoqngPbGiRf3S+t8+0LzLSWhOCtFidZU7YLJh+Ua886MT7aoygLHguZxiHn03c X-Received: by 2002:a50:d65e:: with SMTP id c30mr740208edj.57.1600886875849; Wed, 23 Sep 2020 11:47:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600886875; cv=none; d=google.com; s=arc-20160816; b=JUm8SEcA9q0rMTB8Y3JCo7CgxYNvmSYuShTQVoyOPLqsoUs9NHQDZDeo6EUd7kmT6T AJzyDZCHa6ejMhYJXvyHSozEUiR0pvJPzNlTkvFWTEcEjLkvj27qTT/WVIOBoADFaorA hwQuOm1AukdU59QMmltrSEwvPgtAk1klw/Ucf9Hhc9Alf2ssxwP+huszcA0DAe6Gotho YnxiUr/oDoqxQ+a/vgYnCFMoTyKfo+9RNo0+aNuHvLDTEQl9En1T96fbX0/Qi5MfZiSJ 4tp4H8mD0bw/FmJ3gqyPAu7T/kZP2ONNK0Ze0e4s1CLLTow75YxiKImW1CuHC+9cqqOW B1lA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:ironport-sdr; bh=n2eG4BDwKZxkzb3cJXzIJ41TFNpGMqghcnfaHALA7Jk=; b=cEvTseCRveHRNa50nG/OojYxDFkFX6ufV+VIIEd4BFwgvhGBDKIOmBHwFramR3UG5q CbdqT50Gmpcz7FIE+96Jhbzew8k0EGvGBP+MyoxKY2iy3k+Q7OsaQ6kgOVmN8ILtM4BQ OXqdHuF9cEehoJJzBSS1u2r8rguC5mMOe1BJqYjZS3h2G+us7ii/xHqz3JaOYWo1nEOO aWXiG//9WYiasWGDPsTWsMlbWCc+oUYI0yApnoboxMC5/VkBM9hm1yisJDIZ8avqAO/M Pb7L0QV7SW6OZKk/v/LWsbUckzHF9gv3f0CRia5/LyPIrUlIAXMtYdwrdLoJ+XxtGj6/ mMZg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ds2si459842ejc.117.2020.09.23.11.47.31; Wed, 23 Sep 2020 11:47:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726998AbgIWSp1 (ORCPT + 99 others); Wed, 23 Sep 2020 14:45:27 -0400 Received: from mga07.intel.com ([134.134.136.100]:14506 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726487AbgIWSoy (ORCPT ); Wed, 23 Sep 2020 14:44:54 -0400 IronPort-SDR: lYVYORvuiGnQpiGL6gJCW2XHjrIHWetwCYE2C9FnSzkKniUtGOUtF0UaFQlug2CS7H5WY6+VEA QoieX+LXRayA== X-IronPort-AV: E=McAfee;i="6000,8403,9753"; a="225124471" X-IronPort-AV: E=Sophos;i="5.77,293,1596524400"; d="scan'208";a="225124471" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Sep 2020 11:44:53 -0700 IronPort-SDR: raRX+UdgFpVe0RwVtA3YHBB4KtQmsIqt3dXRq+oX7WgMMhcnsZK0vmJbUXMCzfcheJY3kDUVsD MjTCj77I07qg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.77,293,1596524400"; d="scan'208";a="347457646" Received: from sjchrist-coffee.jf.intel.com ([10.54.74.160]) by FMSMGA003.fm.intel.com with ESMTP; 23 Sep 2020 11:44:53 -0700 From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Dan Cross , Peter Shier Subject: [PATCH v2 1/7] KVM: nVMX: Reset the segment cache when stuffing guest segs Date: Wed, 23 Sep 2020 11:44:46 -0700 Message-Id: <20200923184452.980-2-sean.j.christopherson@intel.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200923184452.980-1-sean.j.christopherson@intel.com> References: <20200923184452.980-1-sean.j.christopherson@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Explicitly reset the segment cache after stuffing guest segment regs in prepare_vmcs02_rare(). Although the cache is reset when switching to vmcs02, there is nothing that prevents KVM from re-populating the cache prior to writing vmcs02 with vmcs12's values. E.g. if the vCPU is preempted after switching to vmcs02 but before prepare_vmcs02_rare(), kvm_arch_vcpu_put() will dereference GUEST_SS_AR_BYTES via .get_cpl() and cache the stale vmcs02 value. While the current code base only caches stale data in the preemption case, it's theoretically possible future code could read a segment register during the nested flow itself, i.e. this isn't technically illegal behavior in kvm_arch_vcpu_put(), although it did introduce the bug. This manifests as an unexpected nested VM-Enter failure when running with unrestricted guest disabled if the above preemption case coincides with L1 switching L2's CPL, e.g. when switching from a L2 vCPU at CPL3 to to a L2 vCPU at CPL0. stack_segment_valid() will see the new SS_SEL but the old SS_AR_BYTES and incorrectly mark the guest state as invalid due to SS.dpl != SS.rpl. Don't bother updating the cache even though prepare_vmcs02_rare() writes every segment. With unrestricted guest, guest segments are almost never read, let alone L2 guest segments. On the other hand, populating the cache requires a large number of memory writes, i.e. it's unlikely to be a net win. Updating the cache would be a win when unrestricted guest is not supported, as guest_state_valid() will immediately cache all segment registers. But, nested virtualization without unrestricted guest is dirt slow, saving some VMREADs won't change that, and every CPU manufactured in the last decade supports unrestricted guest. In other words, the extra (minor) complexity isn't worth the trouble. Note, kvm_arch_vcpu_put() may see stale data when querying guest CPL depending on when preemption occurs. This is "ok" in that the usage is imperfect by nature, i.e. it's used heuristically to improve performance but doesn't affect functionality. kvm_arch_vcpu_put() could be "fixed" by also disabling preemption while loading segments, but that's pointless and misleading as reading state from kvm_sched_{in,out}() is guaranteed to see stale data in one form or another. E.g. even if all the usage of regs_avail is fixed to call kvm_register_mark_available() after the associated state is set, the individual state might still be stale with respect to the overall vCPU state. I.e. making functional decisions in an asynchronous hook is doomed from the get go. Thankfully KVM doesn't do that. Fixes: de63ad4cf4973 ("KVM: X86: implement the logic for spinlock optimization") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/nested.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index b6ce9ce91029..04441663a631 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2408,6 +2408,8 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base); vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base); vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base); + + vmx->segment_cache.bitmask = 0; } if (!hv_evmcs || !(hv_evmcs->hv_clean_fields & -- 2.28.0