From: Dapeng Mi <dapeng1.mi@linux.intel.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Andi Kleen <ak@linux.intel.com>,
Eranian Stephane <eranian@google.com>
Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
Dapeng Mi <dapeng1.mi@intel.com>, Zide Chen <zide.chen@intel.com>,
Falcon Thomas <thomas.falcon@intel.com>,
Xudong Hao <xudong.hao@intel.com>,
Dapeng Mi <dapeng1.mi@linux.intel.com>
Subject: [PATCH 09/15] perf/x86/intel: Refactor intel_pmu_drain_arch_pebs()
Date: Mon, 28 Sep 2026 15:43:03 +0800 [thread overview]
Message-ID: <20260928074309.898043-10-dapeng1.mi@linux.intel.com> (raw)
In-Reply-To: <20260928074309.898043-1-dapeng1.mi@linux.intel.com>
intel_pmu_drain_arch_pebs() and intel_pmu_drain_pebs_icl() use the same
high-level PEBS drain flow. To reduce duplication, extract the shared
logic into a common helper, intel_pmu_handle_pebs_records(), and have
the arch-PEBS path use it.
Add small helper wrappers, including get_pebs_cntr_mask(),
get_pebs_cntr_status(), and find_next_pebs_record(), to hide
record-layout differences between ICL adaptive PEBS and arch PEBS.
This patch refactors only intel_pmu_drain_arch_pebs(); converting
intel_pmu_drain_pebs_icl() to the same helper is done in the next patch.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
---
arch/x86/events/intel/ds.c | 163 ++++++++++++++++++++++---------------
1 file changed, 96 insertions(+), 67 deletions(-)
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 1a32f4168a84..961f7138387a 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -3267,7 +3267,6 @@ __intel_pmu_handle_last_pebs_record(struct pt_regs *iregs,
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
struct perf_event *event;
- bool handled = false;
int bit;
for_each_set_bit(bit, (unsigned long *)&mask,
@@ -3275,15 +3274,101 @@ __intel_pmu_handle_last_pebs_record(struct pt_regs *iregs,
if (!counts[bit])
continue;
- handled = true;
event = cpuc->events[bit];
__intel_pmu_pebs_last_event(event, iregs, regs, data, last[bit],
counts[bit], corrupted, setup_sample);
}
+}
+
+static inline u64 get_pebs_cntr_mask(struct cpu_hw_events *cpuc)
+{
+ return hybrid(cpuc->pmu, arch_pebs_cap).counters &
+ cpuc->pebs_enabled;
+}
+
+static inline u64 get_pebs_cntr_status(void *at)
+{
+ struct arch_pebs_basic *basic;
+
+ basic = at + sizeof(struct arch_pebs_header);
+ return basic->applicable_counters;
+}
+
+static void *find_next_pebs_record(void *at, void *top)
+{
+ struct arch_pebs_header *header;
+
+ header = at;
+ if (WARN_ON_ONCE(!header->size))
+ return NULL;
+
+ /* 1st fragment or single record must have basic group */
+ if (WARN_ON_ONCE(!header->basic))
+ return NULL;
+
+ /* Skip non-last fragments */
+ while (arch_pebs_record_continued(header)) {
+ if (!header->size)
+ return NULL;
+ at += header->size;
+ if (WARN_ON_ONCE(at >= top))
+ return NULL;
+ header = at;
+ }
+
+ /* Skip last fragment or the single record */
+ at += header->size;
+ if (WARN_ON_ONCE(at > top))
+ return NULL;
+
+ return at;
+}
+
+static __always_inline int
+intel_pmu_handle_pebs_records(struct pt_regs *iregs,
+ struct perf_sample_data *data,
+ void *base, void *top,
+ setup_fn setup_sample)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+ void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS];
+ struct x86_perf_regs *perf_regs = this_cpu_ptr(&x86_pebs_regs);
+ struct pt_regs *regs = &perf_regs->regs;
+ u64 mask = get_pebs_cntr_mask(cpuc);
+ u64 events_bitmap = 0;
+ bool corrupted = false;
+ void *at, *next;
+
+ if (!iregs)
+ iregs = &dummy_iregs;
+
+ /* Process all but the last event for each counter. */
+ for (at = base; at < top;) {
+ u64 pebs_status;
+
+ next = find_next_pebs_record(at, top);
+ if (!next) {
+ corrupted = true;
+ break;
+ }
+
+ pebs_status = mask & get_pebs_cntr_status(at);
+ events_bitmap |= pebs_status;
+ __intel_pmu_handle_pebs_record(iregs, regs, data, at,
+ pebs_status, counts, last,
+ setup_sample);
+ at = next;
+ }
+
+ __intel_pmu_handle_last_pebs_record(iregs, regs, data, mask,
+ counts, last, corrupted,
+ setup_sample);
- /* All records are corrupted, reset sampling period. */
- if (!handled)
+ if (!events_bitmap)
intel_pmu_pebs_event_update_no_drain(cpuc, mask);
+
+ return hweight64(events_bitmap);
}
static int intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_data *data)
@@ -3342,22 +3427,19 @@ static int intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_da
__intel_pmu_handle_last_pebs_record(iregs, regs, data, mask, counts, last,
corrupted, setup_pebs_adaptive_sample_data);
+ if (!events_bitmap)
+ intel_pmu_pebs_event_update_no_drain(cpuc, mask);
+
return hweight64(events_bitmap);
}
static int intel_pmu_drain_arch_pebs(struct pt_regs *iregs,
struct perf_sample_data *data)
{
- short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
- void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS];
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ u64 mask = get_pebs_cntr_mask(cpuc);
union arch_pebs_index index;
- struct x86_perf_regs *perf_regs = this_cpu_ptr(&x86_pebs_regs);
- struct pt_regs *regs = &perf_regs->regs;
- void *base, *at, *top;
- u64 events_bitmap = 0;
- bool corrupted = false;
- u64 mask;
+ void *base, *top;
rdmsrq(MSR_IA32_PEBS_INDEX, index.whole);
@@ -3379,61 +3461,8 @@ static int intel_pmu_drain_arch_pebs(struct pt_regs *iregs,
index.thresh = ARCH_PEBS_THRESH_SINGLE;
wrmsrq(MSR_IA32_PEBS_INDEX, index.whole);
- if (!iregs)
- iregs = &dummy_iregs;
-
- /* Process all but the last event for each counter. */
- for (at = base; at < top;) {
- struct arch_pebs_header *header;
- struct arch_pebs_basic *basic;
- u64 pebs_status;
-
- header = at;
-
- if (WARN_ON_ONCE(!header->size)) {
- corrupted = true;
- goto done;
- }
-
- /* 1st fragment or single record must have basic group */
- if (!header->basic) {
- at += header->size;
- continue;
- }
-
- basic = at + sizeof(struct arch_pebs_header);
- pebs_status = mask & basic->applicable_counters;
- events_bitmap |= pebs_status;
- __intel_pmu_handle_pebs_record(iregs, regs, data, at,
- pebs_status, counts, last,
- setup_arch_pebs_sample_data);
-
- /* Skip non-last fragments */
- while (arch_pebs_record_continued(header)) {
- if (!header->size)
- break;
- at += header->size;
- if (WARN_ON_ONCE(at >= top)) {
- corrupted = true;
- goto done;
- }
- header = at;
- }
-
- /* Skip last fragment or the single record */
- at += header->size;
- if (WARN_ON_ONCE(at > top)) {
- corrupted = true;
- goto done;
- }
- }
-
-done:
- __intel_pmu_handle_last_pebs_record(iregs, regs, data, mask,
- counts, last, corrupted,
- setup_arch_pebs_sample_data);
-
- return hweight64(events_bitmap);
+ return intel_pmu_handle_pebs_records(iregs, data, base, top,
+ setup_arch_pebs_sample_data);
}
static void __init intel_arch_pebs_init(void)
--
2.34.1
next prev parent reply other threads:[~2026-09-28 7:51 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 7:42 [PATCH 00/15] perf/x86: Fix sampling bugs and relax slots-event grouping Dapeng Mi
2026-09-28 7:42 ` [PATCH 01/15] perf/x86/intel: Guard leader sibling walk on nr_siblings Dapeng Mi
2026-09-28 8:00 ` sashiko-bot
2026-09-28 7:42 ` [PATCH 02/15] perf/x86/intel: Reset active_fixed_ctrl_val on CPU teardown Dapeng Mi
2026-09-28 8:02 ` sashiko-bot
2026-09-28 7:42 ` [PATCH 03/15] perf/x86/intel: Reset active_pebs_data_cfg " Dapeng Mi
2026-09-28 8:07 ` sashiko-bot
2026-09-28 7:42 ` [PATCH 04/15] perf/x86/intel: Reset cached acr_cfg_b[] and cfg_c_val[] " Dapeng Mi
2026-09-28 8:01 ` sashiko-bot
2026-09-28 7:42 ` [PATCH 05/15] perf/x86/intel: Pass correct PEBS counter mask to no-drain update path Dapeng Mi
2026-09-28 7:58 ` sashiko-bot
2026-09-28 7:43 ` [PATCH 06/15] perf/x86/intel: Limit PEBS counter iteration to valid array bounds Dapeng Mi
2026-09-28 8:00 ` sashiko-bot
2026-09-28 7:43 ` [PATCH 07/15] perf/x86/intel: Reject SAMPLE_READ for no-counter-snapshot ACR events Dapeng Mi
2026-09-28 8:04 ` sashiko-bot
2026-09-29 6:08 ` Mi, Dapeng
2026-09-29 19:02 ` Falcon, Thomas
2026-09-30 1:12 ` Mi, Dapeng
2026-09-28 7:43 ` [PATCH 08/15] perf/x86/intel: Fix stale PEBS count without counter-group support Dapeng Mi
2026-09-28 8:02 ` sashiko-bot
2026-09-28 7:43 ` Dapeng Mi [this message]
2026-09-28 7:57 ` [PATCH 09/15] perf/x86/intel: Refactor intel_pmu_drain_arch_pebs() sashiko-bot
2026-09-28 7:43 ` [PATCH 10/15] perf/x86/intel: Refactor intel_pmu_drain_pebs_icl() Dapeng Mi
2026-09-28 7:59 ` sashiko-bot
2026-09-28 7:43 ` [PATCH 11/15] perf/x86/intel: Fix invalid PEBS counts with counter-group support Dapeng Mi
2026-09-28 8:00 ` sashiko-bot
2026-09-28 7:43 ` [PATCH 12/15] perf/x86/intel: Make ACR static_call update architectural Dapeng Mi
2026-09-28 8:02 ` sashiko-bot
2026-09-28 7:43 ` [PATCH 13/15] perf/x86: Validate event type before topdown/mem-loads classification Dapeng Mi
2026-09-28 8:01 ` sashiko-bot
2026-09-28 7:43 ` [PATCH 14/15] perf/core: Add event_caps dependency flags Dapeng Mi
2026-09-28 8:05 ` sashiko-bot
2026-09-29 6:34 ` Mi, Dapeng
2026-09-28 7:43 ` [PATCH 15/15] perf/x86/intel: Allow Topdown metrics with a non-leader slots event Dapeng Mi
2026-09-28 8:12 ` sashiko-bot
2026-09-29 7:04 ` Mi, Dapeng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928074309.898043-10-dapeng1.mi@linux.intel.com \
--to=dapeng1.mi@linux.intel.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=dapeng1.mi@intel.com \
--cc=eranian@google.com \
--cc=irogers@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=thomas.falcon@intel.com \
--cc=xudong.hao@intel.com \
--cc=zide.chen@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.