Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: Don't treat ENTER and LEAVE as branches, because they aren't

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>

+7 -5
+2 -2
arch/x86/kvm/emulate.c
··· 4330 4330 I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg), 4331 4331 G(ByteOp, group11), G(0, group11), 4332 4332 /* 0xC8 - 0xCF */ 4333 - I(Stack | SrcImmU16 | Src2ImmByte | IsBranch, em_enter), 4334 - I(Stack | IsBranch, em_leave), 4333 + I(Stack | SrcImmU16 | Src2ImmByte, em_enter), 4334 + I(Stack, em_leave), 4335 4335 I(ImplicitOps | SrcImmU16 | IsBranch, em_ret_far_imm), 4336 4336 I(ImplicitOps | IsBranch, em_ret_far), 4337 4337 D(ImplicitOps | IsBranch), DI(SrcImmByte | IsBranch, intn),
+5 -3
tools/testing/selftests/kvm/x86/pmu_counters_test.c
··· 14 14 #define NUM_BRANCH_INSNS_RETIRED (NUM_LOOPS) 15 15 16 16 /* 17 - * Number of instructions in each loop. 1 CLFLUSH/CLFLUSHOPT/NOP, 1 MFENCE, 18 - * 1 LOOP. 17 + * Number of instructions in each loop. 1 ENTER, 1 CLFLUSH/CLFLUSHOPT/NOP, 18 + * 1 MFENCE, 1 MOV, 1 LEAVE, 1 LOOP. 19 19 */ 20 - #define NUM_INSNS_PER_LOOP 4 20 + #define NUM_INSNS_PER_LOOP 6 21 21 22 22 /* 23 23 * Number of "extra" instructions that will be counted, i.e. the number of ··· 210 210 __asm__ __volatile__("wrmsr\n\t" \ 211 211 " mov $" __stringify(NUM_LOOPS) ", %%ecx\n\t" \ 212 212 "1:\n\t" \ 213 + FEP "enter $0, $0\n\t" \ 213 214 clflush "\n\t" \ 214 215 "mfence\n\t" \ 215 216 "mov %[m], %%eax\n\t" \ 217 + FEP "leave\n\t" \ 216 218 FEP "loop 1b\n\t" \ 217 219 FEP "mov %%edi, %%ecx\n\t" \ 218 220 FEP "xor %%eax, %%eax\n\t" \