@@ -11,7 +11,7 @@
#include "libcflat.h"
#include <stdint.h>
-#define N 1000000
+#define N 1000000ULL
// These values match the number of instructions and branches in the
// assembly block in check_emulated_instr().
@@ -28,25 +28,25 @@ typedef struct {
struct pmu_event {
const char *name;
uint32_t unit_sel;
- int min;
- int max;
+ uint64_t min;
+ uint64_t max;
} intel_gp_events[] = {
- {"core cycles", 0x003c, 1*N, 50*N},
+ {"core cycles", 0x003c, 1*N, 500*N},
{"instructions", 0x00c0, 10*N, 10.2*N},
- {"ref cycles", 0x013c, 1*N, 30*N},
- {"llc references", 0x4f2e, 1, 2*N},
- {"llc misses", 0x412e, 1, 1*N},
- {"branches", 0x00c4, 1*N, 1.1*N},
- {"branch misses", 0x00c5, 0, 0.1*N},
+ {"ref cycles", 0x013c, 1*N, 300*N},
+ {"llc references", 0x4f2e, 0.1*N, 2*N},
+ {"llc misses", 0x412e, 0.1*N, 1*N},
+ {"branches", 0x00c4, 3*N, 3.3*N},
+ {"branch misses", 0x00c5, 0.1*N, 0.3*N},
}, amd_gp_events[] = {
- {"core cycles", 0x0076, 1*N, 50*N},
+ {"core cycles", 0x0076, 1*N, 500*N},
{"instructions", 0x00c0, 10*N, 10.2*N},
- {"branches", 0x00c2, 1*N, 1.1*N},
- {"branch misses", 0x00c3, 0, 0.1*N},
+ {"branches", 0x00c2, 3*N, 3.3*N},
+ {"branch misses", 0x00c3, 0.1*N, 0.3*N},
}, fixed_events[] = {
{"fixed 1", MSR_CORE_PERF_FIXED_CTR0, 10*N, 10.2*N},
- {"fixed 2", MSR_CORE_PERF_FIXED_CTR0 + 1, 1*N, 30*N},
- {"fixed 3", MSR_CORE_PERF_FIXED_CTR0 + 2, 0.1*N, 30*N}
+ {"fixed 2", MSR_CORE_PERF_FIXED_CTR0 + 1, 1*N, 500*N},
+ {"fixed 3", MSR_CORE_PERF_FIXED_CTR0 + 2, 0.1*N, 300*N},
};
char *buf;
@@ -56,10 +56,15 @@ static unsigned int gp_events_size;
static inline void loop(void)
{
- unsigned long tmp, tmp2, tmp3;
+ unsigned long tmp, tmp2, tmp3, tmp4;
- asm volatile("1: mov (%1), %2; add $64, %1; nop; nop; nop; nop; nop; nop; nop; loop 1b"
- : "=c"(tmp), "=r"(tmp2), "=r"(tmp3): "0"(N), "1"(buf));
+ asm volatile("1: dec %0; jz 3f; mov (%1), %2; add $64, %1; nop; \n"
+ " rdrand %3; and $7, %3; jnz 2f; clflush (%1); jmp 1b\n"
+ "2: nop; jmp 1b;"
+ "3: nop"
+ : "=c"(tmp), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
+ : "0"(N), "1"(buf)
+ : "memory");
}
@@ -202,7 +207,7 @@ static noinline void __measure(pmu_counter_t *evt, uint64_t count)
static bool verify_event(uint64_t count, struct pmu_event *e)
{
- // printf("%d <= %ld <= %d\n", e->min, count, e->max);
+ // printf("%ld <= %ld <= %ld\n", e->min, count, e->max);
return count >= e->min && count <= e->max;
}
Current loop() helper is a very simple adding loop function, it can't garantee that LLC misses and branch misses would be always triggered in the loop() running, especailly along with the larger and larger LLC size and better and better branch predictor in new CPUs. In this situation 0 LLC/branch misses count would be seen more and more easily just like what we see on Sapphire Rapids. It's ambiguous to take 0 as a valid result in tests since we can't confirm if the PMU function works correctly or it's just disabled. So this patch improves current loop() function and introduces random jump and clflush instructions to force to generate LLC and branch misses. Since random jump and clflush instructions are involved, all pre-defined valid count ranges are also update accordingly. Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com> --- x86/pmu.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-)