Skip to content

Commit ae55e30

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
perf/x86/intel/ds: Simplify the PEBS records processing for adaptive PEBS
The current code may iterate all the PEBS records in the DS area several times. The first loop is to find all active events and calculate the available records for each event. Then iterate the whole buffer again and again to process available records until all active events are processed. The algorithm is inherited from the old generations. The old PEBS hardware does not deal well with the situation when events happen near each other. SW has to drop the error records. Multiple iterations are required. The hardware limit has been addressed on newer platforms with adaptive PEBS. A simple one-iteration algorithm is introduced. The samples are output by record order with the patch, rather than the event order. It doesn't impact the post-processing. The perf tool always sorts the records by time before presenting them to the end user. In an NMI, the last record has to be specially handled. Add a last[] variable to track the last unprocessed record of each event. Test: 11 PEBS events are used in the perf test. Only the basic information is collected. perf record -e instructions:up,...,instructions:up -c 2000003 benchmark The ftrace is used to record the duration of the intel_pmu_drain_pebs_icl(). The average duration reduced from 62.04us to 57.94us. A small improvement can be observed with the new algorithm. Also, the implementation becomes simpler and more straightforward. Suggested-by: Stephane Eranian <eranian@google.com> Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20241119135504.1463839-5-kan.liang@linux.intel.com
1 parent 3c00ed3 commit ae55e30

File tree

1 file changed

+29
-14
lines changed
  • arch/x86/events/intel

1 file changed

+29
-14
lines changed

arch/x86/events/intel/ds.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,8 +2425,12 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
24252425
static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_data *data)
24262426
{
24272427
short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
2428+
void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS];
24282429
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
24292430
struct debug_store *ds = cpuc->ds;
2431+
struct x86_perf_regs perf_regs;
2432+
struct pt_regs *regs = &perf_regs.regs;
2433+
struct pebs_basic *basic;
24302434
struct perf_event *event;
24312435
void *base, *at, *top;
24322436
int bit;
@@ -2448,30 +2452,41 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
24482452
return;
24492453
}
24502454

2451-
for (at = base; at < top; at += cpuc->pebs_record_size) {
2455+
if (!iregs)
2456+
iregs = &dummy_iregs;
2457+
2458+
/* Process all but the last event for each counter. */
2459+
for (at = base; at < top; at += basic->format_size) {
24522460
u64 pebs_status;
24532461

2454-
pebs_status = get_pebs_status(at) & cpuc->pebs_enabled;
2455-
pebs_status &= mask;
2462+
basic = at;
2463+
if (basic->format_size != cpuc->pebs_record_size)
2464+
continue;
2465+
2466+
pebs_status = basic->applicable_counters & cpuc->pebs_enabled & mask;
2467+
for_each_set_bit(bit, (unsigned long *)&pebs_status, X86_PMC_IDX_MAX) {
2468+
event = cpuc->events[bit];
24562469

2457-
for_each_set_bit(bit, (unsigned long *)&pebs_status, X86_PMC_IDX_MAX)
2458-
counts[bit]++;
2470+
if (WARN_ON_ONCE(!event) ||
2471+
WARN_ON_ONCE(!event->attr.precise_ip))
2472+
continue;
2473+
2474+
if (counts[bit]++) {
2475+
__intel_pmu_pebs_event(event, iregs, regs, data, last[bit],
2476+
setup_pebs_adaptive_sample_data);
2477+
}
2478+
last[bit] = at;
2479+
}
24592480
}
24602481

24612482
for_each_set_bit(bit, (unsigned long *)&mask, X86_PMC_IDX_MAX) {
2462-
if (counts[bit] == 0)
2483+
if (!counts[bit])
24632484
continue;
24642485

24652486
event = cpuc->events[bit];
2466-
if (WARN_ON_ONCE(!event))
2467-
continue;
2468-
2469-
if (WARN_ON_ONCE(!event->attr.precise_ip))
2470-
continue;
24712487

2472-
__intel_pmu_pebs_events(event, iregs, data, base,
2473-
top, bit, counts[bit],
2474-
setup_pebs_adaptive_sample_data);
2488+
__intel_pmu_pebs_last_event(event, iregs, regs, data, last[bit],
2489+
counts[bit], setup_pebs_adaptive_sample_data);
24752490
}
24762491
}
24772492

0 commit comments

Comments
 (0)