39 #define CFGWORD_EL0A64EN_MASK (0x20000)
40 #define CPMU_CORE_CYCLE 0x02
41 #define KPC_CLASS_FIXED_MASK (1 << 0)
42 #define KPC_CLASS_CONFIGURABLE_MASK (1 << 1)
43 #define COUNTERS_COUNT 10
44 #define CONFIG_COUNT 8
45 #define KPC_MASK (KPC_CLASS_CONFIGURABLE_MASK | KPC_CLASS_FIXED_MASK)
47static int (*kpc_get_thread_counters)(int,
unsigned int,
void *);
50static inline uint64_t kperf_cycles(
void)
52 uint64_t counters[COUNTERS_COUNT];
53 if (kpc_get_thread_counters(0, COUNTERS_COUNT, counters))
59static uint64_t perf_start(
void)
61 return kperf_cycles();
64static uint64_t perf_stop(uint64_t t)
66 return kperf_cycles() - t;
71 uint64_t
config[COUNTERS_COUNT] = { 0 };
77 = dlopen(
"/System/Library/PrivateFrameworks/kperf.framework/kperf", RTLD_LAZY);
79 fprintf(stderr,
"checkasm: Unable to load kperf: %s\n", dlerror());
83 int (*kpc_force_all_ctrs_set)(int) = dlsym(kperf,
"kpc_force_all_ctrs_set");
84 int (*kpc_set_counting)(uint32_t) = dlsym(kperf,
"kpc_set_counting");
85 int (*kpc_set_thread_counting)(uint32_t) = dlsym(kperf,
"kpc_set_thread_counting");
86 int (*kpc_set_config)(uint32_t,
void *) = dlsym(kperf,
"kpc_set_config");
87 uint32_t (*kpc_get_counter_count)(uint32_t) = dlsym(kperf,
"kpc_get_counter_count");
88 uint32_t (*kpc_get_config_count)(uint32_t) = dlsym(kperf,
"kpc_get_config_count");
89 kpc_get_thread_counters = dlsym(kperf,
"kpc_get_thread_counters");
91 if (!kpc_get_thread_counters) {
92 fprintf(stderr,
"checkasm: Unable to load kpc_get_thread_counters\n");
96 if (!kpc_get_counter_count || kpc_get_counter_count(
KPC_MASK) != COUNTERS_COUNT) {
97 fprintf(stderr,
"checkasm: Unexpected kpc_get_counter_count\n");
101 fprintf(stderr,
"checkasm: Unexpected kpc_get_config_count\n");
107 if (!kpc_set_config || kpc_set_config(
KPC_MASK, config)) {
108 fprintf(stderr,
"checkasm: The kperf API needs to be run as root\n");
111 if (!kpc_force_all_ctrs_set || kpc_force_all_ctrs_set(1)) {
112 fprintf(stderr,
"checkasm: kpc_force_all_ctrs_set failed\n");
115 if (!kpc_set_counting || kpc_set_counting(
KPC_MASK)) {
116 fprintf(stderr,
"checkasm: kpc_set_counting failed\n");
119 if (!kpc_set_counting || kpc_set_thread_counting(
KPC_MASK)) {
120 fprintf(stderr,
"checkasm: kpc_set_thread_counting failed\n");
126 perf->
start = perf_start;
127 perf->
stop = perf_stop;
128 perf->
name =
"macOS (kperf)";
129 perf->
unit =
"cycle";
static void kperf_init(void)
#define CFGWORD_EL0A64EN_MASK
uint64_t(* start)(void)
Start timing measurement.
const char * unit
Unit of measurement (e.g., "ns", "cycles")
const char * name
Name of the timing mechanism (e.g., "clock_gettime")
uint64_t(* stop)(uint64_t start_time)
Stop timing measurement.
int checkasm_perf_init_macos(CheckasmPerf *perf)
int checkasm_perf_validate_start(const CheckasmPerf *perf)