From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9EC61280335; Wed, 6 May 2026 01:58:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032680; cv=none; b=h1i0yO7cDW3wjv7l65HC1QyKZ6O+nxrmWAfxGwogivbAp7GRErGCvPM40+PLrxOHCRED8QoyCH4cy7X8sAGBOtsmBhRX/dJtf0ZdeqAUsu1asiMpkVSVW4HyGJF6CaXbGYIDyYPVebj1X9+2yd0HUIS0RltZlipUi8ueQ/602xY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032680; c=relaxed/simple; bh=E4MwzKyp8yi3zfN85nny6hxSSlImYZ5aS3B8ll4qV6I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cAsJE2rPqkirQVT3k9yS/ORfnynFg5izOgqDvf4rG28Lu7JM3d/npQAkRNjlrKD6hYcvBr4T7vBnlezNnwEG1+1N3b3/E12Svao2lBvatm1ePQjoC+52iuAQUBfWpyPlWe8GnXkpLmpsPtapKZegbVTSXDyKfh4PS0IFaljYYQk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OJa4i7AF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OJa4i7AF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02FD9C2BCB9; Wed, 6 May 2026 01:57:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032680; bh=E4MwzKyp8yi3zfN85nny6hxSSlImYZ5aS3B8ll4qV6I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OJa4i7AFCMjSMQXdzmlgDZ3YYEd86ME3Z/Hv7vWOMAoakENs8DgFAc92KL1lhfQ1z erCeXmM/CPtVyqqA3Emh/eFxOGoSPcxJASYLuErcHLu8LpulSs6M+ooSEw+PGDWbtw BZvx7uvLOPS4lJ48fr9q9IMIIBxpQoO3S39ds0fd2Xice96ePdRvqbEErEFRPeufGa /0RyCFIlQ7njlMo9inPOushAcLVxPMR/cJGDicBeS5Gef46r6HoLspJvGl7tRy5vLF fzxHuYRGr6HtNUOnim7Ub/O6H6WGqb83ZqGvb4mzvQYtm1DNrvWX0iju2GqNg+5gc+ MbWmUo4Rvolcw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 01/16] KVM: nSVM: Stop leaking single-stepping on VMRUN into L2 Date: Wed, 6 May 2026 01:57:17 +0000 Message-ID: <20260506015733.1671124-2-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" According to the APM, TF on VMRUN causes a #DB after VMRUN completes on the _host_ side. However, KVM injects a #DB in L2 context instead (or exits to userspace if KVM_GUESTDBG_SINGLESTEP is set) in kvm_skip_emulated_instruction(). Introduce __kvm_skip_emulated_instruction(), pull single-step handling into the wrapper, and use __kvm_skip_emulated_instruction() for VMRUN. This ignores TF on VMRUN instead of injecting a spurious exception into L2. Document this virtualization hole with a FIXME. Note that a failed VMRUN would have been correctly single-stepped, but now TF is always ignored for consistency and simplicity purposes. VMX does not support TF on VMLAUNCH/VMRESUME, so it's unlikely that single-stepping VMRUN properly is important, especially if it's only for failed VMRUNs. Fixes: c8e16b78c614 ("x86: KVM: svm: eliminate hardcoded RIP advancement fr= om vmrun_interception()") Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/svm/nested.c | 11 ++++++++--- arch/x86/kvm/x86.c | 15 +++++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index c470e40a00aa4..b191967c9c1e4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -2475,7 +2475,9 @@ void kvm_arch_async_page_present_queued(struct kvm_vc= pu *vcpu); bool kvm_arch_can_dequeue_async_page_present(struct kvm_vcpu *vcpu); extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn); =20 +int __kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu); int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu); + int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err); =20 void __user *__x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 961804df5f451..5dfcbaf7743b0 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1125,11 +1125,16 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) return kvm_handle_memory_failure(vcpu, X86EMUL_IO_NEEDED, NULL); =20 /* Advance RIP past VMRUN as part of the nested #VMEXIT. */ - return kvm_skip_emulated_instruction(vcpu); + return __kvm_skip_emulated_instruction(vcpu); } =20 - /* At this point, VMRUN is guaranteed to not fault; advance RIP. */ - ret =3D kvm_skip_emulated_instruction(vcpu); + /* + * At this point, VMRUN is guaranteed to not fault; advance RIP. + * + * FIXME: If TF is set on VMRUN should inject a #DB (or handle guest + * debugging) right after #VMEXIT, right now it's just ignored. + */ + ret =3D __kvm_skip_emulated_instruction(vcpu); =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0a1b63c63d1a9..31dc48a8111e5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -9272,9 +9272,8 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vc= pu) return 1; } =20 -int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) +int __kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) { - unsigned long rflags =3D kvm_x86_call(get_rflags)(vcpu); int r; =20 r =3D kvm_x86_call(skip_emulated_instruction)(vcpu); @@ -9282,6 +9281,18 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *v= cpu) return 0; =20 kvm_pmu_instruction_retired(vcpu); + return r; +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(__kvm_skip_emulated_instruction); + +int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) +{ + unsigned long rflags =3D kvm_x86_call(get_rflags)(vcpu); + int r; + + r =3D __kvm_skip_emulated_instruction(vcpu); + if (unlikely(!r)) + return 0; =20 /* * rflags is the old, "raw" value of the flags. The new value has --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 56255296BA9; Wed, 6 May 2026 01:58:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032681; cv=none; b=AbrsPS5QN2VIKaeK/i1H+NbMmGXYd7ToWqrbp9C1T0kP/y19iQSZmqj3hYjSFyINAFbIhf8AxcDyJ9etODYZ48MecZdvVBos5vEGu4Uk471tqijhG9DkisErlByo0g2CKKqhMh+M4Aa651Gp1Y9RCLVCr4FWmzG3hqdriiNriy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032681; c=relaxed/simple; bh=mGGd8tZ63q+J62gW32bgSGIV4Zg3Cz+xJFbXsCrIfzM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G6eqDA0qObBBi+jezG7qVhVEzEDnK1Apqf6wXvQ4vt8/CQi4QO2jfCiP/QWxwXHBngy/Eh1ZidtZzjur+Q0AT3kSufNSVKg5KBXieiidudElIv4WXVReOlNgp1skdFAsqVMFl/w3GZzx9Hpm3t8ycgCiis+Q4aCyFlhNytEC6TQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BbY5cdCx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BbY5cdCx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A221CC2BCF7; Wed, 6 May 2026 01:58:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032681; bh=mGGd8tZ63q+J62gW32bgSGIV4Zg3Cz+xJFbXsCrIfzM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BbY5cdCxhmslb3iyPfay2pm78ElX41YQU4Ck5s8QsmhIfA1OjglP7/mFxR9a1TZRW m1ONCBB3A6hbs1LMN73rahvt9npCEC7prnsAP/qt8vIeeKZKhKyDDrI5f+kKE3drLI pzoEE1z7nJW0HAscb5PPMlmZOo09gzK3LpdBxoE8n5VxktQ2y67mBQ0kgZOUwAzd+8 /ghc+i7gm+FmGTViPQO6M/g1jXtMixyep7caFMgIPGQQ3kHf563HtjGsxvRRiYi48H 3oYhLRJPmebUov4hbEuaxJDiN4p9tzx3RKUtRYpl53KskbJGfgWlFgfLfbJIcqUD9y biNWlVWrlpFvA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 02/16] KVM: nSVM: Bail early out of VMRUN emulation if advancing RIP fails Date: Wed, 6 May 2026 01:57:18 +0000 Message-ID: <20260506015733.1671124-3-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" If kvm_skip_emulation_instruction() fails, then RIP could not be advanced correctly (e.g. decode failure when NextRIP is not available). KVM will exit to userspace to handle the emulation failure, but only after stuffing the wrong RIP into vmcb01 and entering guest mode. Bail early and exit to userspace before committing any side-effects of emulating the VMRUN. Unify both calls to __kvm_skip_emulated_instruction() into a single one, but return immediately after if copying and caching vmcb12 failed. A side effect of this is that the FIXME comment is now above the only caller. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 5dfcbaf7743b0..0f6ea490d707b 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1120,21 +1120,22 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) } =20 ret =3D nested_svm_copy_vmcb12_to_cache(vcpu, vmcb12_gpa); - if (ret) { - if (ret =3D=3D -EFAULT) - return kvm_handle_memory_failure(vcpu, X86EMUL_IO_NEEDED, NULL); - - /* Advance RIP past VMRUN as part of the nested #VMEXIT. */ - return __kvm_skip_emulated_instruction(vcpu); - } + if (ret =3D=3D -EFAULT) + return kvm_handle_memory_failure(vcpu, X86EMUL_IO_NEEDED, NULL); =20 /* - * At this point, VMRUN is guaranteed to not fault; advance RIP. + * At this point, VMRUN is guaranteed to not fault; advance RIP. If + * caching vmcb12 failed for other reasons, return immediately afterward + * as a nested #VMEXIT was already set up. * * FIXME: If TF is set on VMRUN should inject a #DB (or handle guest * debugging) right after #VMEXIT, right now it's just ignored. */ - ret =3D __kvm_skip_emulated_instruction(vcpu); + if (!__kvm_skip_emulated_instruction(vcpu)) + return 0; + + if (ret) + return 1; =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1164,7 +1165,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) nested_svm_vmexit(svm); } =20 - return ret; + return 1; } =20 /* Copy state save area fields which are handled by VMRUN */ --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 106452C1595; Wed, 6 May 2026 01:58:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032682; cv=none; b=BgrZCmdqeuk8D+jQHk7JlPrthS9t7F4g4rL8eYXxYXSrQ3CUVO61XlV3pnw2UtAuZ+Y5QHEv8TRvHvwNSJkMVYCB4tfPZdiTjeFKeiDp4Ccq1UIxuJC8GnVlxqjhTroKFyjUWHX/YL4d/Tn5PYd8Byc9pNBs1Pd3cPz4GMDK8iU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032682; c=relaxed/simple; bh=3VXogewOmNTOmXsw7CVdZC4grJsyIcf5O6wmSDCMd98=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TaPV9Y2Xtz4muC9FSgCYh8kVX8Iy3DGG2dwJbn10bXQRDet1SNDAL1AfkKHHCzMxHiIea2iUFSJpxoESc3+oTcxP2XkmPOSU4jjW3GjWPbjTHIhR8UQkcmguDqkY+uMUqrEg7ipQh8pNYdL3X7YZAjH2MdDxh8Ds+5t6HjZ2mhE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GADWGPOd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GADWGPOd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 476C5C2BCB4; Wed, 6 May 2026 01:58:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032681; bh=3VXogewOmNTOmXsw7CVdZC4grJsyIcf5O6wmSDCMd98=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GADWGPOdXUuWQhvUgwzCvEKBVJHIZpnLomA9N6p2ixfLIjAWO6tP2a3COzDmuUaMY 76IiMgdLsOHJfcFuBbSmGkfH+zuZeH67i9qkJXcuaIQfmJ2Luq5GNeTbTy80I3IHGD rVOBmWz+6EWDe2uYqKi9uOqgnL3kbTwVpaLy9SZjp/xYKb3aWpEP3qAGwnl8GtlD5u Y0URpBPtyY8/sHwFSd/ThKr2GmI4pbduFIqlwfiWw79tyEyeXll/QQU6NuF/1c9JbE dKng6tsisJO4MSiZ2udUrzITg3OWP12KQra1eCyfph5z28vP6eACl3Q7LKbMSb0RxQ Hk0JiCjiKc4gw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 03/16] KVM: nSVM: Move VMRUN instruction retirement after entering guest mode Date: Wed, 6 May 2026 01:57:19 +0000 Message-ID: <20260506015733.1671124-4-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" A successful VMRUN retires in guest mode and should be counted by the PMU as a guest instruction. However, __kvm_skip_emulated_instruction() is called before entering guest mode to advance L1's RIP to the instruction following VMRUN. This is needed as the RIP is saved in vmcb01 to be restored on VM-Exit. Since VMRUN emulation is the only caller of __kvm_skip_emulated_instruction(), move retiring instructions for PMU purposes to its wrapper, leaving __kvm_skip_emulated_instruction() as a transparent wrapper around the vendor-specific calls. Note that this is currently a noop because KVM does not virtualize Host-Only/Guest-Only PMC controls yet, so all instructions are counted regardless of the vCPU's host/guest state. But this change is needed for the incoming support for Host-Only/Guest-Only controls to count VMRUN correctly. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 9 ++++++++- arch/x86/kvm/x86.c | 11 +++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 0f6ea490d707b..58c78c889a812 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -30,6 +30,7 @@ #include "lapic.h" #include "svm.h" #include "hyperv.h" +#include "pmu.h" =20 #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK =20 @@ -1135,7 +1136,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) return 0; =20 if (ret) - return 1; + goto insn_retired; =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1165,6 +1166,12 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) nested_svm_vmexit(svm); } =20 +insn_retired: + /* + * A successful VMRUN is counted by the PMU in guest mode, so only + * retire the instruction after potentially entering guest mode. + */ + kvm_pmu_instruction_retired(vcpu); return 1; } =20 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 31dc48a8111e5..08be0a63b93bd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -9274,14 +9274,7 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *v= cpu) =20 int __kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) { - int r; - - r =3D kvm_x86_call(skip_emulated_instruction)(vcpu); - if (unlikely(!r)) - return 0; - - kvm_pmu_instruction_retired(vcpu); - return r; + return kvm_x86_call(skip_emulated_instruction)(vcpu); } EXPORT_SYMBOL_FOR_KVM_INTERNAL(__kvm_skip_emulated_instruction); =20 @@ -9294,6 +9287,8 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vc= pu) if (unlikely(!r)) return 0; =20 + kvm_pmu_instruction_retired(vcpu); + /* * rflags is the old, "raw" value of the flags. The new value has * not been saved yet. --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94583282F13; Wed, 6 May 2026 01:58:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032682; cv=none; b=FHyxXL51XC6teAt4F/D8C4ExTARMDZhjh5i2GCi7XiSkXLfff4WRJ1b1xISDuU5XqxTJ+N63H6HnaeSEIOpeuP5VbXkyRYQz/FusawqFqLsp6+ATkY9uH4EfUjvEvp9b1R70Xqj5sbjN5gSaCi+27xdpT+9UI7PHeDOTA0KR4pE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032682; c=relaxed/simple; bh=cCwH5w0fK4UfQLUAiej/+ef24PRVhP/LsGjCzYXi6Cc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mC5OvWjHkGem5aXOQhlxihGuZLmlB8i0j3No9l7X0JhOKH/VcsgTbc6B1IAcjaG4YQMw+zcbF0t7EKoX8BTgzzGPhNlDg+QpWBr6O6Hx8XYtuHL36vjcEyFTabnInvmBrtjMe94dH/UmZrbKbO+CyrNowV/8JgVWBeF3wD/4ewc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c3wQPgAr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c3wQPgAr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E125FC2BCC9; Wed, 6 May 2026 01:58:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032682; bh=cCwH5w0fK4UfQLUAiej/+ef24PRVhP/LsGjCzYXi6Cc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c3wQPgArAwRFRvdpPpCmcYmD9hypAn1PUW0MdykXMlvQCtdqfJOkqD8fuyLlwEreK gTSY1p4o1Yh+VkwmRmPokva6HB9LYAlwKFRRC6TZIB3dbW/OhbOWWA+gxpSMOOTI0V y3rurMVBLSMLdfak8B+dhhXtf0qFdYS9LJQSJGjNB7+CTKjIqyGM4tG5+yRu+mgIVB UN2tP4xbsBHxjOEUJ4v3vw3w1AHvwNZE0CnKmQb0LrMp2/KnuH+oGPB8hjX26U1xcU eBbsc1qsEXw6YtxsQdBait+wZFoLXpBBG7Mh/QJmP11Lku76FVR3sBWO9Ra7ifXHzV yoPJ123qqS9YQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 04/16] KVM: x86: Move enable_pmu/enable_mediated_pmu to pmu.h and pmu.c Date: Wed, 6 May 2026 01:57:20 +0000 Message-ID: <20260506015733.1671124-5-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" The declaration and definition of enable_pmu/enable_mediated_pmu semantically belongs in pmu.h and pmu.c, and more importantly, pmu.h uses enable_mediated_pmu and relies on the caller including x86.h. There is already precedence for other module params defined outside of x86.c, so move enable_pmu/enable_mediated_pmu to pmu.c. No functional change intended. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 10 ++++++++++ arch/x86/kvm/pmu.h | 3 +++ arch/x86/kvm/x86.c | 9 --------- arch/x86/kvm/x86.h | 3 --- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index e218352e34231..d6ac3c55fce55 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "x86.h" @@ -33,6 +34,15 @@ static struct x86_pmu_capability __read_mostly kvm_host_= pmu; struct x86_pmu_capability __read_mostly kvm_pmu_cap; EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_pmu_cap); =20 +/* Enable/disable PMU virtualization */ +bool __read_mostly enable_pmu =3D true; +EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_pmu); +module_param(enable_pmu, bool, 0444); + +/* Enable/disabled mediated PMU virtualization. */ +bool __read_mostly enable_mediated_pmu; +EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_mediated_pmu); + struct kvm_pmu_emulated_event_selectors { u64 INSTRUCTIONS_RETIRED; u64 BRANCH_INSTRUCTIONS_RETIRED; diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 0925246731cb1..b1f2418e960ac 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -53,6 +53,9 @@ struct kvm_pmu_ops { const u32 MSR_STRIDE; }; =20 +extern bool enable_pmu; +extern bool enable_mediated_pmu; + void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops); =20 void kvm_handle_guest_mediated_pmi(void); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 08be0a63b93bd..0b421ea29977b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -182,15 +182,6 @@ module_param(force_emulation_prefix, int, 0644); int __read_mostly pi_inject_timer =3D -1; module_param(pi_inject_timer, bint, 0644); =20 -/* Enable/disable PMU virtualization */ -bool __read_mostly enable_pmu =3D true; -EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_pmu); -module_param(enable_pmu, bool, 0444); - -/* Enable/disabled mediated PMU virtualization. */ -bool __read_mostly enable_mediated_pmu; -EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_mediated_pmu); - bool __read_mostly eager_page_split =3D true; module_param(eager_page_split, bool, 0644); =20 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 38a905fa86de2..30a69effc81e2 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -490,9 +490,6 @@ fastpath_t handle_fastpath_invd(struct kvm_vcpu *vcpu); extern struct kvm_caps kvm_caps; extern struct kvm_host_values kvm_host; =20 -extern bool enable_pmu; -extern bool enable_mediated_pmu; - void kvm_setup_xss_caps(void); =20 /* --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23C412D9792; Wed, 6 May 2026 01:58:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032683; cv=none; b=B27Bs78vQ/f4PdRvTlZPKq76rB+loyE1pH2piZuuqLTkyvTCZMtZUMK3x1PCtKRhcY0cD71lOHLi06F7EZOTk+w/Q5PhutkLN/B84NWV9NxNLVBef5rBQ27ns9AJiNWMvAn8A+Z1KK0IKI36XYQFqlXcTLxQhdtn/9FANHRtHGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032683; c=relaxed/simple; bh=cEJJ2WyrU/9RGR1OUnEPy2odZL0xSqI7NatJ9TETZUg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RqmtbNoYjv48otscpNUggtgGn1PbVIYAcYzJEAr0pjQA4TbrYMAfMz2+yo54toR+DAlC+7rwGcZpfANNffA25sIymOyl8ctx1V2IFO8TxC5xJJLWTLmeguVbVvSEeYxA310r3M7vgw/+RNW+nRyhnOIMbKOoBCYZ6+9exBbFWao= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T3fhBEjl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="T3fhBEjl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 87674C2BCB9; Wed, 6 May 2026 01:58:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032683; bh=cEJJ2WyrU/9RGR1OUnEPy2odZL0xSqI7NatJ9TETZUg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T3fhBEjltF8OVX9bs0MtAp0D8Ozc6gkuIwi9TmFRHG9x2egML1MvoKSwm+fLfvKBC H5ihLziEZfllkhA3hikDc9/qs/2t0WRrgE30TYl0P7+UwjKk2eJKJRMoGY7cQluPIa eLweVZ3IGA2hdfPTigiZWflM8vThrSVY9ttrVaswlMO7pkr/gELv/xOA6m4byTXjGe /H3Ib6dmnu73uVMQNoKMWxO8idkWtXEwQ4zLCgHLK9K6VP+BCrg8BP+JGbuZn15yg/ E+wAOL/IOmG2dkzEIuTL5srz4BOfic+exgTvsXWb5HlMMg682Nq0aVDvfio7gSieaI VZEOEbgmoEaOA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 05/16] KVM: x86/pmu: Rename reprogram_counters() to clarify usage Date: Wed, 6 May 2026 01:57:21 +0000 Message-ID: <20260506015733.1671124-6-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Rename reprogram_counters() to kvm_pmu_request_counters_reprogram() clarifying that it is more similar to kvm_pmu_request_counter_reprogram(), and less similar to reprogram_counter(). The kvm_pmu_* prefix is also appropriate as the function is exposed in the header. Opportunistically rename the argument from 'diff' to 'counters'. No functional change intended. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 2 +- arch/x86/kvm/pmu.h | 7 ++++--- arch/x86/kvm/vmx/pmu_intel.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index d6ac3c55fce55..afbc731e72174 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -889,7 +889,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_d= ata *msr_info) if (pmu->global_ctrl !=3D data) { diff =3D pmu->global_ctrl ^ data; pmu->global_ctrl =3D data; - reprogram_counters(pmu, diff); + kvm_pmu_request_counters_reprogram(pmu, diff); } /* * Unconditionally forward writes to vendor code, i.e. to the diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index b1f2418e960ac..f8286067722b0 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -210,14 +210,15 @@ static inline void kvm_pmu_request_counter_reprogram(= struct kvm_pmc *pmc) kvm_make_request(KVM_REQ_PMU, pmc->vcpu); } =20 -static inline void reprogram_counters(struct kvm_pmu *pmu, u64 diff) +static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, + u64 counters) { int bit; =20 - if (!diff) + if (!counters) return; =20 - for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX) + for_each_set_bit(bit, (unsigned long *)&counters, X86_PMC_IDX_MAX) set_bit(bit, pmu->reprogram_pmi); kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); } diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 27eb76e6b6a03..9bd77843d8da2 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -391,7 +391,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, str= uct msr_data *msr_info) if (pmu->pebs_enable !=3D data) { diff =3D pmu->pebs_enable ^ data; pmu->pebs_enable =3D data; - reprogram_counters(pmu, diff); + kvm_pmu_request_counters_reprogram(pmu, diff); } break; case MSR_IA32_DS_AREA: --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D35DF2949E0; Wed, 6 May 2026 01:58:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032683; cv=none; b=OTnh4Rlk9+9o+jONWBOz7cn7sZeDtrHj1zvbuwaH/kS0iI843yS2T0i9ZXzm5w1lP4NHKEMpvEGs3Qe5L5xXZK1Ab7d1V9ZTQA82bzm4fxXax7PZdNeJgmhPXmCnhgtI0gVjCc4zYJM+ixJlQR8GwsVJTXfVskm3p9S5fksBabk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032683; c=relaxed/simple; bh=443kmV2JABqO+wrTnYMBhbBvjwSW6NmQa1jp4Q2mwMU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ewusgr3Da8utZpCp4rdhVpQs0rst79nL8ahlTHv2veniaSGdbTUYJ0uUBRR0eQQ7YVXiIsz4KztDCn8sjwTh95dUZTGXhZVFyWa5HnA2k3W2u7TrSktIhvFTKG2aghYgJrqVaKxp1AaRaGr4Wrh6XNaTC3+5IGJAv9HXlzXxeyc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ogj5zDMR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ogj5zDMR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2D4B9C2BCC9; Wed, 6 May 2026 01:58:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032683; bh=443kmV2JABqO+wrTnYMBhbBvjwSW6NmQa1jp4Q2mwMU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ogj5zDMR1dyZAwlQyY2gthesC8Cv+VHcZ11BVBGZ/WNGGZeHM28FokG+T64LsU3J5 6w3sCXRKKF+O2P4Rib4W7m382T5oRzE2IJswPQ+HlQBsmELXFPoWJ4joDpxYLzvAC+ 0E3OyfzhrveK92o2skjeZgmZD0OYerUA3KYNT2Z31LvG0m3aJnX+aYWSKWJ+GJhJMr V7fyDd+ydZf6bltYJ6/2VaZG5k934tL9xuYd7HhQS7G0UzTP3ghCv0oB8l9FYPl0JX AK5CoSxGOnIfjz1GPaSj0mQdUXtpf7C8EvxCaogQRLqXGx5tu8UB+PHBkV8I9h1NMF UIIUB2HDlg6pA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 06/16] KVM: x86/pmu: Do a single atomic OR when reprogramming counters Date: Wed, 6 May 2026 01:57:22 +0000 Message-ID: <20260506015733.1671124-7-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Do a single atomic OR using the atomic overlay of reprogram_pmi bitmask, instead of one atomic set_bit() call per counter. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index f8286067722b0..0e99022168a85 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -213,13 +213,10 @@ static inline void kvm_pmu_request_counter_reprogram(= struct kvm_pmc *pmc) static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, u64 counters) { - int bit; - if (!counters) return; =20 - for_each_set_bit(bit, (unsigned long *)&counters, X86_PMC_IDX_MAX) - set_bit(bit, pmu->reprogram_pmi); + atomic64_or(counters, &pmu->__reprogram_pmi); kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); } =20 --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FE6A2EC0B0; Wed, 6 May 2026 01:58:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032684; cv=none; b=CHkGH6F92cZYveRbM8PUYQYDJI3gSD27QgJ1d6VHhiCJ2/QYgNKJ3RGQOLm+JHMPwbUkZsQQIhBzERVSCYb3D2TPGHwxXWaRKiPNQAJklg0wbkrdMRLXHbWus1/eL5CFfj+zwawwQRlab+ObnHv6UbG+t7nwnxfdZiIeCz+uZP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032684; c=relaxed/simple; bh=QSdeIVvdmKvVTB1W8EWGZfD3/JJ2ggJ/eyHVF66wpDs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AygABAl7jp+sTc1DHq4LF8Kw/B2Pxc5kwm7fDXJNQD+a0UpuMAiqXkrFygoHZuZpHOK9dgIRzIYERw9bgb2rDz5zabr51VJeZEjImy2Quo41FbddwsW9HiIbjjSjcoEWbtYEgItUVbSeKc3m0jriZZkH+XFhTNJY2xsukADH72I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Vx+7WnEc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Vx+7WnEc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C74B6C2BCB4; Wed, 6 May 2026 01:58:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032684; bh=QSdeIVvdmKvVTB1W8EWGZfD3/JJ2ggJ/eyHVF66wpDs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vx+7WnEcGUax3CMH3QK5KGjmadjfVqWtj2VCKNhqxI37NoY8UCusiZj5XRMRS9IWr 71vFDZTpqf+I2ACBcrcsVvKXWJTPiYzS2OkbZt1maEGFhk9NZwG4msz73QwlGgqBDY k1zPR8zPKih04IHyvOhlYX5QGQ75K5cqUkLAsSIpICGnY9S/j4N0NcM0oQUVGLiFvW wILXwwpt9nmjyChDzVHNrDyWWIPJYIg/m5JC+TB7ZHLwg/24dxt2n3K7szuOkIu95b EHTXsTsLcg/0eKW9EzVrX9UJ6D2cys2BW9CCNM3ArUhf5Y6mSeHw3hkTvNFDpFI7+H DCWuFW0j1eSvw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 07/16] KVM: x86/pmu: Check mediated PMU counter enablement before event filters Date: Wed, 6 May 2026 01:57:23 +0000 Message-ID: <20260506015733.1671124-8-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" If the guest disables the counter (by clearing ARCH_PERFMON_EVENTSEL_ENABLE), KVM still performs the PMU filter lookup, even though it doesn't end up changing eventsel_hw. Check if the counter is enabled by the guest before doing the potentially expensive PMU filter lookup. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index afbc731e72174..67dbbd4c73036 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -532,7 +532,7 @@ static bool pmc_is_event_allowed(struct kvm_pmc *pmc) =20 static void kvm_mediated_pmu_refresh_event_filter(struct kvm_pmc *pmc) { - bool allowed =3D pmc_is_event_allowed(pmc); + bool allowed =3D pmc_is_locally_enabled(pmc) && pmc_is_event_allowed(pmc); struct kvm_pmu *pmu =3D pmc_to_pmu(pmc); =20 if (pmc_is_gp(pmc)) { --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48D292F7AAB; Wed, 6 May 2026 01:58:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032685; cv=none; b=VW3DQRzUGft4Y1REWZSYL4AGwlIBFKjL+aCuhJA6Uu3Y0uLO/qy84RpHz+O5Ce1TEq8R3Qr28dfEUXBSEHoHc7K2qjr47G3eCdZFy/YA7Fspe/4MdLddjCTUfxe1clLNN+TZxc1HK6hnmaFHD1VnYDsZIym28COzOZMk2KZXDpI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032685; c=relaxed/simple; bh=KljEwRnIPMMzvljIZP+J/d4mM54f+4wV9Y9YVdi4fT8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uaHjSw/MwSIcU/7qAA6ZGpQuXge+3icc+ihL7yTldg+ROX7Ht1sjhx3OG+sajY/whflhVz38wQChuXFQIz4K40TJp/ECO7NcTfpbO28XLB9xqOlenOo62+LOQsEwsHQgptcgfuy5tl7OjjWTFIPnnOVepUoNvgHhimDIhrwELUI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N0OwRpm/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N0OwRpm/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 70B8AC2BCF4; Wed, 6 May 2026 01:58:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032684; bh=KljEwRnIPMMzvljIZP+J/d4mM54f+4wV9Y9YVdi4fT8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N0OwRpm/tZr/8eOYfx2IqN3/aRYyE1Mpr+O4xbT1pCzx+d/CzrwTC+dnCeSRVCqB0 ZIIy7D1jX/AbjYR2z0jmlcjLvtHKxR80BXUAqMksidfLXqMK1GvT5+m8Y1xkyjfuCV 8HjxLn4QD3Mjy/lgzhlHEkt7tO1HGL4rkZcj/LyU89PzEsnHAUQ/n7gsUdtjcGIelI 46EMmyiIJNxauoGqkDJxQRxRHybEgAJsx4t8zheYWA07auBVAc65UfjF7HCpL1yyh+ QlIz1UKOoujS4NMjAu4ZkgotqQWXBRw2ZklGtdSGJGaR3oehwTTBel1tC2HAdL/Dnb tMoEcKFQXCahg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 08/16] KVM: x86/pmu: Add support for KVM_X86_PMU_OP_OPTIONAL_RET0 Date: Wed, 6 May 2026 01:57:24 +0000 Message-ID: <20260506015733.1671124-9-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Add definitions for KVM_X86_PMU_OP_OPTIONAL_RET0() to resolve to __static_call_return0, similar to KVM_X86_OP_OPTIONAL_RET0(). Move the definition of kvm_pmu_call() to pmu.h, and add declarations for the static PMU calls in the header to allow making callbacks from the header in following changes. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm-x86-pmu-ops.h | 4 +++- arch/x86/include/asm/kvm_host.h | 1 - arch/x86/kvm/pmu.c | 4 ++++ arch/x86/kvm/pmu.h | 8 ++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/= kvm-x86-pmu-ops.h index d5452b3433b7d..03ed2c917bb56 100644 --- a/arch/x86/include/asm/kvm-x86-pmu-ops.h +++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ #if !defined(KVM_X86_PMU_OP) || \ - !defined(KVM_X86_PMU_OP_OPTIONAL) + !defined(KVM_X86_PMU_OP_OPTIONAL) || \ + !defined(KVM_X86_PMU_OP_OPTIONAL_RET0) #error Missing one or more KVM_X86_PMU_OP #defines #else =20 @@ -31,3 +32,4 @@ KVM_X86_PMU_OP(mediated_put) =20 #undef KVM_X86_PMU_OP #undef KVM_X86_PMU_OP_OPTIONAL +#undef KVM_X86_PMU_OP_OPTIONAL_RET0 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index b191967c9c1e4..943adf62839fc 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -2041,7 +2041,6 @@ extern bool __read_mostly enable_device_posted_irqs; extern struct kvm_x86_ops kvm_x86_ops; =20 #define kvm_x86_call(func) static_call(kvm_x86_##func) -#define kvm_pmu_call(func) static_call(kvm_x86_pmu_##func) =20 #define KVM_X86_OP(func) \ DECLARE_STATIC_CALL(kvm_x86_##func, *(((struct kvm_x86_ops *)0)->func)); diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 67dbbd4c73036..9b7e39610be22 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -98,6 +98,7 @@ static struct kvm_pmu_ops kvm_pmu_ops __read_mostly; DEFINE_STATIC_CALL_NULL(kvm_x86_pmu_##func, \ *(((struct kvm_pmu_ops *)0)->func)); #define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP +#define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP #include =20 void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops) @@ -109,6 +110,9 @@ void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_o= ps) #define KVM_X86_PMU_OP(func) \ WARN_ON(!kvm_pmu_ops.func); __KVM_X86_PMU_OP(func) #define KVM_X86_PMU_OP_OPTIONAL __KVM_X86_PMU_OP +#define KVM_X86_PMU_OP_OPTIONAL_RET0(func) \ + static_call_update(kvm_x86_pmu_##func, (void *)kvm_pmu_ops.func ? : \ + (void *)__static_call_return0); #include #undef __KVM_X86_PMU_OP } diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 0e99022168a85..a062f0bc3dbb1 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -53,6 +53,14 @@ struct kvm_pmu_ops { const u32 MSR_STRIDE; }; =20 +#define kvm_pmu_call(func) static_call(kvm_x86_pmu_##func) + +#define KVM_X86_PMU_OP(func) \ + DECLARE_STATIC_CALL(kvm_x86_pmu_##func, *(((struct kvm_pmu_ops *)0)->func= )); +#define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP +#define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP +#include + extern bool enable_pmu; extern bool enable_mediated_pmu; =20 --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A5FA3301493; Wed, 6 May 2026 01:58:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032685; cv=none; b=eDMxMBsHBBEUuvSAJisg8WWj7DkpF/CQb4spl63MuIOD3VWBcTqXYG55imLi7brG9PyROYYixRVCTUd+7QDvMaN+gIVN5lqdG1Bzi3WW5aAeNPuA9wn3Jb6fWjwEkGtmP7Ob4N2iPcLXYZ9oJuaz1oQlZYxBGStP1IuWm70c4jY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032685; c=relaxed/simple; bh=gXzff9reFCnaLdjrAFtxgLc3IYzOqctQSRcX/CnC+y4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k6RneTnjQflNK5wW387F1NinBMiU6JwWEjdZ9VjpqnzLUJWaGMAKoGMnNmwzEoiAOjKUVhHfp2PpvK8IGgcU8uxP8TArRMg9oK46gPP9P1rCn03ziF86Cz0BJdEaeE6rW3tQx7CoBYbfSdru29KM83sHaRg0k+0X42c7Pu0OUgo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qw9WeB9c; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qw9WeB9c" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16EBEC2BCC9; Wed, 6 May 2026 01:58:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032685; bh=gXzff9reFCnaLdjrAFtxgLc3IYzOqctQSRcX/CnC+y4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qw9WeB9cCZboi6/fb/bdjYprfssTpYUqSB+9+ZpJCMY5hJpqAiBfKWcMIaxDXYxDP osN4kICaTScC9IxNgxKD8t8zmMdcgafH+0C2nDGfcwaS/vKJLDgJiQ2bPCim/C9j1x jiS0QPJ6xm1TIpapUoZRh4LFhzb2lHA70hMoR5BhCz8R4UA0XdYq7dq6klq3VFfSbu C4C2447zGYPZFnKF4sI4LjKZuMpbKXuz2JA4UWVi8AdtRpS184DGPdzitjsXNsN6nK 3t4+xIuJe+Gxq3NOzguZ4kFkBRkPiRHObmRxkDnNkc2oZSyPI0EVlqisc6+rN5LsjW F5koODa2BiiJA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 09/16] KVM: x86/pmu: Disable counters based on Host-Only/Guest-Only bits in SVM Date: Wed, 6 May 2026 01:57:25 +0000 Message-ID: <20260506015733.1671124-10-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Introduce an optional per-vendor PMU callback for checking if a counter is disabled in the current mode, and register a callback on AMD to disable a counter based on the vCPU's setting of Host-Only or Guest-Only EVENT_SELECT bits with the mediated PMU. If EFER.SVME is set, all events are counted if both bits are set or cleared. If only one bit is set, the counter is disabled if the vCPU context does not match the set bit. If EFER.SVME is cleared, the counter is disabled if any of the bits is set, otherwise all events are counted. Note that a Linux guest correctly handles this and clears Host-Only when EFER.SVME is cleared, see commit 1018faa6cf23 ("perf/x86/kvm: Fix Host-Only/Guest-Only counting with SVM disabled"). The callback is made from pmc_is_locally_enabled(), which is used for the mediated PMU when updating eventsel_hw in kvm_mediated_pmu_refresh_eventsel_hw(), as well as when checking what PMCs count instructions/branches for emulation in kvm_pmu_recalc_pmc_emulation(). Host-Only and Guest-Only bits are currently reserved, so this change is a noop, but the bits will be allowed with mediated PMU in a following change when fully supported. Originally-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm-x86-pmu-ops.h | 1 + arch/x86/include/asm/perf_event.h | 2 ++ arch/x86/kvm/pmu.c | 1 + arch/x86/kvm/pmu.h | 4 +++- arch/x86/kvm/svm/pmu.c | 32 ++++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/= kvm-x86-pmu-ops.h index 03ed2c917bb56..55442fc355eea 100644 --- a/arch/x86/include/asm/kvm-x86-pmu-ops.h +++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h @@ -24,6 +24,7 @@ KVM_X86_PMU_OP(init) KVM_X86_PMU_OP_OPTIONAL(reset) KVM_X86_PMU_OP_OPTIONAL(deliver_pmi) KVM_X86_PMU_OP_OPTIONAL(cleanup) +KVM_X86_PMU_OP_OPTIONAL_RET0(pmc_is_disabled_in_current_mode) =20 KVM_X86_PMU_OP_OPTIONAL(write_global_ctrl) KVM_X86_PMU_OP(mediated_load) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index ff5acb8b199b0..5961c002b28eb 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -60,6 +60,8 @@ #define AMD64_EVENTSEL_INT_CORE_ENABLE (1ULL << 36) #define AMD64_EVENTSEL_GUESTONLY (1ULL << 40) #define AMD64_EVENTSEL_HOSTONLY (1ULL << 41) +#define AMD64_EVENTSEL_HOST_GUEST_MASK \ + (AMD64_EVENTSEL_HOSTONLY | AMD64_EVENTSEL_GUESTONLY) =20 #define AMD64_EVENTSEL_INT_CORE_SEL_SHIFT 37 #define AMD64_EVENTSEL_INT_CORE_SEL_MASK \ diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 9b7e39610be22..8159b07e9bc20 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -100,6 +100,7 @@ static struct kvm_pmu_ops kvm_pmu_ops __read_mostly; #define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP #define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP #include +EXPORT_STATIC_CALL_GPL(kvm_x86_pmu_pmc_is_disabled_in_current_mode); =20 void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops) { diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index a062f0bc3dbb1..cc7f55d4a78b4 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -36,6 +36,7 @@ struct kvm_pmu_ops { void (*reset)(struct kvm_vcpu *vcpu); void (*deliver_pmi)(struct kvm_vcpu *vcpu); void (*cleanup)(struct kvm_vcpu *vcpu); + bool (*pmc_is_disabled_in_current_mode)(struct kvm_pmc *pmc); =20 bool (*is_mediated_pmu_supported)(struct x86_pmu_capability *host_pmu); void (*mediated_load)(struct kvm_vcpu *vcpu); @@ -201,7 +202,8 @@ static inline bool pmc_is_locally_enabled(struct kvm_pm= c *pmc) pmc->idx - KVM_FIXED_PMC_BASE_IDX) & (INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER); =20 - return pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE; + return (pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) && + !kvm_pmu_call(pmc_is_disabled_in_current_mode)(pmc); } =20 extern struct x86_pmu_capability kvm_pmu_cap; diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index 7aa298eeb0721..41ee6532290e9 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -260,6 +260,37 @@ static void amd_mediated_pmu_put(struct kvm_vcpu *vcpu) wrmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, pmu->global_status); } =20 +static bool amd_pmc_is_disabled_in_current_mode(struct kvm_pmc *pmc) +{ + struct kvm_vcpu *vcpu =3D pmc->vcpu; + u64 host_guest_bits; + + if (!kvm_vcpu_has_mediated_pmu(vcpu)) + return false; + + /* Common code is supposed to check the common enable bit */ + if (WARN_ON_ONCE(!(pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE))) + return false; + + /* If both bits are cleared, the counter is always enabled */ + host_guest_bits =3D pmc->eventsel & AMD64_EVENTSEL_HOST_GUEST_MASK; + if (!host_guest_bits) + return false; + + /* If EFER.SVME=3D0 and either bit is set, the counter is disabled */ + if (!(vcpu->arch.efer & EFER_SVME)) + return true; + + /* + * If EFER.SVME=3D1, the counter is disabled iff only one of the bits is + * set AND the set bit doesn't match the vCPU mode. + */ + if (host_guest_bits =3D=3D AMD64_EVENTSEL_HOST_GUEST_MASK) + return false; + + return !!(host_guest_bits & AMD64_EVENTSEL_GUESTONLY) !=3D is_guest_mode(= vcpu); +} + struct kvm_pmu_ops amd_pmu_ops __initdata =3D { .rdpmc_ecx_to_pmc =3D amd_rdpmc_ecx_to_pmc, .msr_idx_to_pmc =3D amd_msr_idx_to_pmc, @@ -269,6 +300,7 @@ struct kvm_pmu_ops amd_pmu_ops __initdata =3D { .set_msr =3D amd_pmu_set_msr, .refresh =3D amd_pmu_refresh, .init =3D amd_pmu_init, + .pmc_is_disabled_in_current_mode =3D amd_pmc_is_disabled_in_current_mode, =20 .is_mediated_pmu_supported =3D amd_pmu_is_mediated_pmu_supported, .mediated_load =3D amd_mediated_pmu_load, --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A4153090F4; Wed, 6 May 2026 01:58:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032686; cv=none; b=DHY2fPrMtfUUsf588LHWRZ18if68B+mM2t+rA1I+625A4v+mdrfKOLS6pvZb1FtCILfA1//FLCgQVqgJCSFaKoHWrjFAYU/Senu/a/PIah0fD4YLIAPJunhYZkSAQbAIZLnJMhC7TpvpMTMPtuWXwAwV8WrwLahD0LwI2amWz3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032686; c=relaxed/simple; bh=D0gGwhO1ykOS4AUq26hRoOWlWAXn2YByfg6lKqg0bvA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gTwP0ot/uMT7p4bmoQR3Ipay6B+c/BKJ9INmFRVXIQyJlynlmlUYZOYsJtvdxd+F5j3a6by1lTImJUjzdyuieYdLRvmlL342ebxiNHZOK1qTy2itZZ+aRUZjR7Iv3bJJxwa2v13tyYEBM/Mu8iZwojk4nPjpOMKDct9lrXLRvec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QR6IiekC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QR6IiekC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B0536C2BCB9; Wed, 6 May 2026 01:58:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032686; bh=D0gGwhO1ykOS4AUq26hRoOWlWAXn2YByfg6lKqg0bvA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QR6IiekCvdgr1fCdP/HJ51Aw0TxvagK3jNpyClheHTel7tVPznPprkiNuoyqCF1Bb Ybb003bomxi8gEK7E3HHiv1tARQxEK6CBi5dkHpvDTT4FLApJxdMdDZUrDZrUt3Fro 0ZjixU5S5l1hvlaHTJLW/h1JD876XZ+5NMYzaIq7f79nl/CbBx4nnrscFRXctnxzCs D5FNF3k5r3SXEzi5g71f6ed15Ryo++eVadGObsR2M6Jrg22Ct/XWGmhnBNEPN1FHdM XTI3WmcSx+OLoqtIYr5PyTmG2r5nj19CKHEpZXHgFv8hEGuOMnA9q26TJaCZXUfk7/ B/NwdNxdxckhw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 10/16] KVM: x86/pmu: Track mediated PMU counters with mode-specific enables Date: Wed, 6 May 2026 01:57:26 +0000 Message-ID: <20260506015733.1671124-11-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Instead of always checking of a counter needs to be disabled for mode-specific reasons (e.g. Host-Only/Guest-Only bits in SVM), add a bitmap to track such counters. Set the bit for counters using either Host-Only or Guest-Only bits in EVENTSEL on SVM. This bitmap will also be reused in following changes to selectively apply changes to such counters. Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/pmu.c | 1 + arch/x86/kvm/pmu.h | 9 +++++++-- arch/x86/kvm/svm/pmu.c | 6 ++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 943adf62839fc..ad5a795b1ffad 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -594,6 +594,8 @@ struct kvm_pmu { DECLARE_BITMAP(pmc_counting_instructions, X86_PMC_IDX_MAX); DECLARE_BITMAP(pmc_counting_branches, X86_PMC_IDX_MAX); =20 + DECLARE_BITMAP(pmc_has_mode_specific_enables, X86_PMC_IDX_MAX); + u64 ds_area; u64 pebs_enable; u64 pebs_enable_rsvd; diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 8159b07e9bc20..84c834ad2cd47 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -936,6 +936,7 @@ static void kvm_pmu_reset(struct kvm_vcpu *vcpu) pmu->need_cleanup =3D false; =20 bitmap_zero(pmu->reprogram_pmi, X86_PMC_IDX_MAX); + bitmap_zero(pmu->pmc_has_mode_specific_enables, X86_PMC_IDX_MAX); =20 kvm_for_each_pmc(pmu, pmc, i, pmu->all_valid_pmc_idx) { pmc_stop_counter(pmc); diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index cc7f55d4a78b4..34c3c6913ef62 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -202,8 +202,13 @@ static inline bool pmc_is_locally_enabled(struct kvm_p= mc *pmc) pmc->idx - KVM_FIXED_PMC_BASE_IDX) & (INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER); =20 - return (pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) && - !kvm_pmu_call(pmc_is_disabled_in_current_mode)(pmc); + if (!(pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE)) + return false; + + if (!test_bit(pmc->idx, pmu->pmc_has_mode_specific_enables)) + return true; + + return !kvm_pmu_call(pmc_is_disabled_in_current_mode)(pmc); } =20 extern struct x86_pmu_capability kvm_pmu_cap; diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index 41ee6532290e9..b892a25ea4ca9 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -168,6 +168,12 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, stru= ct msr_data *msr_info) pmc->eventsel =3D data; pmc->eventsel_hw =3D (data & ~AMD64_EVENTSEL_HOSTONLY) | AMD64_EVENTSEL_GUESTONLY; + + if (data & AMD64_EVENTSEL_HOST_GUEST_MASK) + __set_bit(pmc->idx, pmu->pmc_has_mode_specific_enables); + else + __clear_bit(pmc->idx, pmu->pmc_has_mode_specific_enables); + kvm_pmu_request_counter_reprogram(pmc); } return 0; --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3574330DEA2; Wed, 6 May 2026 01:58:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032687; cv=none; b=U4Lqxw6FvnSQWHTGmnGXzRFHeMTyyUHCok9kMKEn9Qa6JEL7ulWuiUT2fx75LMTFcEsu3JWNIxPkR0gH5e/iDVNpj7GtbkUJK7XQoH5RVRVqJp01tZzAX2iHWNIRjDRdkViCRCaMTMe5JOF8QnnTvUt3IKc0Afe4jDCMxQxGwrA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032687; c=relaxed/simple; bh=T3cgRqVEVIuSXwcmUq5FZZ2VswWbqrXzW+LAsRgQ7pM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i3qe5zOSf0Gzq7aDtdmpXzg1yS0S3eZIpVkJopL8QIpbq2HRQnAWU0LaPXWUPvqVRxeGb0KiJKvuxSEX14wm85emw8eusfwrEkl0bnoIU2srSlWwAwYF4jM+WrkHGd6UYfzA1cYsj0Qc3v9KuAB8H12nTf95ZxajHKib97fMUoA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ijtc6V39; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ijtc6V39" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 559B2C2BCB4; Wed, 6 May 2026 01:58:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032686; bh=T3cgRqVEVIuSXwcmUq5FZZ2VswWbqrXzW+LAsRgQ7pM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ijtc6V3903ES1BMxpwMWUHiMkCGaawbhqAHr/ZilBegEx+1391fa2LIapyUXcHqf6 6fOhwGXLzaWT/gdr/CBiCCL6lygvphZgPOooZ8zv924OhZQBKL61IUcUvY3vAO6RXp RuPA9LxRoC/0xtrND9ty+0OVCvL56XoA+wm4JA4IJIOqC8w5SvdyZFASS1N5sWKyhy xT8JVxcOPP4h6+bNr+N1DTVGkcZdg9inhKIzKlKRAj4rqeJfvdJ74szN3R6GBI/qKT JE3PKaoGulL31kQJWeS6yLWdk8k4ABayLAGhmQSNk3u9idM553v7PX1y1aKV/60sIp tD9mpnjp+CSLA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 11/16] KVM: x86/pmu: Reprogram Host/Guest-Only counters on nested transitions Date: Wed, 6 May 2026 01:57:27 +0000 Message-ID: <20260506015733.1671124-12-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Reprogram PMU counters on nested transitions for the mediated PMU, to re-evaluate Host-Only and Guest-Only bits and enable/disable the PMU counters accordingly. For example, if Host-Only is set and Guest-Only is cleared, a counter should be disabled when entering guest mode and enabled when exiting guest mode. According to the APM, when EFER.SVME is cleared, setting Host-Only or Guest-Only disables the counter, so also trigger counter reprogramming when EFER.SVME is toggled. Counters setting any of Host-Only and Guest-Only bits are already being tracked in pmc_has_mode_specific_enables, use the bitmap to reprogram these counters. Reprogram the counters synchronously on nested VMRUN/#VMEXIT and EFER.SVME toggling. This is necessary as these instructions are counted based on the new CPU state (after the instruction is retired in hardware). Hence, the PMU needs to be updated before instruction emulation is completed and kvm_pmu_instruction_retired() is called. Defer reprogramming the counters when force leaving guest mode through svm_leave_nested() to avoid potentially reading stale state (e.g. incorrect EFER). All flows force leaving nested are not architectural, so precision is not a priority. Refactor a helper out of kvm_pmu_request_reprogram_counters() that accepts a boolean allowing synchronous vs deferred reprogramming, and use that from SVM code to support both scenarios. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 1 + arch/x86/kvm/pmu.h | 18 ++++++++++++++---- arch/x86/kvm/svm/nested.c | 12 ++++++++++++ arch/x86/kvm/svm/svm.c | 1 + arch/x86/kvm/svm/svm.h | 22 ++++++++++++++++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 84c834ad2cd47..b92dd2e583356 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -685,6 +685,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu) kvm_for_each_pmc(pmu, pmc, bit, bitmap) kvm_pmu_recalc_pmc_emulation(pmu, pmc); } +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_pmu_handle_event); =20 int kvm_pmu_check_rdpmc_early(struct kvm_vcpu *vcpu, unsigned int idx) { diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 34c3c6913ef62..a5821d7c87f93 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -216,6 +216,7 @@ extern struct x86_pmu_capability kvm_pmu_cap; void kvm_init_pmu_capability(struct kvm_pmu_ops *pmu_ops); =20 void kvm_pmu_recalc_pmc_emulation(struct kvm_pmu *pmu, struct kvm_pmc *pmc= ); +void kvm_pmu_handle_event(struct kvm_vcpu *vcpu); =20 static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc) { @@ -225,14 +226,24 @@ static inline void kvm_pmu_request_counter_reprogram(= struct kvm_pmc *pmc) kvm_make_request(KVM_REQ_PMU, pmc->vcpu); } =20 -static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, - u64 counters) +static inline void __kvm_pmu_reprogram_counters(struct kvm_pmu *pmu, + u64 counters, + bool defer) { if (!counters) return; =20 atomic64_or(counters, &pmu->__reprogram_pmi); - kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); + if (defer) + kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); + else + kvm_pmu_handle_event(pmu_to_vcpu(pmu)); +} + +static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, + u64 counters) +{ + __kvm_pmu_reprogram_counters(pmu, counters, true); } =20 /* @@ -261,7 +272,6 @@ static inline bool kvm_pmu_is_fastpath_emulation_allowe= d(struct kvm_vcpu *vcpu) } =20 void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu); -void kvm_pmu_handle_event(struct kvm_vcpu *vcpu); int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data); int kvm_pmu_check_rdpmc_early(struct kvm_vcpu *vcpu, unsigned int idx); bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr); diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 58c78c889a812..bb3362c043395 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -826,6 +826,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_s= vm *svm) =20 /* Enter Guest-Mode */ enter_guest_mode(vcpu); + svm_pmu_handle_nested_transition(svm); =20 /* * Filled at exit: exit_code, exit_info_1, exit_info_2, exit_int_info, @@ -1302,6 +1303,8 @@ void nested_svm_vmexit(struct vcpu_svm *svm) =20 /* Exit Guest-Mode */ leave_guest_mode(vcpu); + svm_pmu_handle_nested_transition(svm); + svm->nested.vmcb12_gpa =3D 0; =20 kvm_warn_on_nested_run_pending(vcpu); @@ -1519,6 +1522,15 @@ void svm_leave_nested(struct kvm_vcpu *vcpu) =20 leave_guest_mode(vcpu); =20 + /* + * Force leaving nested is a non-architectural flow so precision + * is not a priority. Defer updating the PMU until the next vCPU + * run, potentially tolerating some imprecision to avoid poking + * into PMU state from arbitrary contexts (e.g. KVM may end up + * using stale state). + */ + __svm_pmu_handle_nested_transition(svm, true); + svm_switch_vmcb(svm, &svm->vmcb01); =20 nested_svm_uninit_mmu_context(vcpu); diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index e7fdd7a9c280d..7d3a142e63ff8 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -261,6 +261,7 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) set_exception_intercept(svm, GP_VECTOR); } =20 + svm_pmu_handle_nested_transition(svm); kvm_make_request(KVM_REQ_RECALC_INTERCEPTS, vcpu); } =20 diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index a10668d17a16a..71a49af941f4e 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -24,6 +24,7 @@ =20 #include "cpuid.h" #include "kvm_cache_regs.h" +#include "pmu.h" =20 /* * Helpers to convert to/from physical addresses for pages whose address is @@ -877,6 +878,27 @@ void nested_sync_control_from_vmcb02(struct vcpu_svm *= svm); void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm); void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vm= cb); =20 + +static inline void __svm_pmu_handle_nested_transition(struct vcpu_svm *svm= , bool defer) +{ + struct kvm_pmu *pmu =3D vcpu_to_pmu(&svm->vcpu); + u64 counters =3D *(u64 *)pmu->pmc_has_mode_specific_enables; + + __kvm_pmu_reprogram_counters(pmu, counters, defer); +} + +static inline void svm_pmu_handle_nested_transition(struct vcpu_svm *svm) +{ + /* + * Do NOT defer reprogramming the counters by default. Instructions + * causing a state change are counted based on the _new_ CPU state + * (e.g. a successful VMRUN is counted in guest mode). Hence, the + * counters should be reprogrammed with the new state _before_ the + * instruction is potentially counted upon emulation completion. + */ + __svm_pmu_handle_nested_transition(svm, false); +} + extern struct kvm_x86_nested_ops svm_nested_ops; =20 /* avic.c */ --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9473530EF9B; Wed, 6 May 2026 01:58:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032687; cv=none; b=QD5sgcN/aFIhSXAeuP+Wdp8mXiW8i9ukU3sYFhBmHRGU1RF00UBVPKRZbl+lhTJhOxoBOf+WGWJOyUEQD6RmqTUc3f0S+ochHuftPBP86jcmAT4+GdCo1+I8eL/1l920E1jLF1HMRU+YrmPcckjRkKsmVfyVsm+kWzq/ShHq6h4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032687; c=relaxed/simple; bh=gQNoIoPM8at1RTCuEi1IITPXgmkxHGtuc1LZwRLbNHU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uJq0P9GXoFz7Nrpc/CEEiq3aXwOhTQQq/NSaHXvF3HXDsCGmN+i6EaHiVXpctSmGUjlk0eDSVb5qBONxbF/oEX22pGCyh1xqIJ1kAlYsalIXNq0bQjNcbJytWBQo4KWcosyr+DtU4Bvj0CQnD027tn0YsoaQ9RTnYLdpNKWtRn8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m1JFoMhH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="m1JFoMhH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EE8F2C2BCC9; Wed, 6 May 2026 01:58:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032687; bh=gQNoIoPM8at1RTCuEi1IITPXgmkxHGtuc1LZwRLbNHU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m1JFoMhHFFgF9mBAsyFYjuFjyJMDkf1ng1PQrWz64B2s2z7m+FvDeit42QQVt4uzE MwVjJ5CZIMfpkKjiJjzy9JIubXuIcc/+wIUTPzzxhN7V13JTk1pZHfiNJ3wytyAckA YRda92cIkLfhA31PVTZFcsc1oQkzZYxcLRaQ1/AzTGzdKqxd4oac+ee8lgFCzEL52u H1gwOMqjxGvistYgr7Dt9G3wjgk3u8BpoH1g2kEfAAw4yN/a+5R5GDh3d6Vb7vZg89 +ZPcxiEAxLt6rvMXlugC5wBsDmSuj0A3yT2zzqTejs4c4oMrCuN+jBRSpwQdYfqPTL CmbzKp/MgmqPg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 12/16] KVM: x86/pmu: Allow Host-Only/Guest-Only bits with nSVM and mediated PMU Date: Wed, 6 May 2026 01:57:28 +0000 Message-ID: <20260506015733.1671124-13-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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: Jim Mattson Now that KVM correctly handles Host-Only and Guest-Only bits in the event selector MSRs, allow the guest to set them if the vCPU advertises SVM and uses the mediated PMU. Signed-off-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/pmu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index b892a25ea4ca9..c18286545a7ac 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -213,7 +213,11 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) } =20 pmu->counter_bitmask[KVM_PMC_GP] =3D BIT_ULL(48) - 1; + pmu->reserved_bits =3D 0xfffffff000280000ull; + if (guest_cpu_cap_has(vcpu, X86_FEATURE_SVM) && kvm_vcpu_has_mediated_pmu= (vcpu)) + pmu->reserved_bits &=3D ~AMD64_EVENTSEL_HOST_GUEST_MASK; + pmu->raw_event_mask =3D AMD64_RAW_EVENT_MASK; /* not applicable to AMD; but clean them to prevent any fall out */ pmu->counter_bitmask[KVM_PMC_FIXED] =3D 0; --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36F81311C01; Wed, 6 May 2026 01:58:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032688; cv=none; b=H1gDk8zhfnmpFLnfQ7/GIoMWTSdOwG0E/J7sFf1SxaLlmu09Ql2BgpS6KpwQrEg0vSPKm/AmA4vq8DjhSFiIIJZL0wsBqr0fbB6ZZDxEk1AhADlUQ2zKkSPTHRyG8qYu32l+inRFNGHbNXQhBul0p290jcAwAxKkdKF2NmK1jjA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032688; c=relaxed/simple; bh=peLf1xjVZgVyqN2SqYE3bmr9oD1pXuOn5SU63DvVSnA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bBjETw85iIjJI8TVe5pEoaSat3xfL9XtTg4TRjfSpYR85zE0xRnoh2QCXsQcvlQqO5zUE30tNBhb46sr7CLXOkDxgWhdrUDliOXeA7eIxEIdGpnTByh4eDieU6WqLxbh0Z/35Al9GYv9ZZ2DVvBCP4gxwTKFTn5Q5X6RsrT/lig= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=py5jd6/k; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="py5jd6/k" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9350BC2BCB4; Wed, 6 May 2026 01:58:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032688; bh=peLf1xjVZgVyqN2SqYE3bmr9oD1pXuOn5SU63DvVSnA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=py5jd6/kmNtV4adicKCIC1XHKNESaWASbrchA64k1LCHvEW23DQsJYcFxsOxBuov7 /mwxPyh+doMvERuOhPtv+Uj0abyn2xN5Wp8KXHvNG+Z9unP58I5p2gaCU/5umjh8LS ZKmiN9ZtVSvPV5fWsJ1vCUaaez1FUY0dSpEWK555ZBvLURzh6Z728dU8k6F1/eo7/f KnfX8LZ1B1J0wb76tPMQ9hLPSBzBpagdGyWogmiSylecycENY4pSGYDQXAttCUe+WB cmqV/8lNLPX3C/g1c0pe9sFF9OOqGc9kmlrlPO8cjN631o+Z6DJ5N/3Ru9m4HcwcT5 BqaiXS/MI4cAA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 13/16] KVM: selftests: Refactor allocating guest stack into a helper Date: Wed, 6 May 2026 01:57:29 +0000 Message-ID: <20260506015733.1671124-14-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" In preparation for reusing the logic to allocate stacks for nested guests, refactoring allocating a guest stack and aligning RSP into a helper. No functional change intended. Signed-off-by: Yosry Ahmed --- .../testing/selftests/kvm/lib/x86/processor.c | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index b51467d70f6e7..94a1cadb2b26b 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -778,6 +778,30 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vc= pu) REPORT_GUEST_ASSERT(uc); } =20 +static gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages) +{ + int size =3D nr_pages * getpagesize(); + gva_t stack_gva; + + stack_gva =3D __vm_alloc(vm, size, DEFAULT_GUEST_STACK_VADDR_MIN, MEM_REG= ION_DATA); + stack_gva +=3D size; + + /* + * Align stack to match calling sequence requirements in section "The + * Stack Frame" of the System V ABI AMD64 Architecture Processor + * Supplement, which requires the value (%rsp + 8) to be a multiple of + * 16 when control is transferred to the function entry point. + * + * If this code is ever used to launch a vCPU with 32-bit entry point it + * may need to subtract 4 bytes instead of 8 bytes. + */ + TEST_ASSERT(IS_ALIGNED(stack_gva, PAGE_SIZE), + "__vm_alloc() did not provide a page-aligned address"); + stack_gva -=3D 8; + + return stack_gva; +} + void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus) { int r; @@ -820,27 +844,8 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, u= 32 vcpu_id) { struct kvm_mp_state mp_state; struct kvm_regs regs; - gva_t stack_gva; struct kvm_vcpu *vcpu; =20 - stack_gva =3D __vm_alloc(vm, DEFAULT_STACK_PGS * getpagesize(), - DEFAULT_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA); - - stack_gva +=3D DEFAULT_STACK_PGS * getpagesize(); - - /* - * Align stack to match calling sequence requirements in section "The - * Stack Frame" of the System V ABI AMD64 Architecture Processor - * Supplement, which requires the value (%rsp + 8) to be a multiple of - * 16 when control is transferred to the function entry point. - * - * If this code is ever used to launch a vCPU with 32-bit entry point it - * may need to subtract 4 bytes instead of 8 bytes. - */ - TEST_ASSERT(IS_ALIGNED(stack_gva, PAGE_SIZE), - "__vm_alloc() did not provide a page-aligned address"); - stack_gva -=3D 8; - vcpu =3D __vm_vcpu_add(vm, vcpu_id); vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); vcpu_init_sregs(vm, vcpu); @@ -849,7 +854,7 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, u3= 2 vcpu_id) /* Setup guest general purpose registers */ vcpu_regs_get(vcpu, ®s); regs.rflags =3D regs.rflags | 0x2; - regs.rsp =3D stack_gva; + regs.rsp =3D vm_alloc_stack(vm, DEFAULT_STACK_PGS); vcpu_regs_set(vcpu, ®s); =20 /* Setup the MP state */ --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E900317176; Wed, 6 May 2026 01:58:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032689; cv=none; b=NUVVGhCRqa0Lua4ozlynZkJjzx2y3be7pGXMyeby0EBvaFB3M2fWCgk4FtwAiBgXVM502+tPogLsNzd/7wWJFH5LuR/s98VroGgoKOETmg4YPh3/fToaUPlzU+D3Jw45rQWr1HqJ8ZNxPKT4Gbqx7CDxwVdGtKGPmZVZmgvASWc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032689; c=relaxed/simple; bh=VbLJ32Ncrl6JWXs7JHt9AhGT1rBSyUoUB8s+GDb2irY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OzHTz4VL6LBByWqmyGjbcZgY+8vgVNqdGdMpwuh9G9d7bV09yMvX2wvBKT1By0u7TOix7zAAyYtyawbV63P4iHzhyZaeaGF7ZTacMvh8BI7SCFqm5044hjfQaTfGQy+nDWKS4rNBkDDF4Nu4oWK3uzVbbd0xBBRKk3jW5uL5G8Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DN3S069w; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DN3S069w" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 38D19C2BCB9; Wed, 6 May 2026 01:58:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032688; bh=VbLJ32Ncrl6JWXs7JHt9AhGT1rBSyUoUB8s+GDb2irY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DN3S069wB21ijDaab8hQvOU1UPjcHZQtYK2XViBKeJiDiCBi/sEYM5+GmpEqbmEWP oquelY25F4w3Sw/2Z6BdRMjQ3WL99EAHN1bKSzs0qD7/6OoBNzD8xqEX89JzjRAWQa NGH1x2cKIe1CE8imYMRfEKx41NYQO3kNyHp980LuLK1jjTu2Fyf4mDJWZunSpR0SwS Aep65VriqLA1PrrVdFyfObqhXSzpNF0LDnn5epdmAKRg5wLsYK88TLVPVynbjEkPFA i+hkg7CjX8+ue+OFb75Mh0Ccym8XaI6Zz8cb5/ftCYc9OW3a4KJPbZPpTjDCIQ74es oimmSW+0MQ7Bg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 14/16] KVM: selftests: Allocate a dedicated guest page for x86 L2 guest stack Date: Wed, 6 May 2026 01:57:30 +0000 Message-ID: <20260506015733.1671124-15-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Instead of relying on the L1-provided stack for L2, which is usually an array on L1's own stack, allocate a dedicated page of VM memory for the L2 stack in vcpu_alloc_{vmx/svm}() and use that as L2's RSP in the VMCS/VMCB instead of the L1-provided value. Most L1 guest code does not do anything with the L2 stack other than stuff it in RSP, so this change is transparent and the L1-provided stack is silently ignored. The only exception is memstress nested L1 code which puts the vCPU index on L2's stack, so update this code to use the newly allocated stack. L1-provided stacks will be dropped and cleaned up separately. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/x86/processor.h | 2 ++ tools/testing/selftests/kvm/include/x86/svm_util.h | 3 +++ tools/testing/selftests/kvm/include/x86/vmx.h | 2 ++ tools/testing/selftests/kvm/lib/x86/memstress.c | 5 ++--- tools/testing/selftests/kvm/lib/x86/processor.c | 2 +- tools/testing/selftests/kvm/lib/x86/svm.c | 4 +++- tools/testing/selftests/kvm/lib/x86/vmx.c | 4 +++- 7 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 77f576ee7789d..36df2cadbc4f6 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1208,6 +1208,8 @@ struct idt_entry { void vm_install_exception_handler(struct kvm_vm *vm, int vector, void (*handler)(struct ex_regs *)); =20 +gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages); + /* * Exception fixup morphs #DE to an arbitrary magic vector so that '0' can= be * used to signal "no expcetion". diff --git a/tools/testing/selftests/kvm/include/x86/svm_util.h b/tools/tes= ting/selftests/kvm/include/x86/svm_util.h index 6c013eb838beb..3b1cc484fba1c 100644 --- a/tools/testing/selftests/kvm/include/x86/svm_util.h +++ b/tools/testing/selftests/kvm/include/x86/svm_util.h @@ -28,6 +28,9 @@ struct svm_test_data { void *msr_hva; u64 msr_gpa; =20 + /* Stack */ + void *stack; /* gva */ + /* NPT */ u64 ncr3_gpa; }; diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 90fffaf915958..1dcb9b86d33d3 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -524,6 +524,8 @@ struct vmx_pages { u64 apic_access_gpa; void *apic_access; =20 + void *stack; + u64 eptp_gpa; }; =20 diff --git a/tools/testing/selftests/kvm/lib/x86/memstress.c b/tools/testin= g/selftests/kvm/lib/x86/memstress.c index 61cf952cd2dc2..fa07ef037cad1 100644 --- a/tools/testing/selftests/kvm/lib/x86/memstress.c +++ b/tools/testing/selftests/kvm/lib/x86/memstress.c @@ -43,7 +43,7 @@ static void l1_vmx_code(struct vmx_pages *vmx, u64 vcpu_i= d) GUEST_ASSERT(ept_1g_pages_supported()); =20 rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; - *rsp =3D vcpu_id; + *(u64 *)vmx->stack =3D vcpu_id; prepare_vmcs(vmx, memstress_l2_guest_entry, rsp); =20 GUEST_ASSERT(!vmlaunch()); @@ -56,9 +56,8 @@ static void l1_svm_code(struct svm_test_data *svm, u64 vc= pu_id) unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; unsigned long *rsp; =20 - rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; - *rsp =3D vcpu_id; + *(u64 *)svm->stack =3D vcpu_id; generic_svm_setup(svm, memstress_l2_guest_entry, rsp); =20 run_guest(svm->vmcb, svm->vmcb_gpa); diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 94a1cadb2b26b..cf59ffed45b74 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -778,7 +778,7 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vcp= u) REPORT_GUEST_ASSERT(uc); } =20 -static gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages) +gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages) { int size =3D nr_pages * getpagesize(); gva_t stack_gva; diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 3b01605ab016c..4e9c37f8d1a61 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -46,6 +46,8 @@ vcpu_alloc_svm(struct kvm_vm *vm, gva_t *p_svm_gva) svm->msr_gpa =3D addr_gva2gpa(vm, (uintptr_t)svm->msr); memset(svm->msr_hva, 0, getpagesize()); =20 + svm->stack =3D (void *)vm_alloc_stack(vm, 1); + if (vm->stage2_mmu.pgd_created) svm->ncr3_gpa =3D vm->stage2_mmu.pgd; =20 @@ -122,7 +124,7 @@ void generic_svm_setup(struct svm_test_data *svm, void = *guest_rip, void *guest_r ctrl->msrpm_base_pa =3D svm->msr_gpa; =20 vmcb->save.rip =3D (u64)guest_rip; - vmcb->save.rsp =3D (u64)guest_rsp; + vmcb->save.rsp =3D (u64)svm->stack; guest_regs.rdi =3D (u64)svm; =20 if (svm->ncr3_gpa) { diff --git a/tools/testing/selftests/kvm/lib/x86/vmx.c b/tools/testing/self= tests/kvm/lib/x86/vmx.c index 67642759e4a05..81fe85cf22e8f 100644 --- a/tools/testing/selftests/kvm/lib/x86/vmx.c +++ b/tools/testing/selftests/kvm/lib/x86/vmx.c @@ -116,6 +116,8 @@ vcpu_alloc_vmx(struct kvm_vm *vm, gva_t *p_vmx_gva) vmx->vmwrite_gpa =3D addr_gva2gpa(vm, (uintptr_t)vmx->vmwrite); memset(vmx->vmwrite_hva, 0, getpagesize()); =20 + vmx->stack =3D (void *)vm_alloc_stack(vm, 1); + if (vm->stage2_mmu.pgd_created) vmx->eptp_gpa =3D vm->stage2_mmu.pgd; =20 @@ -370,7 +372,7 @@ void prepare_vmcs(struct vmx_pages *vmx, void *guest_ri= p, void *guest_rsp) { init_vmcs_control_fields(vmx); init_vmcs_host_state(); - init_vmcs_guest_state(guest_rip, guest_rsp); + init_vmcs_guest_state(guest_rip, vmx->stack); } =20 bool kvm_cpu_has_ept(void) --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A353231AF1B; Wed, 6 May 2026 01:58:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032689; cv=none; b=Atsk8O4kQo24b8Nk/eP4BAix6CqoX1io8dxTyUS3w/sZ1jfJXqSn3DARX48h5LbBsEbhkSiNcj185XraZQPgm99RX9MawKCcToeRxb6YFYQDlH9nxQFcjLpSGW+5AvPtG9fu1xwaL0nkmUFL3hGzFc+nzvyDcCCSLkNgR3fT2BA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032689; c=relaxed/simple; bh=EXpMS070km2jkmp/gI3DYD1LhoVXg4lpJ6o+o5cUz08=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DprVV+VmjoRtBKvFEnWb6s3iN6LjLExiAwrjHaSkqR44MwktdQFm6mNmosZHfIUJhB9EiIdBUqaVLU+pHLX/alZiPijxSgX1oIh1YPhfiRIHTGdT+G01fCFNPSPkn/8Sv73DjyFFYCjY1bWtf6DM4epFkimJCFOTnwMc/OQAy5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U8NPpcqs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="U8NPpcqs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D310FC4AF0C; Wed, 6 May 2026 01:58:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032689; bh=EXpMS070km2jkmp/gI3DYD1LhoVXg4lpJ6o+o5cUz08=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U8NPpcqsagsDXwDVqNHJ2gn8kZFAEn1e28jJl0ZZKGZUNJ7D5UOgxUYvxplwsrtmS WL/jzaS35ASL6JwFjn0h5A6WCMWeOzemp8LMesJXHkwBZoy2D5VD0ITWomz4ySDYBH ZyMUYaRm7SwBI2B731hvzRTFCuYku5UN8awEQC0obodvAeqZd18vHmicJyfuR7/P/2 IYCzSopHGZkFvLFrVqNXiP0VCb0OcsNkxhSNckI26zTLzGuXEEbnn70Ckm01RSck1i aB5Q8s8X82zTH3g3elxIj97tWrWpbmBUZ4Obrvnt3wCcdKfF2tmFeTOko/KzLjnX9X pBwJHTZ99C6yg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 15/16] KVM: selftests: Drop L1-provided stacks for L2 guests on x86 Date: Wed, 6 May 2026 01:57:31 +0000 Message-ID: <20260506015733.1671124-16-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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" Now that a dedicated page is allocated for L2's stack and stuffed in RSP, the L1-provided stack is unused. Drop the stacks allocated by L1 guest code for L2 in all x86 tests. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/x86/svm_util.h | 2 +- tools/testing/selftests/kvm/include/x86/vmx.h | 2 +- tools/testing/selftests/kvm/lib/x86/memstress.c | 14 ++------------ tools/testing/selftests/kvm/lib/x86/svm.c | 2 +- tools/testing/selftests/kvm/lib/x86/vmx.c | 2 +- tools/testing/selftests/kvm/x86/aperfmperf_test.c | 9 ++------- .../selftests/kvm/x86/evmcs_smm_controls_test.c | 5 +---- tools/testing/selftests/kvm/x86/hyperv_evmcs.c | 6 +----- tools/testing/selftests/kvm/x86/hyperv_svm_test.c | 6 +----- tools/testing/selftests/kvm/x86/kvm_buslock_test.c | 9 ++------- .../selftests/kvm/x86/nested_close_kvm_test.c | 12 ++---------- .../selftests/kvm/x86/nested_dirty_log_test.c | 8 ++------ .../selftests/kvm/x86/nested_emulation_test.c | 4 ++-- .../selftests/kvm/x86/nested_exceptions_test.c | 9 ++------- .../selftests/kvm/x86/nested_invalid_cr3_test.c | 10 ++-------- .../selftests/kvm/x86/nested_tsc_adjust_test.c | 10 ++-------- .../selftests/kvm/x86/nested_tsc_scaling_test.c | 10 ++-------- .../selftests/kvm/x86/nested_vmsave_vmload_test.c | 6 +----- tools/testing/selftests/kvm/x86/smm_test.c | 8 ++------ tools/testing/selftests/kvm/x86/state_test.c | 11 ++--------- tools/testing/selftests/kvm/x86/svm_int_ctl_test.c | 5 +---- .../selftests/kvm/x86/svm_lbr_nested_state.c | 6 +----- .../selftests/kvm/x86/svm_nested_clear_efer_svme.c | 7 +------ .../selftests/kvm/x86/svm_nested_shutdown_test.c | 5 +---- .../kvm/x86/svm_nested_soft_inject_test.c | 6 +----- .../selftests/kvm/x86/svm_nested_vmcb12_gpa.c | 13 ++++--------- tools/testing/selftests/kvm/x86/svm_vmcall_test.c | 5 +---- .../selftests/kvm/x86/triple_fault_event_test.c | 9 ++------- .../selftests/kvm/x86/vmx_apic_access_test.c | 5 +---- .../selftests/kvm/x86/vmx_apicv_updates_test.c | 4 +--- .../kvm/x86/vmx_invalid_nested_guest_state.c | 6 +----- .../selftests/kvm/x86/vmx_nested_la57_state_test.c | 5 +---- .../selftests/kvm/x86/vmx_preemption_timer_test.c | 5 +---- 33 files changed, 49 insertions(+), 177 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/svm_util.h b/tools/tes= ting/selftests/kvm/include/x86/svm_util.h index 3b1cc484fba1c..c201c30485e72 100644 --- a/tools/testing/selftests/kvm/include/x86/svm_util.h +++ b/tools/testing/selftests/kvm/include/x86/svm_util.h @@ -60,7 +60,7 @@ static inline void vmmcall(void) ) =20 struct svm_test_data *vcpu_alloc_svm(struct kvm_vm *vm, gva_t *p_svm_gva); -void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *g= uest_rsp); +void generic_svm_setup(struct svm_test_data *svm, void *guest_rip); void run_guest(struct vmcb *vmcb, u64 vmcb_gpa); =20 static inline bool kvm_cpu_has_npt(void) diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 1dcb9b86d33d3..4bcfd60e3aecb 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -554,7 +554,7 @@ union vmx_ctrl_msr { =20 struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, gva_t *p_vmx_gva); bool prepare_for_vmx_operation(struct vmx_pages *vmx); -void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp); +void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip); bool load_vmcs(struct vmx_pages *vmx); =20 bool ept_1g_pages_supported(void); diff --git a/tools/testing/selftests/kvm/lib/x86/memstress.c b/tools/testin= g/selftests/kvm/lib/x86/memstress.c index fa07ef037cad1..e19e8b5a09c5a 100644 --- a/tools/testing/selftests/kvm/lib/x86/memstress.c +++ b/tools/testing/selftests/kvm/lib/x86/memstress.c @@ -30,21 +30,15 @@ __asm__( " ud2;" ); =20 -#define L2_GUEST_STACK_SIZE 64 - static void l1_vmx_code(struct vmx_pages *vmx, u64 vcpu_id) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - unsigned long *rsp; - GUEST_ASSERT(vmx->vmcs_gpa); GUEST_ASSERT(prepare_for_vmx_operation(vmx)); GUEST_ASSERT(load_vmcs(vmx)); GUEST_ASSERT(ept_1g_pages_supported()); =20 - rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; *(u64 *)vmx->stack =3D vcpu_id; - prepare_vmcs(vmx, memstress_l2_guest_entry, rsp); + prepare_vmcs(vmx, memstress_l2_guest_entry); =20 GUEST_ASSERT(!vmlaunch()); GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL); @@ -53,12 +47,8 @@ static void l1_vmx_code(struct vmx_pages *vmx, u64 vcpu_= id) =20 static void l1_svm_code(struct svm_test_data *svm, u64 vcpu_id) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - unsigned long *rsp; - - rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; *(u64 *)svm->stack =3D vcpu_id; - generic_svm_setup(svm, memstress_l2_guest_entry, rsp); + generic_svm_setup(svm, memstress_l2_guest_entry); =20 run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMMCALL); diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 4e9c37f8d1a61..1445b890986fd 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -83,7 +83,7 @@ void vm_enable_npt(struct kvm_vm *vm) tdp_mmu_init(vm, vm->mmu.pgtable_levels, &pte_masks); } =20 -void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *g= uest_rsp) +void generic_svm_setup(struct svm_test_data *svm, void *guest_rip) { struct vmcb *vmcb =3D svm->vmcb; u64 vmcb_gpa =3D svm->vmcb_gpa; diff --git a/tools/testing/selftests/kvm/lib/x86/vmx.c b/tools/testing/self= tests/kvm/lib/x86/vmx.c index 81fe85cf22e8f..33c477ce4a58b 100644 --- a/tools/testing/selftests/kvm/lib/x86/vmx.c +++ b/tools/testing/selftests/kvm/lib/x86/vmx.c @@ -368,7 +368,7 @@ static inline void init_vmcs_guest_state(void *rip, voi= d *rsp) vmwrite(GUEST_SYSENTER_EIP, vmreadz(HOST_IA32_SYSENTER_EIP)); } =20 -void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp) +void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip) { init_vmcs_control_fields(vmx); init_vmcs_host_state(); diff --git a/tools/testing/selftests/kvm/x86/aperfmperf_test.c b/tools/test= ing/selftests/kvm/x86/aperfmperf_test.c index c91660103137b..845cb685f1743 100644 --- a/tools/testing/selftests/kvm/x86/aperfmperf_test.c +++ b/tools/testing/selftests/kvm/x86/aperfmperf_test.c @@ -54,8 +54,6 @@ static void guest_read_aperf_mperf(void) GUEST_SYNC2(rdmsr(MSR_IA32_APERF), rdmsr(MSR_IA32_MPERF)); } =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { guest_read_aperf_mperf(); @@ -64,21 +62,18 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZE= ]); + generic_svm_setup(svm, l2_guest_code); run_guest(vmcb, svm->vmcb_gpa); } =20 static void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true); GUEST_ASSERT_EQ(load_vmcs(vmx), true); =20 - prepare_vmcs(vmx, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, NULL); =20 /* * Enable MSR bitmaps (the bitmap itself is allocated, zeroed, and set diff --git a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c b/to= ols/testing/selftests/kvm/x86/evmcs_smm_controls_test.c index 5b3aef109cfc5..77ce87c41a868 100644 --- a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c +++ b/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c @@ -52,8 +52,6 @@ static void l2_guest_code(void) static void guest_code(struct vmx_pages *vmx_pages, struct hyperv_test_pages *hv_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; =20 /* Set up Hyper-V enlightenments and eVMCS */ wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID); @@ -62,8 +60,7 @@ static void guest_code(struct vmx_pages *vmx_pages, =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_evmcs(hv_pages)); - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 GUEST_ASSERT(!vmlaunch()); =20 diff --git a/tools/testing/selftests/kvm/x86/hyperv_evmcs.c b/tools/testing= /selftests/kvm/x86/hyperv_evmcs.c index c7fa114aee20f..1bda2cd3f7396 100644 --- a/tools/testing/selftests/kvm/x86/hyperv_evmcs.c +++ b/tools/testing/selftests/kvm/x86/hyperv_evmcs.c @@ -78,9 +78,6 @@ void l2_guest_code(void) void guest_code(struct vmx_pages *vmx_pages, struct hyperv_test_pages *hv_= pages, gpa_t hv_hcall_page_gpa) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID); wrmsr(HV_X64_MSR_HYPERCALL, hv_hcall_page_gpa); =20 @@ -100,8 +97,7 @@ void guest_code(struct vmx_pages *vmx_pages, struct hype= rv_test_pages *hv_pages, GUEST_SYNC(4); GUEST_ASSERT(vmptrstz() =3D=3D hv_pages->enlightened_vmcs_gpa); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 GUEST_SYNC(5); GUEST_ASSERT(vmptrstz() =3D=3D hv_pages->enlightened_vmcs_gpa); diff --git a/tools/testing/selftests/kvm/x86/hyperv_svm_test.c b/tools/test= ing/selftests/kvm/x86/hyperv_svm_test.c index 7a62f6a9d606d..1f74b0fa9b835 100644 --- a/tools/testing/selftests/kvm/x86/hyperv_svm_test.c +++ b/tools/testing/selftests/kvm/x86/hyperv_svm_test.c @@ -18,8 +18,6 @@ #include "svm_util.h" #include "hyperv.h" =20 -#define L2_GUEST_STACK_SIZE 256 - /* Exit to L1 from L2 with RDMSR instruction */ static inline void rdmsr_from_l2(u32 msr) { @@ -69,7 +67,6 @@ static void __attribute__((__flatten__)) guest_code(struc= t svm_test_data *svm, struct hyperv_test_pages *hv_pages, gpa_t pgs_gpa) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; struct hv_vmcb_enlightenments *hve =3D &vmcb->control.hv_enlightenments; =20 @@ -81,8 +78,7 @@ static void __attribute__((__flatten__)) guest_code(struc= t svm_test_data *svm, =20 GUEST_ASSERT(svm->vmcb_gpa); /* Prepare for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* L2 TLB flush setup */ hve->partition_assist_page =3D hv_pages->partition_assist_gpa; diff --git a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c b/tools/tes= ting/selftests/kvm/x86/kvm_buslock_test.c index 52014a3210c88..25a182be00a97 100644 --- a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c +++ b/tools/testing/selftests/kvm/x86/kvm_buslock_test.c @@ -26,8 +26,6 @@ static void guest_generate_buslocks(void) atomic_inc(val); } =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { guest_generate_buslocks(); @@ -36,21 +34,18 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZE= ]); + generic_svm_setup(svm, l2_guest_code); run_guest(vmcb, svm->vmcb_gpa); } =20 static void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true); GUEST_ASSERT_EQ(load_vmcs(vmx), true); =20 - prepare_vmcs(vmx, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, NULL); =20 GUEST_ASSERT(!vmwrite(GUEST_RIP, (u64)l2_guest_code)); GUEST_ASSERT(!vmlaunch()); diff --git a/tools/testing/selftests/kvm/x86/nested_close_kvm_test.c b/tool= s/testing/selftests/kvm/x86/nested_close_kvm_test.c index 761fec2934080..b974cfb347d6e 100644 --- a/tools/testing/selftests/kvm/x86/nested_close_kvm_test.c +++ b/tools/testing/selftests/kvm/x86/nested_close_kvm_test.c @@ -21,8 +21,6 @@ enum { PORT_L0_EXIT =3D 0x2000, }; =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { /* Exit to L0 */ @@ -32,14 +30,11 @@ static void l2_guest_code(void) =20 static void l1_vmx_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 GUEST_ASSERT(!vmlaunch()); GUEST_ASSERT(0); @@ -47,11 +42,8 @@ static void l1_vmx_code(struct vmx_pages *vmx_pages) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* Prepare the VMCB for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT(0); diff --git a/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c b/tool= s/testing/selftests/kvm/x86/nested_dirty_log_test.c index 0e67cce835701..26b474bf13535 100644 --- a/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c +++ b/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c @@ -40,8 +40,6 @@ =20 #define TEST_HVA(vm, idx) addr_gpa2hva(vm, TEST_GPA(idx)) =20 -#define L2_GUEST_STACK_SIZE 64 - /* Use the page offset bits to communicate the access+fault type. */ #define TEST_SYNC_READ_FAULT BIT(0) #define TEST_SYNC_WRITE_FAULT BIT(1) @@ -92,7 +90,6 @@ static void l2_guest_code_tdp_disabled(void) =20 void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; void *l2_rip; =20 GUEST_ASSERT(vmx->vmcs_gpa); @@ -104,7 +101,7 @@ void l1_vmx_code(struct vmx_pages *vmx) else l2_rip =3D l2_guest_code_tdp_disabled; =20 - prepare_vmcs(vmx, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, l2_rip); =20 GUEST_SYNC(TEST_SYNC_NO_FAULT); GUEST_ASSERT(!vmlaunch()); @@ -115,7 +112,6 @@ void l1_vmx_code(struct vmx_pages *vmx) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; void *l2_rip; =20 if (svm->ncr3_gpa) @@ -123,7 +119,7 @@ static void l1_svm_code(struct svm_test_data *svm) else l2_rip =3D l2_guest_code_tdp_disabled; =20 - generic_svm_setup(svm, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_rip); =20 GUEST_SYNC(TEST_SYNC_NO_FAULT); run_guest(svm->vmcb, svm->vmcb_gpa); diff --git a/tools/testing/selftests/kvm/x86/nested_emulation_test.c b/tool= s/testing/selftests/kvm/x86/nested_emulation_test.c index fb7dcbe53ac73..e08c6b0697e50 100644 --- a/tools/testing/selftests/kvm/x86/nested_emulation_test.c +++ b/tools/testing/selftests/kvm/x86/nested_emulation_test.c @@ -57,7 +57,7 @@ static void guest_code(void *test_data) struct svm_test_data *svm =3D test_data; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, NULL, NULL); + generic_svm_setup(svm, NULL); vmcb->save.idtr.limit =3D 0; vmcb->save.rip =3D (u64)l2_guest_code; =20 @@ -69,7 +69,7 @@ static void guest_code(void *test_data) GUEST_ASSERT(prepare_for_vmx_operation(test_data)); GUEST_ASSERT(load_vmcs(test_data)); =20 - prepare_vmcs(test_data, NULL, NULL); + prepare_vmcs(test_data, NULL); GUEST_ASSERT(!vmwrite(GUEST_IDTR_LIMIT, 0)); GUEST_ASSERT(!vmwrite(GUEST_RIP, (u64)l2_guest_code)); GUEST_ASSERT(!vmwrite(EXCEPTION_BITMAP, 0)); diff --git a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c b/too= ls/testing/selftests/kvm/x86/nested_exceptions_test.c index 186e980aa8eee..aeec3121c8e83 100644 --- a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c +++ b/tools/testing/selftests/kvm/x86/nested_exceptions_test.c @@ -5,8 +5,6 @@ #include "vmx.h" #include "svm_util.h" =20 -#define L2_GUEST_STACK_SIZE 256 - /* * Arbitrary, never shoved into KVM/hardware, just need to avoid conflict = with * the "real" exceptions used, #SS/#GP/#DF (12/13/8). @@ -91,9 +89,8 @@ static void svm_run_l2(struct svm_test_data *svm, void *l= 2_code, int vector, static void l1_svm_code(struct svm_test_data *svm) { struct vmcb_control_area *ctrl =3D &svm->vmcb->control; - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; =20 - generic_svm_setup(svm, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, NULL); svm->vmcb->save.idtr.limit =3D 0; ctrl->intercept |=3D BIT_ULL(INTERCEPT_SHUTDOWN); =20 @@ -128,13 +125,11 @@ static void vmx_run_l2(void *l2_code, int vector, u32= error_code) =20 static void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true); =20 GUEST_ASSERT_EQ(load_vmcs(vmx), true); =20 - prepare_vmcs(vmx, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, NULL); GUEST_ASSERT_EQ(vmwrite(GUEST_IDTR_LIMIT, 0), 0); =20 /* diff --git a/tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c b/to= ols/testing/selftests/kvm/x86/nested_invalid_cr3_test.c index 11fd2467d8233..8c2ba9674558e 100644 --- a/tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c +++ b/tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c @@ -11,8 +11,6 @@ #include "kselftest.h" =20 =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { vmcall(); @@ -20,11 +18,9 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; uintptr_t save_cr3; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* Try to run L2 with invalid CR3 and make sure it fails */ save_cr3 =3D svm->vmcb->save.cr3; @@ -42,14 +38,12 @@ static void l1_svm_code(struct svm_test_data *svm) =20 static void l1_vmx_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; uintptr_t save_cr3; =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* Try to run L2 with invalid CR3 and make sure it fails */ save_cr3 =3D vmreadz(GUEST_CR3); diff --git a/tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c b/too= ls/testing/selftests/kvm/x86/nested_tsc_adjust_test.c index f0e4adac47510..cb79d7b9619c2 100644 --- a/tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c +++ b/tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c @@ -34,8 +34,6 @@ #define TSC_ADJUST_VALUE (1ll << 32) #define TSC_OFFSET_VALUE -(1ll << 48) =20 -#define L2_GUEST_STACK_SIZE 64 - enum { PORT_ABORT =3D 0x1000, PORT_REPORT, @@ -75,8 +73,6 @@ static void l2_guest_code(void) =20 static void l1_guest_code(void *data) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* Set TSC from L1 and make sure TSC_ADJUST is updated correctly */ GUEST_ASSERT(rdtsc() < TSC_ADJUST_VALUE); wrmsr(MSR_IA32_TSC, rdtsc() - TSC_ADJUST_VALUE); @@ -93,8 +89,7 @@ static void l1_guest_code(void *data) GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); control |=3D CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETTING; vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); @@ -105,8 +100,7 @@ static void l1_guest_code(void *data) } else { struct svm_test_data *svm =3D data; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 svm->vmcb->control.tsc_offset =3D TSC_OFFSET_VALUE; run_guest(svm->vmcb, svm->vmcb_gpa); diff --git a/tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c b/to= ols/testing/selftests/kvm/x86/nested_tsc_scaling_test.c index 190e93af20a14..18f765835bf4c 100644 --- a/tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c +++ b/tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c @@ -22,8 +22,6 @@ #define TSC_OFFSET_L2 ((u64)-33125236320908) #define TSC_MULTIPLIER_L2 (L2_SCALE_FACTOR << 48) =20 -#define L2_GUEST_STACK_SIZE 64 - enum { USLEEP, UCHECK_L1, UCHECK_L2 }; #define GUEST_SLEEP(sec) ucall(UCALL_SYNC, 2, USLEEP, sec) #define GUEST_CHECK(level, freq) ucall(UCALL_SYNC, 2, level, freq) @@ -82,13 +80,10 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* check that L1's frequency looks alright before launching L2 */ check_tsc_freq(UCHECK_L1); =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* enable TSC scaling for L2 */ wrmsr(MSR_AMD64_TSC_RATIO, L2_SCALE_FACTOR << 32); @@ -105,7 +100,6 @@ static void l1_svm_code(struct svm_test_data *svm) =20 static void l1_vmx_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u32 control; =20 /* check that L1's frequency looks alright before launching L2 */ @@ -115,7 +109,7 @@ static void l1_vmx_code(struct vmx_pages *vmx_pages) GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* prepare the VMCS for L2 execution */ - prepare_vmcs(vmx_pages, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZ= E]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* enable TSC offsetting and TSC scaling for L2 */ control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); diff --git a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c b/= tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c index 85d3f4cc76f39..a130759f39a19 100644 --- a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c +++ b/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c @@ -28,8 +28,6 @@ =20 #define TEST_VMCB_L2_GPA TEST_VMCB_L1_GPA(0) =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code_vmsave(void) { asm volatile("vmsave %0" : : "a"(TEST_VMCB_L2_GPA) : "memory"); @@ -70,10 +68,8 @@ static void l2_guest_code_vmcb1(void) =20 static void l1_guest_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* Each test case initializes the guest RIP below */ - generic_svm_setup(svm, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, NULL); =20 /* Set VMSAVE/VMLOAD intercepts and make sure they work with.. */ svm->vmcb->control.intercept |=3D (BIT_ULL(INTERCEPT_VMSAVE) | diff --git a/tools/testing/selftests/kvm/x86/smm_test.c b/tools/testing/sel= ftests/kvm/x86/smm_test.c index 740051167dbd4..e2542f4ced605 100644 --- a/tools/testing/selftests/kvm/x86/smm_test.c +++ b/tools/testing/selftests/kvm/x86/smm_test.c @@ -63,8 +63,6 @@ static void l2_guest_code(void) =20 static void guest_code(void *arg) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 apicbase =3D rdmsr(MSR_IA32_APICBASE); struct svm_test_data *svm =3D arg; struct vmx_pages *vmx_pages =3D arg; @@ -81,13 +79,11 @@ static void guest_code(void *arg) =20 if (arg) { if (this_cpu_has(X86_FEATURE_SVM)) { - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); } else { GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); } =20 sync_with_host(5); diff --git a/tools/testing/selftests/kvm/x86/state_test.c b/tools/testing/s= elftests/kvm/x86/state_test.c index 409c6cc9f9214..4a1056a6cb8dc 100644 --- a/tools/testing/selftests/kvm/x86/state_test.c +++ b/tools/testing/selftests/kvm/x86/state_test.c @@ -19,8 +19,6 @@ #include "vmx.h" #include "svm_util.h" =20 -#define L2_GUEST_STACK_SIZE 256 - void svm_l2_guest_code(void) { GUEST_SYNC(4); @@ -35,13 +33,11 @@ void svm_l2_guest_code(void) =20 static void svm_l1_guest_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 GUEST_ASSERT(svm->vmcb_gpa); /* Prepare for L2 execution. */ - generic_svm_setup(svm, svm_l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, svm_l2_guest_code); =20 vmcb->control.int_ctl |=3D (V_GIF_ENABLE_MASK | V_GIF_MASK); =20 @@ -78,8 +74,6 @@ void vmx_l2_guest_code(void) =20 static void vmx_l1_guest_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT(vmx_pages->vmcs_gpa); GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_SYNC(3); @@ -89,8 +83,7 @@ static void vmx_l1_guest_code(struct vmx_pages *vmx_pages) GUEST_SYNC(4); GUEST_ASSERT(vmptrstz() =3D=3D vmx_pages->vmcs_gpa); =20 - prepare_vmcs(vmx_pages, vmx_l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, vmx_l2_guest_code); =20 GUEST_SYNC(5); GUEST_ASSERT(vmptrstz() =3D=3D vmx_pages->vmcs_gpa); diff --git a/tools/testing/selftests/kvm/x86/svm_int_ctl_test.c b/tools/tes= ting/selftests/kvm/x86/svm_int_ctl_test.c index d3cc5e4f78831..7b1f4a4818bdd 100644 --- a/tools/testing/selftests/kvm/x86/svm_int_ctl_test.c +++ b/tools/testing/selftests/kvm/x86/svm_int_ctl_test.c @@ -54,15 +54,12 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 x2apic_enable(); =20 /* Prepare for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* No virtual interrupt masking */ vmcb->control.int_ctl &=3D ~V_INTR_MASKING_MASK; diff --git a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c b/tools= /testing/selftests/kvm/x86/svm_lbr_nested_state.c index 7fbfaa054c952..77c6ce9f45078 100644 --- a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c +++ b/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c @@ -9,8 +9,6 @@ #include "svm_util.h" =20 =20 -#define L2_GUEST_STACK_SIZE 64 - #define DO_BRANCH() do { asm volatile("jmp 1f\n 1: nop"); } while (0) =20 struct lbr_branch { @@ -55,7 +53,6 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm, bool nested_lbrv) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; struct lbr_branch l1_branch; =20 @@ -65,8 +62,7 @@ static void l1_guest_code(struct svm_test_data *svm, bool= nested_lbrv) CHECK_BRANCH_MSRS(&l1_branch); =20 /* Run L2, which will also do the same */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 if (nested_lbrv) vmcb->control.misc_ctl2 =3D SVM_MISC2_ENABLE_V_LBR; diff --git a/tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c b= /tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c index 6a89eaffc6578..6bc301207cbcb 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c @@ -8,8 +8,6 @@ #include "kselftest.h" =20 =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { unsigned long efer =3D rdmsr(MSR_EFER); @@ -24,10 +22,7 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); run_guest(svm->vmcb, svm->vmcb_gpa); =20 /* Unreachable, L1 should be shutdown */ diff --git a/tools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c b/t= ools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c index c6ea3d609a629..2a4a216954bb3 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c @@ -19,12 +19,9 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm, struct idt_entry *idt) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 vmcb->control.intercept &=3D ~(BIT(INTERCEPT_SHUTDOWN)); =20 diff --git a/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c = b/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c index f72f11d4c4f83..0b640d09d1943 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c @@ -78,17 +78,13 @@ static void l2_guest_code_nmi(void) =20 static void l1_guest_code(struct svm_test_data *svm, u64 is_nmi, u64 idt_a= lt) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 if (is_nmi) x2apic_enable(); =20 /* Prepare for L2 execution. */ - generic_svm_setup(svm, - is_nmi ? l2_guest_code_nmi : l2_guest_code_int, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, is_nmi ? l2_guest_code_nmi : l2_guest_code_int); =20 vmcb->control.intercept_exceptions |=3D BIT(PF_VECTOR) | BIT(UD_VECTOR); vmcb->control.intercept |=3D BIT(INTERCEPT_NMI) | BIT(INTERCEPT_HLT); diff --git a/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c b/tool= s/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c index a4935ce2fb998..b3f45035745ff 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c @@ -9,14 +9,9 @@ #include "kvm_test_harness.h" #include "test_util.h" =20 - -#define L2_GUEST_STACK_SIZE 64 - #define SYNC_GP 101 #define SYNC_L2_STARTED 102 =20 -static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - static void guest_gp_handler(struct ex_regs *regs) { GUEST_SYNC(SYNC_GP); @@ -30,28 +25,28 @@ static void l2_code(void) =20 static void l1_vmrun(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 asm volatile ("vmrun %[gpa]" : : [gpa] "a" (gpa) : "memory"); } =20 static void l1_vmload(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 asm volatile ("vmload %[gpa]" : : [gpa] "a" (gpa) : "memory"); } =20 static void l1_vmsave(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 asm volatile ("vmsave %[gpa]" : : [gpa] "a" (gpa) : "memory"); } =20 static void l1_vmexit(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT(svm->vmcb->control.exit_code =3D=3D SVM_EXIT_VMMCALL); diff --git a/tools/testing/selftests/kvm/x86/svm_vmcall_test.c b/tools/test= ing/selftests/kvm/x86/svm_vmcall_test.c index b1887242f3b8e..7c57fb7e64221 100644 --- a/tools/testing/selftests/kvm/x86/svm_vmcall_test.c +++ b/tools/testing/selftests/kvm/x86/svm_vmcall_test.c @@ -19,13 +19,10 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 /* Prepare for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 run_guest(vmcb, svm->vmcb_gpa); =20 diff --git a/tools/testing/selftests/kvm/x86/triple_fault_event_test.c b/to= ols/testing/selftests/kvm/x86/triple_fault_event_test.c index f1c488e0d4975..0d83516f4bd08 100644 --- a/tools/testing/selftests/kvm/x86/triple_fault_event_test.c +++ b/tools/testing/selftests/kvm/x86/triple_fault_event_test.c @@ -21,9 +21,6 @@ static void l2_guest_code(void) : : [port] "d" (ARBITRARY_IO_PORT) : "rax"); } =20 -#define L2_GUEST_STACK_SIZE 64 -unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - void l1_guest_code_vmx(struct vmx_pages *vmx) { =20 @@ -31,8 +28,7 @@ void l1_guest_code_vmx(struct vmx_pages *vmx) GUEST_ASSERT(prepare_for_vmx_operation(vmx)); GUEST_ASSERT(load_vmcs(vmx)); =20 - prepare_vmcs(vmx, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, l2_guest_code); =20 GUEST_ASSERT(!vmlaunch()); /* L2 should triple fault after a triple fault event injected. */ @@ -44,8 +40,7 @@ void l1_guest_code_svm(struct svm_test_data *svm) { struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* don't intercept shutdown to test the case of SVM allowing to do so */ vmcb->control.intercept &=3D ~(BIT(INTERCEPT_SHUTDOWN)); diff --git a/tools/testing/selftests/kvm/x86/vmx_apic_access_test.c b/tools= /testing/selftests/kvm/x86/vmx_apic_access_test.c index 1720113eae799..463f73aa9159a 100644 --- a/tools/testing/selftests/kvm/x86/vmx_apic_access_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_apic_access_test.c @@ -36,16 +36,13 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages, unsigned long high_= gpa) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u32 control; =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); control |=3D CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); diff --git a/tools/testing/selftests/kvm/x86/vmx_apicv_updates_test.c b/too= ls/testing/selftests/kvm/x86/vmx_apicv_updates_test.c index 80a4fd1e5bbbe..f9b88a6f6113d 100644 --- a/tools/testing/selftests/kvm/x86/vmx_apicv_updates_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_apicv_updates_test.c @@ -31,15 +31,13 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u32 control; =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZ= E]); + prepare_vmcs(vmx_pages, l2_guest_code); control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); control |=3D CPU_BASED_USE_MSR_BITMAPS; vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); diff --git a/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state= .c b/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c index a2eaceed9ad52..6d88c54f69faa 100644 --- a/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c +++ b/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c @@ -25,15 +25,11 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* * L2 must be run without unrestricted guest, verify that the selftests diff --git a/tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c b= /tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c index f13dee3173837..75073efa926da 100644 --- a/tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c @@ -27,8 +27,6 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 guest_cr4; gpa_t pml5_pa, pml4_pa; u64 *pml5; @@ -42,8 +40,7 @@ static void l1_guest_code(struct vmx_pages *vmx_pages) GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* * Set up L2 with a 4-level page table by pointing its CR3 to diff --git a/tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c b/= tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c index 1b7b6ba23de76..eb8021c33cd43 100644 --- a/tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c @@ -66,8 +66,6 @@ void l2_guest_code(void) =20 void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 l1_vmx_pt_start; u64 l1_vmx_pt_finish; u64 l1_tsc_deadline, l2_tsc_deadline; @@ -77,8 +75,7 @@ void l1_guest_code(struct vmx_pages *vmx_pages) GUEST_ASSERT(load_vmcs(vmx_pages)); GUEST_ASSERT(vmptrstz() =3D=3D vmx_pages->vmcs_gpa); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* * Check for Preemption timer support --=20 2.54.0.545.g6539524ca2-goog From nobody Sat Jun 13 19:00:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2018731E85E; Wed, 6 May 2026 01:58:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032690; cv=none; b=fZf5ZIx9/p6essCMvrxNBCG8T308WRaBRbvIZuOMflsVFSS1lVC4shBz2wwMbR0pi4Ce/A29WTC8QTXI0B+xhE/4OiNb0sgfHyyAo8wbwmUgjDkDm+olIYzdYJEB1SEunVbtHRb+/dNHDH1QJrJZn+Gk+asXqbiDgwKWlXY5U/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778032690; c=relaxed/simple; bh=w7BOcW7oGNOHqoOeMuhJmVj0G58bwZUkFpiGj9J6q9s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b2AxHcIOOeEQuM7fmoJa6kpjnPg87McSFydVUYM8e/rtFizMtT7BusNebJUnrLxM26u+AQCihBBQ0i7KWUEklVXLS9Iy/xwy0ytLKU7D6B7VTdiHPSPk86th+eem3EM07x+Hs86p8LvSTq9lX0CfPxhWHnhudUc+1mKg2x2EUnA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jmWPuKZX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jmWPuKZX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82410C2BCF4; Wed, 6 May 2026 01:58:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778032690; bh=w7BOcW7oGNOHqoOeMuhJmVj0G58bwZUkFpiGj9J6q9s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jmWPuKZXPJf2wYhCs/LNEaxsavZrUIEJTLZR1cvPDOB//zrgx4Wg8yLOEfO07QSOj Md5pX6OgFJKljUzlv21KUv5BfNXY7in9noTHkGrix+FCar/KkanhoD2GdA7YtG2IVx rOzCiX3WQpS56VbHuVqV55FGq27Q3WmGSnCN0dWvRH7I8MuJkdfqQO8MO1IrgLti6z EzlAfj1Vb4sLMNIDCmKOCFWri2mt3eeLIkgusXRwSK+01Ml4x5OtUBg0Ane4mri7rn UeCfieHgUSVfI0rbyV4Bgq3+fUKmG38EVcB4/RK/nGj7ppmytb79sR5OpKpk/i7Ddd dHKimom9o9G/w== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v6 16/16] KVM: selftests: Add svm_pmu_host_guest_test for Host-Only/Guest-Only bits Date: Wed, 6 May 2026 01:57:32 +0000 Message-ID: <20260506015733.1671124-17-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog In-Reply-To: <20260506015733.1671124-1-yosry@kernel.org> References: <20260506015733.1671124-1-yosry@kernel.org> 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: Jim Mattson Add a selftest to verify KVM correctly virtualizes the AMD PMU Host-Only (bit 41) and Guest-Only (bit 40) event selector bits across all relevant SVM state transitions. The test programs 4 PMCs simultaneously with all combinations of the Host-Only and Guest-Only bits, then verifies correct counting behavior with EFER.SVME clear and set, as well as in host mode and guest mode. The test also verifies that updating Host-Only / Guest-Only bits for a PMC works as intended, and that event filtering is still respected. Signed-off-by: Jim Mattson Co-developed-by: Yosry Ahmed Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/Makefile.kvm | 1 + tools/testing/selftests/kvm/include/x86/pmu.h | 6 + .../kvm/x86/svm_pmu_host_guest_test.c | 216 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/svm_pmu_host_guest_test= .c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 9118a5a51b89f..df52e938891e3 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -118,6 +118,7 @@ TEST_GEN_PROGS_x86 +=3D x86/svm_nested_shutdown_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_soft_inject_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_vmcb12_gpa TEST_GEN_PROGS_x86 +=3D x86/svm_lbr_nested_state +TEST_GEN_PROGS_x86 +=3D x86/svm_pmu_host_guest_test TEST_GEN_PROGS_x86 +=3D x86/tsc_scaling_sync TEST_GEN_PROGS_x86 +=3D x86/sync_regs_test TEST_GEN_PROGS_x86 +=3D x86/ucna_injection_test diff --git a/tools/testing/selftests/kvm/include/x86/pmu.h b/tools/testing/= selftests/kvm/include/x86/pmu.h index 98537cc8840d1..608ed83d7c6a6 100644 --- a/tools/testing/selftests/kvm/include/x86/pmu.h +++ b/tools/testing/selftests/kvm/include/x86/pmu.h @@ -38,6 +38,12 @@ #define ARCH_PERFMON_EVENTSEL_INV BIT_ULL(23) #define ARCH_PERFMON_EVENTSEL_CMASK GENMASK_ULL(31, 24) =20 +/* + * These are AMD-specific bits. + */ +#define AMD64_EVENTSEL_GUESTONLY BIT_ULL(40) +#define AMD64_EVENTSEL_HOSTONLY BIT_ULL(41) + /* RDPMC control flags, Intel only. */ #define INTEL_RDPMC_METRICS BIT_ULL(29) #define INTEL_RDPMC_FIXED BIT_ULL(30) diff --git a/tools/testing/selftests/kvm/x86/svm_pmu_host_guest_test.c b/to= ols/testing/selftests/kvm/x86/svm_pmu_host_guest_test.c new file mode 100644 index 0000000000000..ee4633ab79aa7 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_pmu_host_guest_test.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * KVM nested SVM PMU Host-Only/Guest-Only test + * + * Copyright (C) 2026, Google LLC. + * + * Test that KVM correctly virtualizes the AMD PMU Host-Only (bit 41) and + * Guest-Only (bit 40) event selector bits across all SVM state + * transitions. + * + * Programs 4 PMCs simultaneously with all combinations of Host-Only and + * Guest-Only bits, then verifies correct counting behavior with different + * combinations of EFER.SVME and host/guest mode -- as well as event filte= ring. + */ +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" +#include "pmu.h" + +#define EVENTSEL_RETIRED_INSNS (ARCH_PERFMON_EVENTSEL_OS | \ + ARCH_PERFMON_EVENTSEL_USR | \ + ARCH_PERFMON_EVENTSEL_ENABLE | \ + AMD_ZEN_INSTRUCTIONS_RETIRED) + +/* PMC configurations: index corresponds to Host-Only | Guest-Only bits */ +#define PMC_NONE 0 /* Neither bit set */ +#define PMC_G 1 /* Guest-Only bit set */ +#define PMC_H 2 /* Host-Only bit set */ +#define PMC_HG 3 /* Both bits set */ +#define NR_PMCS 4 + +#define LOOP_INSNS 1000 + +static __always_inline void run_instruction_loop(void) +{ + unsigned int i; + + for (i =3D 0; i < LOOP_INSNS; i++) + __asm__ __volatile__("nop"); +} + +static __always_inline void read_counters(uint64_t *counts) +{ + int i; + + for (i =3D 0; i < NR_PMCS; i++) + counts[i] =3D rdmsr(MSR_F15H_PERF_CTR + 2 * i); +} + +static __always_inline void run_and_measure(uint64_t *deltas) +{ + uint64_t before[NR_PMCS], after[NR_PMCS]; + int i; + + read_counters(before); + run_instruction_loop(); + read_counters(after); + + for (i =3D 0; i < NR_PMCS; i++) + deltas[i] =3D after[i] - before[i]; +} + +static void assert_pmc_counts(uint64_t *deltas, unsigned int expected_coun= ting) +{ + int i; + + for (i =3D 0; i < NR_PMCS; i++) { + if (expected_counting & BIT(i)) + GUEST_ASSERT_NE(deltas[i], 0); + else + GUEST_ASSERT_EQ(deltas[i], 0); + } +} + +static uint64_t l2_deltas[NR_PMCS]; + +static void l2_guest_code(void) +{ + run_and_measure(l2_deltas); + vmmcall(); +} + +static void l1_guest_code(struct svm_test_data *svm) +{ + struct vmcb *vmcb =3D svm->vmcb; + uint64_t deltas[NR_PMCS]; + uint64_t eventsel; + int i; + + /* Program 4 PMCs with all combinations of Host-Only/Guest-Only bits */ + for (i =3D 0; i < NR_PMCS; i++) { + eventsel =3D EVENTSEL_RETIRED_INSNS; + if (i & PMC_G) + eventsel |=3D AMD64_EVENTSEL_GUESTONLY; + if (i & PMC_H) + eventsel |=3D AMD64_EVENTSEL_HOSTONLY; + wrmsr(MSR_F15H_PERF_CTL + 2 * i, eventsel); + wrmsr(MSR_F15H_PERF_CTR + 2 * i, 0); + } + + /* Step 1: SVME=3D0 - Only the counter with neither bits set counts */ + wrmsr(MSR_EFER, rdmsr(MSR_EFER) & ~EFER_SVME); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE)); + + /* Step 2: Set SVME=3D1 - In L1 "host mode"; Guest-Only stops */ + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SVME); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 3: VMRUN to L2 - In "guest mode"; Host-Only stops */ + generic_svm_setup(svm, l2_guest_code); + vmcb->control.intercept &=3D ~(1ULL << INTERCEPT_MSR_PROT); + + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + assert_pmc_counts(l2_deltas, BIT(PMC_NONE) | BIT(PMC_G) | BIT(PMC_HG)); + + /* Step 4: After VMEXIT to L1 - Back in "host mode"; Guest-Only stops */ + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 5: Set KVM_PMU_EVENT_DENY - all counters stop */ + GUEST_SYNC(KVM_PMU_EVENT_DENY); + run_and_measure(deltas); + assert_pmc_counts(deltas, 0); + + /* Step 6: Set KVM_PMU_EVENT_ALLOW - back to all except Guest-only */ + GUEST_SYNC(KVM_PMU_EVENT_ALLOW); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 7: Clear Host-Only for PMC_HG - counter stops in "host mode" */ + eventsel =3D rdmsr(MSR_F15H_PERF_CTL + 2 * PMC_HG); + wrmsr(MSR_F15H_PERF_CTL + 2 * PMC_HG, eventsel & ~AMD64_EVENTSEL_HOSTONLY= ); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H)); + + /* Step 8: Restore Host-Only for PMC_HG - counter counts again */ + wrmsr(MSR_F15H_PERF_CTL + 2 * PMC_HG, eventsel); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 9: Clear SVME - Only the counter with neither bits set counts */ + wrmsr(MSR_EFER, rdmsr(MSR_EFER) & ~EFER_SVME); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE)); + + GUEST_DONE(); +} + +static struct kvm_pmu_event_filter *alloc_event_filter(u64 event) +{ + struct kvm_pmu_event_filter *filter; + + filter =3D malloc(sizeof(*filter) + sizeof(event)); + TEST_ASSERT(filter !=3D NULL, "Filter allocation failed"); + + memset(filter, 0, sizeof(*filter)); + memcpy(filter->events, &event, sizeof(event)); + filter->nevents =3D 1; + filter->action =3D KVM_PMU_EVENT_ALLOW; + + return filter; +} + +int main(int argc, char *argv[]) +{ + struct kvm_pmu_event_filter *filter; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct ucall uc; + gva_t svm_gva; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + TEST_REQUIRE(kvm_is_pmu_enabled()); + TEST_REQUIRE(get_kvm_amd_param_bool("enable_mediated_pmu")); + TEST_REQUIRE(host_cpu_is_amd && kvm_cpu_family() >=3D 0x17); + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + + vcpu_alloc_svm(vm, &svm_gva); + vcpu_args_set(vcpu, 1, svm_gva); + + filter =3D alloc_event_filter(AMD_ZEN_INSTRUCTIONS_RETIRED); + + for (;;) { + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + goto done; + case UCALL_DONE: + goto done; + case UCALL_SYNC: + filter->action =3D uc.args[1]; + vm_ioctl(vm, KVM_SET_PMU_EVENT_FILTER, filter); + break; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + goto done; + } + } +done: + kvm_vm_free(vm); + return 0; +} --=20 2.54.0.545.g6539524ca2-goog