]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: x86: Don't treat ENTER and LEAVE as branches, because they aren't
authorSean Christopherson <seanjc@google.com>
Fri, 19 Sep 2025 00:46:39 +0000 (17:46 -0700)
committerSean Christopherson <seanjc@google.com>
Mon, 22 Sep 2025 14:14:05 +0000 (07:14 -0700)
Remove the IsBranch flag from ENTER and LEAVE in KVM's emulator, as ENTER
and LEAVE are stack operations, not branches.  Add forced emulation of
said instructions to the PMU counters test to prove that KVM diverges from
hardware, and to guard against regressions.

Opportunistically add a missing "1 MOV" to the selftest comment regarding
the number of instructions per loop, which commit 7803339fa929 ("KVM:
selftests: Use data load to trigger LLC references/misses in Intel PMU")
forgot to add.

Fixes: 018d70ffcfec ("KVM: x86: Update vPMCs when retiring branch instructions")
Cc: Jim Mattson <jmattson@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Link: https://lore.kernel.org/r/20250919004639.1360453-1-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/emulate.c
tools/testing/selftests/kvm/x86/pmu_counters_test.c

index 542d3664afa31aea55248ee8bd6150b0cf4ffbd4..23929151a5b8fdea48303c024b40fe8ec7b6db0f 100644 (file)
@@ -4330,8 +4330,8 @@ static const struct opcode opcode_table[256] = {
        I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
        G(ByteOp, group11), G(0, group11),
        /* 0xC8 - 0xCF */
-       I(Stack | SrcImmU16 | Src2ImmByte | IsBranch, em_enter),
-       I(Stack | IsBranch, em_leave),
+       I(Stack | SrcImmU16 | Src2ImmByte, em_enter),
+       I(Stack, em_leave),
        I(ImplicitOps | SrcImmU16 | IsBranch, em_ret_far_imm),
        I(ImplicitOps | IsBranch, em_ret_far),
        D(ImplicitOps | IsBranch), DI(SrcImmByte | IsBranch, intn),
index 8aaaf25b6111d21be654ce125a5d470f68d00d2a..881cce1c81b8d22e9c7c7a7abb70ec4f6002c43e 100644 (file)
 #define NUM_BRANCH_INSNS_RETIRED       (NUM_LOOPS)
 
 /*
- * Number of instructions in each loop. 1 CLFLUSH/CLFLUSHOPT/NOP, 1 MFENCE,
- * 1 LOOP.
+ * Number of instructions in each loop. 1 ENTER, 1 CLFLUSH/CLFLUSHOPT/NOP,
+ * 1 MFENCE, 1 MOV, 1 LEAVE, 1 LOOP.
  */
-#define NUM_INSNS_PER_LOOP             4
+#define NUM_INSNS_PER_LOOP             6
 
 /*
  * Number of "extra" instructions that will be counted, i.e. the number of
@@ -210,9 +210,11 @@ do {                                                                               \
        __asm__ __volatile__("wrmsr\n\t"                                        \
                             " mov $" __stringify(NUM_LOOPS) ", %%ecx\n\t"      \
                             "1:\n\t"                                           \
+                            FEP "enter $0, $0\n\t"                             \
                             clflush "\n\t"                                     \
                             "mfence\n\t"                                       \
                             "mov %[m], %%eax\n\t"                              \
+                            FEP "leave\n\t"                                    \
                             FEP "loop 1b\n\t"                                  \
                             FEP "mov %%edi, %%ecx\n\t"                         \
                             FEP "xor %%eax, %%eax\n\t"                         \