]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: selftests: Use data load to trigger LLC references/misses in Intel PMU
authorSean Christopherson <seanjc@google.com>
Wed, 27 Nov 2024 23:56:27 +0000 (15:56 -0800)
committerSean Christopherson <seanjc@google.com>
Wed, 8 Jan 2025 20:56:32 +0000 (12:56 -0800)
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>
tools/testing/selftests/kvm/x86/pmu_counters_test.c

index 0e305e43a93b0e2754785df0dfa58804545207f3..accd7ecd3e5f036f357f02fb3f14d9446c361a86 100644 (file)
@@ -17,7 +17,7 @@
  * Number of instructions in each loop. 1 CLFLUSH/CLFLUSHOPT/NOP, 1 MFENCE,
  * 1 LOOP.
  */
-#define NUM_INSNS_PER_LOOP             3
+#define NUM_INSNS_PER_LOOP             4
 
 /*
  * Number of "extra" instructions that will be counted, i.e. the number of
@@ -162,13 +162,14 @@ do {                                                                              \
                             "1:\n\t"                                           \
                             clflush "\n\t"                                     \
                             "mfence\n\t"                                       \
+                            "mov %[m], %%eax\n\t"                              \
                             FEP "loop 1b\n\t"                                  \
                             FEP "mov %%edi, %%ecx\n\t"                         \
                             FEP "xor %%eax, %%eax\n\t"                         \
                             FEP "xor %%edx, %%edx\n\t"                         \
                             "wrmsr\n\t"                                        \
                             :: "a"((uint32_t)_value), "d"(_value >> 32),       \
-                               "c"(_msr), "D"(_msr)                            \
+                               "c"(_msr), "D"(_msr), [m]"m"(kvm_pmu_version)   \
        );                                                                      \
 } while (0)
 
@@ -177,9 +178,9 @@ do {                                                                                \
        wrmsr(_pmc_msr, 0);                                                     \
                                                                                \
        if (this_cpu_has(X86_FEATURE_CLFLUSHOPT))                               \
-               GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt .", FEP);    \
+               GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt %[m]", FEP); \
        else if (this_cpu_has(X86_FEATURE_CLFLUSH))                             \
-               GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush .", FEP);       \
+               GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush  %[m]", FEP);   \
        else                                                                    \
                GUEST_MEASURE_EVENT(_ctrl_msr, _value, "nop", FEP);             \
                                                                                \