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: 16+ 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 7:42 ` [PATCH 02/15] perf/x86/intel: Reset active_fixed_ctrl_val on CPU teardown Dapeng Mi
2026-09-28 7:42 ` [PATCH 03/15] perf/x86/intel: Reset active_pebs_data_cfg " Dapeng Mi
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 7:42 ` [PATCH 05/15] perf/x86/intel: Pass correct PEBS counter mask to no-drain update path Dapeng Mi
2026-09-28 7:43 ` [PATCH 06/15] perf/x86/intel: Limit PEBS counter iteration to valid array bounds Dapeng Mi
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 7:43 ` [PATCH 08/15] perf/x86/intel: Fix stale PEBS count without counter-group support Dapeng Mi
2026-09-28 7:43 ` Dapeng Mi [this message]
2026-09-28 7:43 ` [PATCH 10/15] perf/x86/intel: Refactor intel_pmu_drain_pebs_icl() Dapeng Mi
2026-09-28 7:43 ` [PATCH 11/15] perf/x86/intel: Fix invalid PEBS counts with counter-group support Dapeng Mi
2026-09-28 7:43 ` [PATCH 12/15] perf/x86/intel: Make ACR static_call update architectural Dapeng Mi
2026-09-28 7:43 ` [PATCH 13/15] perf/x86: Validate event type before topdown/mem-loads classification Dapeng Mi
2026-09-28 7:43 ` [PATCH 14/15] perf/core: Add event_caps dependency flags Dapeng Mi
2026-09-28 7:43 ` [PATCH 15/15] perf/x86/intel: Allow Topdown metrics with a non-leader slots event Dapeng Mi
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®