From nobody Tue Dec 2 01:51:35 2025 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91E43333439 for ; Fri, 21 Nov 2025 11:11:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763723487; cv=none; b=WG0gnEAKAe/yhRJv8LNmna3wmwskRUBODNzmicbwe5n2/pe93DvWTsSpq5hdctUEkgMdYX4zeeg1TdIgPejRMT0ETlCSWQhLW06HnR2Txs6G57l/x/kxW7a295UcMkgVNsNmRfZIyoOtJH5ukBTEnaUf9u/XK1zU0OQjcHhN60M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763723487; c=relaxed/simple; bh=GTh03DnovL1IfXrIJWOOWsXVB4KulpyzdpPOxbFjAXc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MJJOWYMRH7GBzDWhcSUzu0o1BfFkf3AwHKObZgzcFaWz/+bDWgArM9VxHNUUtAHD+gQpI0Ad5/FHXJ1YiwabGRh6Ykyq2v6CXzi0et79BdJHMNpxGEv/4DFAbk/C4YapVaRAff+QJb84RFtQD1wumJ4fPqHwb7WxnXj2C2WcREU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NRQ0dWgl; arc=none smtp.client-ip=209.85.221.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NRQ0dWgl" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-42b566859ecso1718081f8f.2 for ; Fri, 21 Nov 2025 03:11:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763723484; x=1764328284; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2msaF/pghuykVBiKeYLpA2uXeztIpV3HBLG8Kfba9b0=; b=NRQ0dWglCzb6OKJfkoLo+VryyIaJKNwPiLDqsNKZ3Lxsu3fnHYc/hqSU+aH5pZrsD0 YEXVg8dC4RHNcNc+KHz/EOeRIAdFfIhYvcrw1nTw3JIE8KRxMn+kmfLPiyddBLSK9Orh UzV74q7zMcu542GGnCWSlfV3FxJnBZClVtu6PMyoZ96GhzqZ2bVQ/jmImXcZK6y1uve4 i/b7ySFkC1wKd4LHHaZE/9l+K2GGNj+JJhFU/oLuBv5sQJE+Mfvb6XvscchFyU3kM8AI r1a/yWUzzfxUfk20/QX31Cjc2jtnkvdD8jsS2PnVP+U/skPSm176r4Fu/N3m829hK5CQ nJeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763723484; x=1764328284; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=2msaF/pghuykVBiKeYLpA2uXeztIpV3HBLG8Kfba9b0=; b=CbWw7IJzqEQhkIcRyO9TNEkslHVmmslbPg5apBoZuD9LukDf6eH6qgF6aB+B7j40lJ rHQjEtuvFRsKQq4bh59vc+TEjN/tYrCpvXr82i4YBysbDFnGpTYlqhk4Su4gXrdOfXPA jiMcabVOFA8u9BZMblomdSyhP2ZG3T5XMGkBb1GuDCxhYZ55UXyv3KguixsNjwWr+g11 yQkoeHT8bbZFvcNqLv9+2l5I/NgnteJbZqJGC+H9OAaCb9JhG7NyJiCEIY9hBmh9dlBx nuId0fKgF07i7orxHJLBxXl5XBwjFoq9DnLi6rwJZphnaR2u+No8uaSKdz4NY7kzutP7 jbWA== X-Forwarded-Encrypted: i=1; AJvYcCVjSN6wob/FZdtUNsbNyje7Ke2jrZQfAA4Ohm89Rl6yJ7mpnncl8cGRMgsLUNBbni90C14KaMF/OHif2CQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yw/ol0kCAKP5W4ISUJIX8zyNSlSNyNM7dyGptNzo1QNineLW3+1 Yp+DPgYOrmGwVi1qsmXjdKEU5HJuaPRuL07ga/6n/brUcG4jiAxKB5n6 X-Gm-Gg: ASbGncsvtx5PxMQnRm4jaAn+raBtfCxlkR6GXj1EBiCbca5Inwl13egK3+CYVLnOFTU 7pVehBxc1R65wSpGixducW6hp4DPyqFI4vvZSNB6ZiAagfHOhS5rWbti3gV4Al412FyWjTklRVM ssWFuVAVM4ZzmSEp3IyRUgO0SMKTfGEAvoaqozpYLHfZyteSCJ5KJF2I482m7Ne6HQ3fvk3EGHf eX4+EbzqHdjBXe3Okd9Hy3uIdUo9rF3W2jRXyLSkpu857A9JGzYymJcgUQyFT7qzcVU7vbLMZRN Y4+hZsKW3InNniSzt59zF/zhGPmGOX47yljWrMo1etF74kbWv4JdUAQ5fHSfd01giTkr3kwdzUT Arlj9qNk65AahhGtFrmirUABnG9bUEanDIV52i/anjwv3C0Mrsbyp9k2OFeRvBadRkTU/ScGOIt WZZ91NL+FB0Knu+9PHdN91k6OxlXlM3Cpsh5GPKn42JUs3AAuKGYGwURz86Xm+om6pWmjEdIM4R z2qrtKDwrSpNVGVG+CxbEtTpP1DpHmQ X-Google-Smtp-Source: AGHT+IHo5C0rwkC/ovLdq93KgTIAbuzG1TA3/TDefcWM5XOmUmrdZ1+NEnJ8PSLvBfBcBoCYrETpjg== X-Received: by 2002:a05:6000:40c7:b0:429:9323:2bec with SMTP id ffacd0b85a97d-42cc1d1981dmr2054714f8f.40.1763723483713; Fri, 21 Nov 2025 03:11:23 -0800 (PST) Received: from ip-10-0-150-200.eu-west-1.compute.internal (ec2-52-49-196-232.eu-west-1.compute.amazonaws.com. [52.49.196.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7f363e4sm10484180f8f.12.2025.11.21.03.11.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Nov 2025 03:11:23 -0800 (PST) From: Fred Griffoul To: kvm@vger.kernel.org Cc: seanjc@google.com, pbonzini@redhat.com, vkuznets@redhat.com, shuah@kernel.org, dwmw@amazon.co.uk, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Fred Griffoul Subject: [PATCH v3 01/10] KVM: nVMX: Implement cache for L1 MSR bitmap Date: Fri, 21 Nov 2025 11:11:04 +0000 Message-ID: <20251121111113.456628-2-griffoul@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251121111113.456628-1-griffoul@gmail.com> References: <20251121111113.456628-1-griffoul@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fred Griffoul Introduce a gfn_to_pfn_cache to optimize L1 MSR bitmap access by replacing map/unmap operations. This optimization reduces overhead during L2 VM-entry where nested_vmx_prepare_msr_bitmap() merges L1's MSR intercepts with L0's requirements. Current implementation using kvm_vcpu_map_readonly() and kvm_vcpu_unmap() creates significant performance impact, mostly with unmanaged guest memory. The cache is initialized when entering VMX operation and deactivated when VMX operation ends. Signed-off-by: Fred Griffoul --- arch/x86/kvm/vmx/nested.c | 42 +++++++++++++++++++++++++++++++++++---- arch/x86/kvm/vmx/vmx.h | 2 ++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 8b131780e981..0de84b30c41d 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -315,6 +315,34 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, str= uct loaded_vmcs *vmcs) vcpu->arch.regs_dirty =3D 0; } =20 +/* + * Maps a single guest page starting at @gpa and lock the cache for access. + */ +static int nested_gpc_lock(struct gfn_to_pfn_cache *gpc, gpa_t gpa) +{ + int err; + + if (!PAGE_ALIGNED(gpa)) + return -EINVAL; +retry: + read_lock(&gpc->lock); + if (!kvm_gpc_check(gpc, PAGE_SIZE) || (gpc->gpa !=3D gpa)) { + read_unlock(&gpc->lock); + err =3D kvm_gpc_activate(gpc, gpa, PAGE_SIZE); + if (err) + return err; + + goto retry; + } + + return 0; +} + +static void nested_gpc_unlock(struct gfn_to_pfn_cache *gpc) +{ + read_unlock(&gpc->lock); +} + static void nested_put_vmcs12_pages(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); @@ -344,6 +372,9 @@ static void free_nested(struct kvm_vcpu *vcpu) vmx->nested.vmxon =3D false; vmx->nested.smm.vmxon =3D false; vmx->nested.vmxon_ptr =3D INVALID_GPA; + + kvm_gpc_deactivate(&vmx->nested.msr_bitmap_cache); + free_vpid(vmx->nested.vpid02); vmx->nested.posted_intr_nv =3D -1; vmx->nested.current_vmptr =3D INVALID_GPA; @@ -625,7 +656,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct= kvm_vcpu *vcpu, int msr; unsigned long *msr_bitmap_l1; unsigned long *msr_bitmap_l0 =3D vmx->nested.vmcs02.msr_bitmap; - struct kvm_host_map map; + struct gfn_to_pfn_cache *gpc; =20 /* Nothing to do if the MSR bitmap is not in use. */ if (!cpu_has_vmx_msr_bitmap() || @@ -648,10 +679,11 @@ static inline bool nested_vmx_prepare_msr_bitmap(stru= ct kvm_vcpu *vcpu, return true; } =20 - if (kvm_vcpu_map_readonly(vcpu, gpa_to_gfn(vmcs12->msr_bitmap), &map)) + gpc =3D &vmx->nested.msr_bitmap_cache; + if (nested_gpc_lock(gpc, vmcs12->msr_bitmap)) return false; =20 - msr_bitmap_l1 =3D (unsigned long *)map.hva; + msr_bitmap_l1 =3D (unsigned long *)gpc->khva; =20 /* * To keep the control flow simple, pay eight 8-byte writes (sixteen @@ -739,7 +771,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct= kvm_vcpu *vcpu, nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, MSR_IA32_PL3_SSP, MSR_TYPE_RW); =20 - kvm_vcpu_unmap(vcpu, &map); + nested_gpc_unlock(gpc); =20 vmx->nested.force_msr_bitmap_recalc =3D false; =20 @@ -5490,6 +5522,8 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu) =20 vmx->nested.vpid02 =3D allocate_vpid(); =20 + kvm_gpc_init(&vmx->nested.msr_bitmap_cache, vcpu->kvm); + vmx->nested.vmcs02_initialized =3D false; vmx->nested.vmxon =3D true; =20 diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index ea93121029f9..d76621403c28 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -152,6 +152,8 @@ struct nested_vmx { =20 struct loaded_vmcs vmcs02; =20 + struct gfn_to_pfn_cache msr_bitmap_cache; + /* * Guest pages referred to in the vmcs02 with host-physical * pointers, so we must keep them pinned while L2 runs. --=20 2.43.0