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

KVM: selftests: Use data load to trigger LLC references/misses in Intel PMU

In the PMU counters test, add a data load in the measured loop and target
the data with CLFLUSH{OPT} in order to (try to) guarantee the loop
generates LLC misses and fills. Per the SDM, some hardware prefetchers
are allowed to omit relevant PMU events, and Emerald Rapids (and possibly
Sapphire Rapids) appears to have gained an instruction prefetcher that
bypasses event counts. E.g. the test will consistently fail on EMR CPUs,
but then pass with seemingly benign changes to the code.

The event count includes speculation and cache line fills due to the
first-level cache hardware prefetcher, but may exclude cache line fills
due to other hardware-prefetchers.

Generate a data load as a last ditch effort to preserve the (minimal) test
coverage for LLC references and misses.

Cc: Maxim Levitsky <mlevitsk@redhat.com>
Link: https://lore.kernel.org/r/20241127235627.4049619-1-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

+5 -4
+5 -4
tools/testing/selftests/kvm/x86/pmu_counters_test.c
··· 17 17 * Number of instructions in each loop. 1 CLFLUSH/CLFLUSHOPT/NOP, 1 MFENCE, 18 18 * 1 LOOP. 19 19 */ 20 - #define NUM_INSNS_PER_LOOP 3 20 + #define NUM_INSNS_PER_LOOP 4 21 21 22 22 /* 23 23 * Number of "extra" instructions that will be counted, i.e. the number of ··· 162 162 "1:\n\t" \ 163 163 clflush "\n\t" \ 164 164 "mfence\n\t" \ 165 + "mov %[m], %%eax\n\t" \ 165 166 FEP "loop 1b\n\t" \ 166 167 FEP "mov %%edi, %%ecx\n\t" \ 167 168 FEP "xor %%eax, %%eax\n\t" \ 168 169 FEP "xor %%edx, %%edx\n\t" \ 169 170 "wrmsr\n\t" \ 170 171 :: "a"((uint32_t)_value), "d"(_value >> 32), \ 171 - "c"(_msr), "D"(_msr) \ 172 + "c"(_msr), "D"(_msr), [m]"m"(kvm_pmu_version) \ 172 173 ); \ 173 174 } while (0) 174 175 ··· 178 177 wrmsr(_pmc_msr, 0); \ 179 178 \ 180 179 if (this_cpu_has(X86_FEATURE_CLFLUSHOPT)) \ 181 - GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt .", FEP); \ 180 + GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt %[m]", FEP); \ 182 181 else if (this_cpu_has(X86_FEATURE_CLFLUSH)) \ 183 - GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush .", FEP); \ 182 + GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush %[m]", FEP); \ 184 183 else \ 185 184 GUEST_MEASURE_EVENT(_ctrl_msr, _value, "nop", FEP); \ 186 185 \