[PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop

Sean Christopherson posted 1 patch 1 year ago
arch/x86/include/asm/kvm-x86-ops.h |  1 +
arch/x86/include/asm/kvm_host.h    |  1 +
arch/x86/kvm/svm/svm.c             | 13 ++++++-------
arch/x86/kvm/vmx/main.c            |  1 +
arch/x86/kvm/vmx/vmx.c             | 10 ++++++----
arch/x86/kvm/vmx/x86_ops.h         |  1 +
arch/x86/kvm/x86.c                 |  3 +++
7 files changed, 19 insertions(+), 11 deletions(-)
[PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
Posted by Sean Christopherson 1 year ago
Move the conditional loading of hardware DR6 with the guest's DR6 value
out of the core .vcpu_run() loop to fix a bug where KVM can load hardware
with a stale vcpu->arch.dr6.

When the guest accesses a DR and host userspace isn't debugging the guest,
KVM disables DR interception and loads the guest's values into hardware on
VM-Enter and saves them on VM-Exit.  This allows the guest to access DRs
at will, e.g. so that a sequence of DR accesses to configure a breakpoint
only generates one VM-Exit.

For DR0-DR3, the logic/behavior is identical between VMX and SVM, and also
identical between KVM_DEBUGREG_BP_ENABLED (userspace debugging the guest)
and KVM_DEBUGREG_WONT_EXIT (guest using DRs), and so KVM handles loading
DR0-DR3 in common code, _outside_ of the core kvm_x86_ops.vcpu_run() loop.

But for DR6, the guest's value doesn't need to be loaded into hardware for
KVM_DEBUGREG_BP_ENABLED, and SVM provides a dedicated VMCB field whereas
VMX requires software to manually load the guest value, and so loading the
guest's value into DR6 is handled by {svm,vmx}_vcpu_run(), i.e. is done
_inside_ the core run loop.

Unfortunately, saving the guest values on VM-Exit is initiated by common
x86, again outside of the core run loop.  If the guest modifies DR6 (in
hardware, when DR interception is disabled), and then the next VM-Exit is
a fastpath VM-Exit, KVM will reload hardware DR6 with vcpu->arch.dr6 and
clobber the guest's actual value.

The bug shows up primarily with nested VMX because KVM handles the VMX
preemption timer in the fastpath, and the window between hardware DR6
being modified (in guest context) and DR6 being read by guest software is
orders of magnitude larger in a nested setup.  E.g. in non-nested, the
VMX preemption timer would need to fire precisely between #DB injection
and the #DB handler's read of DR6, whereas with a KVM-on-KVM setup, the
window where hardware DR6 is "dirty" extends all the way from L1 writing
DR6 to VMRESUME (in L1).

    L1's view:
    ==========
    <L1 disables DR interception>
           CPU 0/KVM-7289    [023] d....  2925.640961: kvm_entry: vcpu 0
 A:  L1 Writes DR6
           CPU 0/KVM-7289    [023] d....  2925.640963: <hack>: Set DRs, DR6 = 0xffff0ff1

 B:        CPU 0/KVM-7289    [023] d....  2925.640967: kvm_exit: vcpu 0 reason EXTERNAL_INTERRUPT intr_info 0x800000ec

 D: L1 reads DR6, arch.dr6 = 0
           CPU 0/KVM-7289    [023] d....  2925.640969: <hack>: Sync DRs, DR6 = 0xffff0ff0

           CPU 0/KVM-7289    [023] d....  2925.640976: kvm_entry: vcpu 0
    L2 reads DR6, L1 disables DR interception
           CPU 0/KVM-7289    [023] d....  2925.640980: kvm_exit: vcpu 0 reason DR_ACCESS info1 0x0000000000000216
           CPU 0/KVM-7289    [023] d....  2925.640983: kvm_entry: vcpu 0

           CPU 0/KVM-7289    [023] d....  2925.640983: <hack>: Set DRs, DR6 = 0xffff0ff0

    L2 detects failure
           CPU 0/KVM-7289    [023] d....  2925.640987: kvm_exit: vcpu 0 reason HLT
    L1 reads DR6 (confirms failure)
           CPU 0/KVM-7289    [023] d....  2925.640990: <hack>: Sync DRs, DR6 = 0xffff0ff0

    L0's view:
    ==========
    L2 reads DR6, arch.dr6 = 0
          CPU 23/KVM-5046    [001] d....  3410.005610: kvm_exit: vcpu 23 reason DR_ACCESS info1 0x0000000000000216
          CPU 23/KVM-5046    [001] .....  3410.005610: kvm_nested_vmexit: vcpu 23 reason DR_ACCESS info1 0x0000000000000216

    L2 => L1 nested VM-Exit
          CPU 23/KVM-5046    [001] .....  3410.005610: kvm_nested_vmexit_inject: reason: DR_ACCESS ext_inf1: 0x0000000000000216

          CPU 23/KVM-5046    [001] d....  3410.005610: kvm_entry: vcpu 23
          CPU 23/KVM-5046    [001] d....  3410.005611: kvm_exit: vcpu 23 reason VMREAD
          CPU 23/KVM-5046    [001] d....  3410.005611: kvm_entry: vcpu 23
          CPU 23/KVM-5046    [001] d....  3410.005612: kvm_exit: vcpu 23 reason VMREAD
          CPU 23/KVM-5046    [001] d....  3410.005612: kvm_entry: vcpu 23

    L1 writes DR7, L0 disables DR interception
          CPU 23/KVM-5046    [001] d....  3410.005612: kvm_exit: vcpu 23 reason DR_ACCESS info1 0x0000000000000007
          CPU 23/KVM-5046    [001] d....  3410.005613: kvm_entry: vcpu 23

    L0 writes DR6 = 0 (arch.dr6)
          CPU 23/KVM-5046    [001] d....  3410.005613: <hack>: Set DRs, DR6 = 0xffff0ff0

 A: <L1 writes DR6 = 1, no interception, arch.dr6 is still '0'>

 B:       CPU 23/KVM-5046    [001] d....  3410.005614: kvm_exit: vcpu 23 reason PREEMPTION_TIMER
          CPU 23/KVM-5046    [001] d....  3410.005614: kvm_entry: vcpu 23

 C: L0 writes DR6 = 0 (arch.dr6)
          CPU 23/KVM-5046    [001] d....  3410.005614: <hack>: Set DRs, DR6 = 0xffff0ff0

    L1 => L2 nested VM-Enter
          CPU 23/KVM-5046    [001] d....  3410.005616: kvm_exit: vcpu 23 reason VMRESUME

    L0 reads DR6, arch.dr6 = 0

Reported-by: John Stultz <jstultz@google.com>
Closes: https://lkml.kernel.org/r/CANDhNCq5_F3HfFYABqFGCA1bPd_%2BxgNj-iDQhH4tDk%2Bwi8iZZg%40mail.gmail.com
Fixes: 375e28ffc0cf ("KVM: X86: Set host DR6 only on VMX and for KVM_DEBUGREG_WONT_EXIT")
Fixes: d67668e9dd76 ("KVM: x86, SVM: isolate vcpu->arch.dr6 from vmcb->save.dr6")
Cc: stable@vger.kernel.org
Cc: Jim Mattson <jmattson@google.com>
Tested-by: John Stultz <jstultz@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/include/asm/kvm-x86-ops.h |  1 +
 arch/x86/include/asm/kvm_host.h    |  1 +
 arch/x86/kvm/svm/svm.c             | 13 ++++++-------
 arch/x86/kvm/vmx/main.c            |  1 +
 arch/x86/kvm/vmx/vmx.c             | 10 ++++++----
 arch/x86/kvm/vmx/x86_ops.h         |  1 +
 arch/x86/kvm/x86.c                 |  3 +++
 7 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index 7b4536ff3834..5459bc48cfd1 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -48,6 +48,7 @@ KVM_X86_OP(set_idt)
 KVM_X86_OP(get_gdt)
 KVM_X86_OP(set_gdt)
 KVM_X86_OP(sync_dirty_debug_regs)
+KVM_X86_OP(set_dr6)
 KVM_X86_OP(set_dr7)
 KVM_X86_OP(cache_reg)
 KVM_X86_OP(get_rflags)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 5193c3dfbce1..21d247176858 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1685,6 +1685,7 @@ struct kvm_x86_ops {
 	void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
 	void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
 	void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu);
+	void (*set_dr6)(struct kvm_vcpu *vcpu, unsigned long value);
 	void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value);
 	void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
 	unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 7640a84e554a..a713c803a3a3 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1991,11 +1991,11 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
 	svm->asid = sd->next_asid++;
 }
 
-static void svm_set_dr6(struct vcpu_svm *svm, unsigned long value)
+static void svm_set_dr6(struct kvm_vcpu *vcpu, unsigned long value)
 {
-	struct vmcb *vmcb = svm->vmcb;
+	struct vmcb *vmcb = to_svm(vcpu)->vmcb;
 
-	if (svm->vcpu.arch.guest_state_protected)
+	if (vcpu->arch.guest_state_protected)
 		return;
 
 	if (unlikely(value != vmcb->save.dr6)) {
@@ -4247,10 +4247,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu,
 	 * Run with all-zero DR6 unless needed, so that we can get the exact cause
 	 * of a #DB.
 	 */
-	if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
-		svm_set_dr6(svm, vcpu->arch.dr6);
-	else
-		svm_set_dr6(svm, DR6_ACTIVE_LOW);
+	if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)))
+		svm_set_dr6(vcpu, DR6_ACTIVE_LOW);
 
 	clgi();
 	kvm_load_guest_xsave_state(vcpu);
@@ -5043,6 +5041,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
 	.set_idt = svm_set_idt,
 	.get_gdt = svm_get_gdt,
 	.set_gdt = svm_set_gdt,
+	.set_dr6 = svm_set_dr6,
 	.set_dr7 = svm_set_dr7,
 	.sync_dirty_debug_regs = svm_sync_dirty_debug_regs,
 	.cache_reg = svm_cache_reg,
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 2427f918e763..43ee9ed11291 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -61,6 +61,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
 	.set_idt = vmx_set_idt,
 	.get_gdt = vmx_get_gdt,
 	.set_gdt = vmx_set_gdt,
+	.set_dr6 = vmx_set_dr6,
 	.set_dr7 = vmx_set_dr7,
 	.sync_dirty_debug_regs = vmx_sync_dirty_debug_regs,
 	.cache_reg = vmx_cache_reg,
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index f72835e85b6d..6c56d5235f0f 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5648,6 +5648,12 @@ void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
 	set_debugreg(DR6_RESERVED, 6);
 }
 
+void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	lockdep_assert_irqs_disabled();
+	set_debugreg(vcpu->arch.dr6, 6);
+}
+
 void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
 {
 	vmcs_writel(GUEST_DR7, val);
@@ -7417,10 +7423,6 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
 		vmx->loaded_vmcs->host_state.cr4 = cr4;
 	}
 
-	/* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */
-	if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
-		set_debugreg(vcpu->arch.dr6, 6);
-
 	/* When single-stepping over STI and MOV SS, we must clear the
 	 * corresponding interruptibility bits in the guest state. Otherwise
 	 * vmentry fails as it then expects bit 14 (BS) in pending debug
diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h
index ce3295a67c04..430773a5ef8e 100644
--- a/arch/x86/kvm/vmx/x86_ops.h
+++ b/arch/x86/kvm/vmx/x86_ops.h
@@ -73,6 +73,7 @@ void vmx_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
 void vmx_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
 void vmx_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
 void vmx_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
+void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val);
 void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val);
 void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu);
 void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b2d9a16fd4d3..9d5d267b4e14 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10971,6 +10971,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 		set_debugreg(vcpu->arch.eff_db[1], 1);
 		set_debugreg(vcpu->arch.eff_db[2], 2);
 		set_debugreg(vcpu->arch.eff_db[3], 3);
+		/* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */
+		if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
+			kvm_x86_call(set_dr6)(vcpu, vcpu->arch.dr6);
 	} else if (unlikely(hw_breakpoint_active())) {
 		set_debugreg(0, 7);
 	}

base-commit: eb723766b1030a23c38adf2348b7c3d1409d11f0
-- 
2.48.1.262.g85cc9f2d1e-goog
Re: [PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
Posted by Sean Christopherson 12 months ago
On Fri, 24 Jan 2025 17:18:33 -0800, Sean Christopherson wrote:
> Move the conditional loading of hardware DR6 with the guest's DR6 value
> out of the core .vcpu_run() loop to fix a bug where KVM can load hardware
> with a stale vcpu->arch.dr6.
> 
> When the guest accesses a DR and host userspace isn't debugging the guest,
> KVM disables DR interception and loads the guest's values into hardware on
> VM-Enter and saves them on VM-Exit.  This allows the guest to access DRs
> at will, e.g. so that a sequence of DR accesses to configure a breakpoint
> only generates one VM-Exit.
> 
> [...]

Applied to kvm-x86 fixes, thanks!

[1/1] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
      https://github.com/kvm-x86/linux/commit/c2fee09fc167

--
https://github.com/kvm-x86/linux/tree/next
Re: [PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
Posted by Paolo Bonzini 12 months ago
Queued, thanks.

Paolo
Re: [PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
Posted by Sean Christopherson 12 months ago
On Fri, Feb 14, 2025, Paolo Bonzini wrote:
> Queued, thanks.

Drat, I was too slow today.  I applied and pushed this to "kvm-x86 fixes" and
linux-next (as of yesterday), along with a few other things, I just haven't sent
out the "thanks" yet (got sidetracked).

If you want to grab those, here's a semi-impromptu pull request.  Otherwise I'll
just drop this particular commit.

--

The following changes since commit a64dcfb451e254085a7daee5fe51bf22959d52d3:

  Linux 6.14-rc2 (2025-02-09 12:45:03 -0800)

are available in the Git repository at:

  https://github.com/kvm-x86/linux.git tags/kvm-x86-fixes-6.14-rcN

for you to fetch changes up to c2fee09fc167c74a64adb08656cb993ea475197e:

  KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop (2025-02-12 08:59:38 -0800)

----------------------------------------------------------------
KVM fixes for 6.14 part 1

 - Reject Hyper-V SEND_IPI hypercalls if the local APIC isn't being emulated
   by KVM to fix a NULL pointer dereference.

 - Enter guest mode (L2) from KVM's perspective before initializing the vCPU's
   nested NPT MMU so that the MMU is properly tagged for L2, not L1.

 - Load the guest's DR6 outside of the innermost .vcpu_run() loop, as the
   guest's value may be stale if a VM-Exit is handled in the fastpath.

----------------------------------------------------------------
Sean Christopherson (6):
      KVM: x86: Reject Hyper-V's SEND_IPI hypercalls if local APIC isn't in-kernel
      KVM: selftests: Mark test_hv_cpuid_e2big() static in Hyper-V CPUID test
      KVM: selftests: Manage CPUID array in Hyper-V CPUID test's core helper
      KVM: selftests: Add CPUID tests for Hyper-V features that need in-kernel APIC
      KVM: nSVM: Enter guest mode before initializing nested NPT MMU
      KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop

 arch/x86/include/asm/kvm-x86-ops.h             |  1 +
 arch/x86/include/asm/kvm_host.h                |  1 +
 arch/x86/kvm/hyperv.c                          |  6 +++++-
 arch/x86/kvm/mmu/mmu.c                         |  2 +-
 arch/x86/kvm/svm/nested.c                      | 10 +++++-----
 arch/x86/kvm/svm/svm.c                         | 13 ++++++-------
 arch/x86/kvm/vmx/main.c                        |  1 +
 arch/x86/kvm/vmx/vmx.c                         | 10 ++++++----
 arch/x86/kvm/vmx/x86_ops.h                     |  1 +
 arch/x86/kvm/x86.c                             |  3 +++
 tools/testing/selftests/kvm/x86/hyperv_cpuid.c | 47 ++++++++++++++++++++++++++++++++---------------
 11 files changed, 62 insertions(+), 33 deletions(-)
Re: [PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
Posted by Paolo Bonzini 12 months ago
On 2/15/25 01:06, Sean Christopherson wrote:
> On Fri, Feb 14, 2025, Paolo Bonzini wrote:
>> Queued, thanks.
> 
> Drat, I was too slow today.  I applied and pushed this to "kvm-x86 fixes" and
> linux-next (as of yesterday), along with a few other things, I just haven't sent
> out the "thanks" yet (got sidetracked).
> 
> If you want to grab those, here's a semi-impromptu pull request.  Otherwise I'll
> just drop this particular commit.

I had "KVM: nSVM: Enter guest mode before initializing nested NPT MMU" 
on my list, but not the others.

I'll just pull these, thanks.

Paolo

> --
> 
> The following changes since commit a64dcfb451e254085a7daee5fe51bf22959d52d3:
> 
>    Linux 6.14-rc2 (2025-02-09 12:45:03 -0800)
> 
> are available in the Git repository at:
> 
>    https://github.com/kvm-x86/linux.git tags/kvm-x86-fixes-6.14-rcN
> 
> for you to fetch changes up to c2fee09fc167c74a64adb08656cb993ea475197e:
> 
>    KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop (2025-02-12 08:59:38 -0800)
> 
> ----------------------------------------------------------------
> KVM fixes for 6.14 part 1
> 
>   - Reject Hyper-V SEND_IPI hypercalls if the local APIC isn't being emulated
>     by KVM to fix a NULL pointer dereference.
> 
>   - Enter guest mode (L2) from KVM's perspective before initializing the vCPU's
>     nested NPT MMU so that the MMU is properly tagged for L2, not L1.
> 
>   - Load the guest's DR6 outside of the innermost .vcpu_run() loop, as the
>     guest's value may be stale if a VM-Exit is handled in the fastpath.
> 
> ----------------------------------------------------------------
> Sean Christopherson (6):
>        KVM: x86: Reject Hyper-V's SEND_IPI hypercalls if local APIC isn't in-kernel
>        KVM: selftests: Mark test_hv_cpuid_e2big() static in Hyper-V CPUID test
>        KVM: selftests: Manage CPUID array in Hyper-V CPUID test's core helper
>        KVM: selftests: Add CPUID tests for Hyper-V features that need in-kernel APIC
>        KVM: nSVM: Enter guest mode before initializing nested NPT MMU
>        KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
> 
>   arch/x86/include/asm/kvm-x86-ops.h             |  1 +
>   arch/x86/include/asm/kvm_host.h                |  1 +
>   arch/x86/kvm/hyperv.c                          |  6 +++++-
>   arch/x86/kvm/mmu/mmu.c                         |  2 +-
>   arch/x86/kvm/svm/nested.c                      | 10 +++++-----
>   arch/x86/kvm/svm/svm.c                         | 13 ++++++-------
>   arch/x86/kvm/vmx/main.c                        |  1 +
>   arch/x86/kvm/vmx/vmx.c                         | 10 ++++++----
>   arch/x86/kvm/vmx/x86_ops.h                     |  1 +
>   arch/x86/kvm/x86.c                             |  3 +++
>   tools/testing/selftests/kvm/x86/hyperv_cpuid.c | 47 ++++++++++++++++++++++++++++++++---------------
>   11 files changed, 62 insertions(+), 33 deletions(-)
>
Re: [PATCH] KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
Posted by Sean Christopherson 12 months ago
On Sat, Feb 15, 2025, Paolo Bonzini wrote:
> On 2/15/25 01:06, Sean Christopherson wrote:
> > On Fri, Feb 14, 2025, Paolo Bonzini wrote:
> > > Queued, thanks.
> > 
> > Drat, I was too slow today.  I applied and pushed this to "kvm-x86 fixes" and
> > linux-next (as of yesterday), along with a few other things, I just haven't sent
> > out the "thanks" yet (got sidetracked).
> > 
> > If you want to grab those, here's a semi-impromptu pull request.  Otherwise I'll
> > just drop this particular commit.
> 
> I had "KVM: nSVM: Enter guest mode before initializing nested NPT MMU" on my
> list, but not the others.
> 
> I'll just pull these, thanks.

Heh, while you're here, here's combined pull request for the selftests changes
that missed 6.14 due to the pmu_counters_test snafumi[1][2]?

I'm a-ok if you want to hold off until 6.15.  I have them sitting in a separate
branch (selftests_6.14), and don't anticipate conflicts, so it's no trouble to
carry them until the next merge window.

[1] https://lore.kernel.org/all/Z6qN3wPXH4cbRzLP@google.com
[2] https://lore.kernel.org/all/20250117010718.2328467-5-seanjc@google.com

---
The following changes since commit 10b2c8a67c4b8ec15f9d07d177f63b563418e948:

  Merge tag 'kvm-x86-fixes-6.13-rcN' of https://github.com/kvm-x86/linux into HEAD (2024-12-22 12:59:33 -0500)

are available in the Git repository at:

  https://github.com/kvm-x86/linux.git tags/kvm-x86-selftests-6.14-2

for you to fetch changes up to 54108e73344480c3e5f3799129970009f52c59f4:

  KVM: selftests: Print out the actual Top-Down Slots count on failure (2025-02-12 08:34:56 -0800)

----------------------------------------------------------------
KVM selftests changes for 6.14:

 - Misc cleanups and prep work.

 - Annotate _no_printf() with "printf" so that pr_debug() statements are
   checked by the compiler for default builds (and pr_info() when QUIET).

 - Attempt to whack the last LLC references/misses mole in the Intel PMU
   counters test by adding a data load and doing CLFLUSH{OPT} on the data
   instead of the code being executed.  The theory is that modern Intel CPUs
   have learned new code prefetching tricks that bypass the PMU counters.

 - Fix a flaw in the Intel PMU counters test where it asserts that an event is
   counting correctly without actually knowing what the event counts on the
   underlying hardware.

----------------------------------------------------------------
Chen Ni (1):
      KVM: selftests: Remove unneeded semicolon

Colton Lewis (2):
      KVM: selftests: Fix typos in x86's PMU counter test's macro variable use
      KVM: selftests: Add defines for AMD PMU CPUID features and properties

Isaku Yamahata (1):
      KVM: selftests: Add printf attribute to _no_printf()

Sean Christopherson (7):
      KVM: selftests: Use data load to trigger LLC references/misses in Intel PMU
      KVM: selftests: Add helpers for locally (un)blocking IRQs on x86
      KVM: selftests: Make Intel arch events globally available in PMU counters test
      KVM: selftests: Only validate counts for hardware-supported arch events
      KVM: selftests: Remove dead code in Intel PMU counters test
      KVM: selftests: Drop the "feature event" param from guest test helpers
      KVM: selftests: Print out the actual Top-Down Slots count on failure

 tools/testing/selftests/kvm/access_tracking_perf_test.c |   2 +-
 tools/testing/selftests/kvm/include/test_util.h         |   2 +-
 tools/testing/selftests/kvm/include/x86/processor.h     |  47 +++++++++++++++++++++++++++++++++
 tools/testing/selftests/kvm/x86/hyperv_ipi.c            |   6 +++--
 tools/testing/selftests/kvm/x86/pmu_counters_test.c     | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------
 tools/testing/selftests/kvm/x86/svm_int_ctl_test.c      |   5 +---
 tools/testing/selftests/kvm/x86/ucna_injection_test.c   |   2 +-
 tools/testing/selftests/kvm/x86/xapic_ipi_test.c        |   3 ++-
 tools/testing/selftests/kvm/x86/xapic_state_test.c      |   4 +--
 tools/testing/selftests/kvm/x86/xen_shinfo_test.c       |   5 +---
 10 files changed, 151 insertions(+), 83 deletions(-)