Skip to content

Commit 2cb2af7

Browse files
committed
x86/pmu: Test adaptive PEBS without any adaptive counters
If adaptive PEBS is supported, verify that only basic PEBS records are generated for counters without their ADAPTIVE flag set. Per the SDM, adaptive records are generated if and only if both the per-counter flag *and* the global enable(s) in MSR_PEBS_DATA_CFG are set. IA32_PERFEVTSELx.Adaptive_Record[34]: If this bit is set and IA32_PEBS_ENABLE.PEBS_EN_PMCx is set for the corresponding GP counter, an overflow of PMCx results in generation of an adaptive PEBS record with state information based on the selections made in MSR_PEBS_DATA_CFG. If this bit is not set, a basic record is generated. and IA32_FIXED_CTR_CTRL.FCx_Adaptive_Record: If this bit is set and IA32_PEBS_ENABLE.PEBS_EN_FIXEDx is set for the corresponding Fixed counter, an overflow of FixedCtrx results in generation of an adaptive PEBS record with state information based on the selections made in MSR_PEBS_DATA_CFG. If this bit is not set, a basic record is generated. Reviewed-by: Like Xu <likexu@tencent.com> Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Tested-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20240306230153.786365-4-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent fc17d52 commit 2cb2af7

File tree

1 file changed

+38
-36
lines changed

1 file changed

+38
-36
lines changed

x86/pmu_pebs.c

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ static u64 counter_start_values[] = {
8989
0xffffffffffff,
9090
};
9191

92-
static unsigned int get_adaptive_pebs_record_size(u64 pebs_data_cfg)
92+
static unsigned int get_pebs_record_size(u64 pebs_data_cfg, bool use_adaptive)
9393
{
9494
unsigned int sz = sizeof(struct pebs_basic);
9595

96-
if (!has_baseline)
96+
if (!use_adaptive)
9797
return sz;
9898

9999
if (pebs_data_cfg & PEBS_DATACFG_MEMINFO)
@@ -199,10 +199,10 @@ static void free_buffers(void)
199199
free_page(pebs_buffer);
200200
}
201201

202-
static void pebs_enable(u64 bitmask, u64 pebs_data_cfg)
202+
static void pebs_enable(u64 bitmask, u64 pebs_data_cfg, bool use_adaptive)
203203
{
204204
static struct debug_store *ds;
205-
u64 baseline_extra_ctrl = 0, fixed_ctr_ctrl = 0;
205+
u64 adaptive_ctrl = 0, fixed_ctr_ctrl = 0;
206206
unsigned int idx;
207207

208208
if (has_baseline)
@@ -212,26 +212,26 @@ static void pebs_enable(u64 bitmask, u64 pebs_data_cfg)
212212
ds->pebs_index = ds->pebs_buffer_base = (unsigned long)pebs_buffer;
213213
ds->pebs_absolute_maximum = (unsigned long)pebs_buffer + PAGE_SIZE;
214214
ds->pebs_interrupt_threshold = ds->pebs_buffer_base +
215-
get_adaptive_pebs_record_size(pebs_data_cfg);
215+
get_pebs_record_size(pebs_data_cfg, use_adaptive);
216216

217217
for (idx = 0; idx < pmu.nr_fixed_counters; idx++) {
218218
if (!(BIT_ULL(FIXED_CNT_INDEX + idx) & bitmask))
219219
continue;
220-
if (has_baseline)
221-
baseline_extra_ctrl = BIT(FIXED_CNT_INDEX + idx * 4);
220+
if (use_adaptive)
221+
adaptive_ctrl = BIT(FIXED_CNT_INDEX + idx * 4);
222222
wrmsr(MSR_PERF_FIXED_CTRx(idx), ctr_start_val);
223-
fixed_ctr_ctrl |= (0xbULL << (idx * 4) | baseline_extra_ctrl);
223+
fixed_ctr_ctrl |= (0xbULL << (idx * 4) | adaptive_ctrl);
224224
}
225225
if (fixed_ctr_ctrl)
226226
wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, fixed_ctr_ctrl);
227227

228228
for (idx = 0; idx < max_nr_gp_events; idx++) {
229229
if (!(BIT_ULL(idx) & bitmask))
230230
continue;
231-
if (has_baseline)
232-
baseline_extra_ctrl = ICL_EVENTSEL_ADAPTIVE;
231+
if (use_adaptive)
232+
adaptive_ctrl = ICL_EVENTSEL_ADAPTIVE;
233233
wrmsr(MSR_GP_EVENT_SELECTx(idx), EVNTSEL_EN | EVNTSEL_OS | EVNTSEL_USR |
234-
intel_arch_events[idx] | baseline_extra_ctrl);
234+
intel_arch_events[idx] | adaptive_ctrl);
235235
wrmsr(MSR_GP_COUNTERx(idx), ctr_start_val);
236236
}
237237

@@ -268,11 +268,11 @@ static void pebs_disable(unsigned int idx)
268268
wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
269269
}
270270

271-
static void check_pebs_records(u64 bitmask, u64 pebs_data_cfg)
271+
static void check_pebs_records(u64 bitmask, u64 pebs_data_cfg, bool use_adaptive)
272272
{
273273
struct pebs_basic *pebs_rec = (struct pebs_basic *)pebs_buffer;
274274
struct debug_store *ds = (struct debug_store *)ds_bufer;
275-
unsigned int pebs_record_size = get_adaptive_pebs_record_size(pebs_data_cfg);
275+
unsigned int pebs_record_size;
276276
unsigned int count = 0;
277277
bool expected, pebs_idx_match, pebs_size_match, data_cfg_match;
278278
void *cur_record;
@@ -293,12 +293,9 @@ static void check_pebs_records(u64 bitmask, u64 pebs_data_cfg)
293293
do {
294294
pebs_rec = (struct pebs_basic *)cur_record;
295295
pebs_record_size = pebs_rec->format_size >> RECORD_SIZE_OFFSET;
296-
pebs_idx_match =
297-
pebs_rec->applicable_counters & bitmask;
298-
pebs_size_match =
299-
pebs_record_size == get_adaptive_pebs_record_size(pebs_data_cfg);
300-
data_cfg_match =
301-
(pebs_rec->format_size & GENMASK_ULL(47, 0)) == pebs_data_cfg;
296+
pebs_idx_match = pebs_rec->applicable_counters & bitmask;
297+
pebs_size_match = pebs_record_size == get_pebs_record_size(pebs_data_cfg, use_adaptive);
298+
data_cfg_match = (pebs_rec->format_size & GENMASK_ULL(47, 0)) == pebs_data_cfg;
302299
expected = pebs_idx_match && pebs_size_match && data_cfg_match;
303300
report(expected,
304301
"PEBS record (written seq %d) is verified (including size, counters and cfg).", count);
@@ -311,56 +308,57 @@ static void check_pebs_records(u64 bitmask, u64 pebs_data_cfg)
311308
printf("FAIL: The applicable_counters (0x%lx) doesn't match with pmc_bitmask (0x%lx).\n",
312309
pebs_rec->applicable_counters, bitmask);
313310
if (!pebs_size_match)
314-
printf("FAIL: The pebs_record_size (%d) doesn't match with MSR_PEBS_DATA_CFG (%d).\n",
315-
pebs_record_size, get_adaptive_pebs_record_size(pebs_data_cfg));
311+
printf("FAIL: The pebs_record_size (%d) doesn't match with expected record size (%d).\n",
312+
pebs_record_size, get_pebs_record_size(pebs_data_cfg, use_adaptive));
316313
if (!data_cfg_match)
317-
printf("FAIL: The pebs_data_cfg (0x%lx) doesn't match with MSR_PEBS_DATA_CFG (0x%lx).\n",
318-
pebs_rec->format_size & 0xffffffffffff, pebs_data_cfg);
314+
printf("FAIL: The pebs_data_cfg (0x%lx) doesn't match with the effective MSR_PEBS_DATA_CFG (0x%lx).\n",
315+
pebs_rec->format_size & 0xffffffffffff, use_adaptive ? pebs_data_cfg : 0);
319316
}
320317
}
321318

322-
static void check_one_counter(enum pmc_type type,
323-
unsigned int idx, u64 pebs_data_cfg)
319+
static void check_one_counter(enum pmc_type type, unsigned int idx,
320+
u64 pebs_data_cfg, bool use_adaptive)
324321
{
325322
int pebs_bit = BIT_ULL(type == FIXED ? FIXED_CNT_INDEX + idx : idx);
326323

327324
report_prefix_pushf("%s counter %d (0x%lx)",
328325
type == FIXED ? "Extended Fixed" : "GP", idx, ctr_start_val);
329326
reset_pebs();
330-
pebs_enable(pebs_bit, pebs_data_cfg);
327+
pebs_enable(pebs_bit, pebs_data_cfg, use_adaptive);
331328
workload();
332329
pebs_disable(idx);
333-
check_pebs_records(pebs_bit, pebs_data_cfg);
330+
check_pebs_records(pebs_bit, pebs_data_cfg, use_adaptive);
334331
report_prefix_pop();
335332
}
336333

337334
/* more than one PEBS records will be generated. */
338-
static void check_multiple_counters(u64 bitmask, u64 pebs_data_cfg)
335+
static void check_multiple_counters(u64 bitmask, u64 pebs_data_cfg,
336+
bool use_adaptive)
339337
{
340338
reset_pebs();
341-
pebs_enable(bitmask, pebs_data_cfg);
339+
pebs_enable(bitmask, pebs_data_cfg, use_adaptive);
342340
workload2();
343341
pebs_disable(0);
344-
check_pebs_records(bitmask, pebs_data_cfg);
342+
check_pebs_records(bitmask, pebs_data_cfg, use_adaptive);
345343
}
346344

347-
static void check_pebs_counters(u64 pebs_data_cfg)
345+
static void check_pebs_counters(u64 pebs_data_cfg, bool use_adaptive)
348346
{
349347
unsigned int idx;
350348
u64 bitmask = 0;
351349

352350
for (idx = 0; has_baseline && idx < pmu.nr_fixed_counters; idx++)
353-
check_one_counter(FIXED, idx, pebs_data_cfg);
351+
check_one_counter(FIXED, idx, pebs_data_cfg, use_adaptive);
354352

355353
for (idx = 0; idx < max_nr_gp_events; idx++)
356-
check_one_counter(GP, idx, pebs_data_cfg);
354+
check_one_counter(GP, idx, pebs_data_cfg, use_adaptive);
357355

358356
for (idx = 0; has_baseline && idx < pmu.nr_fixed_counters; idx++)
359357
bitmask |= BIT_ULL(FIXED_CNT_INDEX + idx);
360358
for (idx = 0; idx < max_nr_gp_events; idx += 2)
361359
bitmask |= BIT_ULL(idx);
362360
report_prefix_pushf("Multiple (0x%lx)", bitmask);
363-
check_multiple_counters(bitmask, pebs_data_cfg);
361+
check_multiple_counters(bitmask, pebs_data_cfg, use_adaptive);
364362
report_prefix_pop();
365363
}
366364

@@ -408,7 +406,7 @@ int main(int ac, char **av)
408406

409407
for (i = 0; i < ARRAY_SIZE(counter_start_values); i++) {
410408
ctr_start_val = counter_start_values[i];
411-
check_pebs_counters(0);
409+
check_pebs_counters(0, false);
412410
if (!has_baseline)
413411
continue;
414412

@@ -419,7 +417,11 @@ int main(int ac, char **av)
419417
pebs_data_cfg |= ((MAX_NUM_LBR_ENTRY -1) << PEBS_DATACFG_LBR_SHIFT);
420418

421419
report_prefix_pushf("Adaptive (0x%lx)", pebs_data_cfg);
422-
check_pebs_counters(pebs_data_cfg);
420+
check_pebs_counters(pebs_data_cfg, true);
421+
report_prefix_pop();
422+
423+
report_prefix_pushf("Ignored Adaptive (0x%lx)", pebs_data_cfg);
424+
check_pebs_counters(pebs_data_cfg, false);
423425
report_prefix_pop();
424426
}
425427
}

0 commit comments

Comments
 (0)