The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Puranjay Mohan <puranjay@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	James Clark <james.clark@linaro.org>,
	Usama Arif <usama.arif@linux.dev>, Will Deacon <will@kernel.org>,
	Anshuman Khandual <anshuman.khandual@arm.com>,
	Ravi Bangoria <ravi.bangoria@amd.com>,
	Thomas Gleixner <tglx@kernel.org>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	x86@kernel.org, linux-perf-users@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v6 3/3] perf/core: Clear the whole branch entry in perf_clear_branch_entry()
Date: Fri, 7 Aug 2026 12:29:32 +0200	[thread overview]
Message-ID: <20260807102932.GU776954@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20260806135224.3267890-4-puranjay@kernel.org>

On Thu, Aug 06, 2026 at 06:52:23AM -0700, Puranjay Mohan wrote:
> perf_clear_branch_entry_bitfields() clears the bitfields of struct
> perf_branch_entry one by one and leaves from/to alone, since callers
> overwrite those straight away. The list has to be kept in sync with the
> struct by hand and has already fallen behind: new_type and priv were
> added to perf_branch_entry and never added here.
> 
> Only BRBE writes those two, and neither is written for every record.
> brbe_set_perf_entry_type() leaves new_type alone for a branch type it
> does not recognise, and priv is not set for source-only records.
> arm_pmuv3.c allocates the per-CPU branch stack with kmalloc(), so such a
> record carries whatever the slot held: uninitialised kmalloc() data on
> the first pass over the buffer, the previous record's values after that.
> Both reach userspace through the branch stack. Nothing under
> arch/x86/events/ writes either field, so x86 is unaffected.
> 
> Clear the entry with a single struct assignment instead:
> 
> 	*br = (struct perf_branch_entry){ };
> 
> The bitfields add up to exactly 64 bits, so there is no padding, and
> every caller assigns from/to immediately afterwards, so zeroing those as
> well changes nothing. PERF_BR_SPEC_NA is 0, so dropping the explicit
> spec assignment leaves the behaviour unchanged. Nothing needs keeping in
> sync when a field is added.
> 
> The helper no longer touches only bitfields, so rename it to
> perf_clear_branch_entry().

Fair enough I suppose, but then why not write it like so?

---
--- a/arch/x86/events/amd/brs.c
+++ b/arch/x86/events/amd/brs.c
@@ -343,11 +343,7 @@ void amd_brs_drain(void)
 		if (!amd_brs_match_plm(event, from, to))
 			continue;
 
-		perf_clear_branch_entry_bitfields(br+nr);
-
-		br[nr].from = from;
-		br[nr].to   = to;
-
+		br[nr] = (struct perf_branch_entry){ from, to };
 		nr++;
 	}
 empty:
--- a/arch/x86/events/amd/lbr.c
+++ b/arch/x86/events/amd/lbr.c
@@ -184,12 +184,6 @@ void amd_pmu_lbr_read(void)
 		    entry.to.split.reserved)
 			continue;
 
-		perf_clear_branch_entry_bitfields(br + out);
-
-		br[out].from	= sign_ext_branch_ip(entry.from.split.ip);
-		br[out].to	= sign_ext_branch_ip(entry.to.split.ip);
-		br[out].mispred	= entry.from.split.mispredict;
-		br[out].predicted = !br[out].mispred;
 
 		/*
 		 * Set branch speculation information using the status of
@@ -208,7 +202,13 @@ void amd_pmu_lbr_read(void)
 		 * speculative and took the correct path
 		 */
 		idx = (entry.to.split.valid << 1) | entry.to.split.spec;
-		br[out].spec = lbr_spec_map[idx];
+		br[out] = (struct perf_branch_entry) {
+			.from      = sign_ext_branch_ip(entry.from.split.ip),
+			.to        = sign_ext_branch_ip(entry.to.split.ip),
+			.mispred   = entry.from.split.mispredict,
+			.predicted = !entry.from.split.mispredict,
+			.spec      = lbr_spec_map[idx],
+		};
 		out++;
 	}
 
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -756,10 +756,10 @@ void intel_pmu_lbr_read_32(struct cpu_hw
 
 		rdmsrq(x86_pmu.lbr_from + lbr_idx, msr_lastbranch.lbr);
 
-		perf_clear_branch_entry_bitfields(br);
-
-		br->from	= msr_lastbranch.from;
-		br->to		= msr_lastbranch.to;
+		*br = (struct perf_branch_entry){
+			.from = msr_lastbranch.from,
+			.to   = msr_lastbranch.to,
+		};
 		br++;
 	}
 	cpuc->lbr_stack.nr = i;
@@ -847,14 +847,15 @@ void intel_pmu_lbr_read_64(struct cpu_hw
 		if (abort && x86_pmu.lbr_double_abort && out > 0)
 			out--;
 
-		perf_clear_branch_entry_bitfields(br+out);
-		br[out].from	 = from;
-		br[out].to	 = to;
-		br[out].mispred	 = mis;
-		br[out].predicted = pred;
-		br[out].in_tx	 = in_tx;
-		br[out].abort	 = abort;
-		br[out].cycles	 = cycles;
+		br[out] = (struct perf_branch_entry) {
+			.from      = from,
+			.to        = to,
+			.mispred   = mis,
+			.predicted = pred,
+			.in_tx     = in_tx,
+			.abort     = abort,
+			.cycles    = cycles,
+		};
 		out++;
 	}
 	cpuc->lbr_stack.nr = out;
@@ -921,24 +922,25 @@ static void intel_pmu_store_lbr(struct c
 		to = rdlbr_to(i, lbr);
 		info = rdlbr_info(i, lbr);
 
-		perf_clear_branch_entry_bitfields(e);
-
-		e->from		= from;
-		e->to		= to;
-		e->mispred	= get_lbr_mispred(info);
-		e->predicted	= !e->mispred;
-		e->in_tx	= !!(info & LBR_INFO_IN_TX);
-		e->abort	= !!(info & LBR_INFO_ABORT);
-		e->cycles	= get_lbr_cycles(info);
-		e->type		= get_lbr_br_type(info);
-
-		/*
-		 * Leverage the reserved field of cpuc->lbr_entries[i] to
-		 * temporarily store the branch counters information.
-		 * The later code will decide what content can be disclosed
-		 * to the perf tool. Pleae see intel_pmu_lbr_counters_reorder().
-		 */
-		e->reserved	= (info >> LBR_INFO_BR_CNTR_OFFSET) & LBR_INFO_BR_CNTR_FULL_MASK;
+		*e = (struct perf_branch_entry){
+			.from      = from,
+			.to        = to,
+			.mispred   = get_lbr_mispred(info),
+			.predicted = !get_lbr_mispred(info),
+			.in_tx     = !!(info & LBR_INFO_IN_TX),
+			.abort     = !!(info & LBR_INFO_ABORT),
+			.cycles    = get_lbr_cycles(info),
+			.type      = get_lbr_br_type(info),
+
+			/*
+			 * Leverage the reserved field of cpuc->lbr_entries[i]
+			 * to temporarily store the branch counters
+			 * information. The later code will decide what
+			 * content can be disclosed to the perf tool. Pleae
+			 * see intel_pmu_lbr_counters_reorder().
+			 */
+			.reserved  = (info >> LBR_INFO_BR_CNTR_OFFSET) & LBR_INFO_BR_CNTR_FULL_MASK,
+		};
 	}
 
 	cpuc->lbr_stack.nr = i;
--- a/drivers/perf/arm_brbe.c
+++ b/drivers/perf/arm_brbe.c
@@ -604,7 +604,7 @@ static bool perf_entry_from_brbe_regset(
 		return false;
 
 	brbinf = bregs.brbinf;
-	perf_clear_branch_entry_bitfields(entry);
+	*entry = (struct perf_branch_entry) { };
 	if (brbe_record_is_complete(brbinf)) {
 		entry->from = bregs.brbsrc;
 		entry->to = bregs.brbtgt;
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1467,23 +1467,6 @@ static inline u32 perf_sample_data_size(
 	return size;
 }
 
-/*
- * Clear all bitfields in the perf_branch_entry.
- * The to and from fields are not cleared because they are
- * systematically modified by caller.
- */
-static inline void perf_clear_branch_entry_bitfields(struct perf_branch_entry *br)
-{
-	br->mispred	= 0;
-	br->predicted	= 0;
-	br->in_tx	= 0;
-	br->abort	= 0;
-	br->cycles	= 0;
-	br->type	= 0;
-	br->spec	= PERF_BR_SPEC_NA;
-	br->reserved	= 0;
-}
-
 extern void perf_output_sample(struct perf_output_handle *handle,
 			       struct perf_event_header *header,
 			       struct perf_sample_data *data,

  reply	other threads:[~2026-08-07 10:29 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06 13:52 [PATCH v6 0/3] perf/core: sched_task() dispatch and branch entry fixes Puranjay Mohan
2026-08-06 13:52 ` [PATCH v6 1/3] perf/core: Fix NULL pmu_ctx passed to pmu->sched_task() Puranjay Mohan
2026-08-07  9:39   ` Peter Zijlstra
2026-08-06 13:52 ` [PATCH v6 2/3] perf/core: Run sched_task() for PMUs with only CPU-wide events Puranjay Mohan
2026-08-07 10:08   ` Peter Zijlstra
2026-08-06 13:52 ` [PATCH v6 3/3] perf/core: Clear the whole branch entry in perf_clear_branch_entry() Puranjay Mohan
2026-08-07 10:29   ` Peter Zijlstra [this message]
2026-08-07  8:30 ` [PATCH v6 0/3] perf/core: sched_task() dispatch and branch entry fixes James Clark

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=20260807102932.GU776954@noisy.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=anshuman.khandual@arm.com \
    --cc=bp@alien8.de \
    --cc=bpf@vger.kernel.org \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=puranjay@kernel.org \
    --cc=ravi.bangoria@amd.com \
    --cc=tglx@kernel.org \
    --cc=usama.arif@linux.dev \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /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