Linux Perf Users
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Atish Patra" <atish.patra@linux.dev>
Cc: robh@kernel.org, linux-perf-users@vger.kernel.org,
	devicetree@vger.kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v8 16/22] RISC-V: perf: Use config2/vendor table for event to counter mapping
Date: Wed, 01 Jul 2026 09:35:00 +0000	[thread overview]
Message-ID: <20260701093500.6A6F01F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260701-counter_delegation-v8-16-7909f863a645@meta.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Legacy perf tools fail to profile hardware cycle and instruction events on platforms with counter delegation, rendering fixed counters and vendor mappings unusable.
- [High] Standard hardware events (PERF_TYPE_HARDWARE) fail unconditionally on platforms supporting counter delegation unless a vendor-specific event table is present.
- [Medium] The 64-bit `event->attr.config2` mask is truncated to a 32-bit integer `temp_mask`, causing invalid user constraints to be silently bypassed.
--

commit 25bb8be42a29d054e5ce833c3ed3ff8935990ee1
Author: Atish Patra <atishp@rivosinc.com>

RISC-V: perf: Use config2/vendor table for event to counter mapping

This commit allows platform vendors to define custom mappings between
performance events and hardware counters via the config2 attribute. Legacy
events can either map to ISA-defined fixed counters or fall back to
alternate programmable counters as specified by the platform driver.

> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index fcf8fbb6fd864..19d9e47504247 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
[ ... ]
> @@ -1501,24 +1503,85 @@ static int rvpmu_deleg_find_ctrs(void)
>  	return num_hw_ctr;
>  }
>  
> +/*
> + * The json file must correctly specify counter 0 or counter 2 is available
> + * in the counter lists for cycle/instret events. Otherwise, the drivers have
> + * no way to figure out if a fixed counter must be used and pick a programmable
> + * counter if available.
> + */
>  static int get_deleg_fixed_hw_idx(struct cpu_hw_events *cpuc, struct perf_event *event)
>  {
> -	return -EINVAL;
> +	bool guest_events = event->attr.config1 & RISCV_PMU_CONFIG1_GUEST_EVENTS;
> +	int idx;
> +
> +	/* event_base is 0 on the delegation path; match via the original perf attrs. */
> +	if (guest_events) {
> +		if (event->attr.type != PERF_TYPE_HARDWARE)
> +			return -EINVAL;
> +		if (event->attr.config == PERF_COUNT_HW_CPU_CYCLES)
> +			idx = 0; /* CY counter */
> +		else if (event->attr.config == PERF_COUNT_HW_INSTRUCTIONS)
> +			idx = 2; /* IR counter */
> +		else
> +			return -EINVAL;
> +	} else if (event->attr.config2 & RISCV_PMU_CYCLE_FIXED_CTR_MASK) {
> +		idx = 0; /* CY counter */
> +	} else if (event->attr.config2 & RISCV_PMU_INSTRUCTION_FIXED_CTR_MASK) {
> +		idx = 2; /* IR counter */
> +	} else {
> +		return -EINVAL;
> +	}

[Severity: High]
Does this break legacy perf tools (like 'perf stat -e cycles') on platforms
with counter delegation?

Older tools don't set config2, so legacy events without config2 set are
explicitly rejected here. The code then falls back to
get_deleg_next_hpm_hw_idx(), which excludes fixed counters:

    hw_ctr_mask = cmask & (~0x7) & ~(cpuc->used_hw_ctrs[0]);

If the vendor table mapped the event to a fixed counter, the mask evaluation
will result in 0, causing the allocation to fail with -EINVAL.

> +
> +	/* Take the fixed counter only if delegated and free, else fall back. */
> +	if (!(cmask & BIT(idx)) || test_bit(idx, cpuc->used_hw_ctrs))
> +		return -EINVAL;
> +
> +	return idx;
>  }
>  
>  static int get_deleg_next_hpm_hw_idx(struct cpu_hw_events *cpuc, struct perf_event *event)
>  {
> -	unsigned long hw_ctr_mask = 0;
> +	u32 hw_ctr_mask = 0, temp_mask = 0;
> +	u32 type = event->attr.type;
> +	u64 config = event->attr.config;
> +	int ret;
>  
> -	/*
> -	 * TODO: Treat every hpmcounter can monitor every event for now.
> -	 * The event to counter mapping should come from the json file.
> -	 * The mapping should also tell if sampling is supported or not.
> -	 */
> +	/* Select only available hpmcounters */
> +	hw_ctr_mask = cmask & (~0x7) & ~(cpuc->used_hw_ctrs[0]);
> +
> +	switch (type) {
> +	case PERF_TYPE_HARDWARE:
> +		temp_mask = current_pmu_hw_event_map[config].counter_mask;

[Severity: High]
Do standard hardware events (PERF_TYPE_HARDWARE) fail unconditionally on
platforms supporting counter delegation if a vendor-specific event table is
missing?

In rvpmu_event_map(), it appears that all non-firmware events are intercepted
when counter delegation is available:

    if (riscv_pmu_cdeleg_available() && !pmu_sbi_is_fw_event(event))
        return rvpmu_cdeleg_event_map(event, econfig);

Then in rvpmu_cdeleg_event_map(), it hard-fails standard hardware events if
the vendor table is missing:

    case PERF_TYPE_HARDWARE:
        if (config >= PERF_COUNT_HW_MAX)
            return -EINVAL;
        if (!current_pmu_hw_event_map)
            return -ENOENT;

Without a fallback to the SBI PMU, does this completely break legacy hardware
events on new platforms that don't yet have a vendor-specific driver table?

> +		break;
> +	case PERF_TYPE_HW_CACHE:
> +		ret = cdeleg_pmu_event_find_cache(config, NULL, &temp_mask);
> +		if (ret)
> +			return ret;
> +		break;
> +	case PERF_TYPE_RAW:
> +		/*
> +		 * Mask off the counters that can't monitor this event (specified via json)
> +		 * The counter mask for this event is set in config2 via the property 'Counter'
> +		 * in the json file or manual configuration of config2. If the config2 is not set,
> +		 * it is assumed all the available hpmcounters can monitor this event.
> +		 * Note: This assumption may fail for virtualization use case where they hypervisor
> +		 * (e.g. KVM) virtualizes the counter. Any event to counter mapping provided by the
> +		 * guest is meaningless from a hypervisor perspective. Thus, the hypervisor doesn't
> +		 * set config2 when creating kernel counter and relies default host mapping.
> +		 */
> +		if (event->attr.config2)
> +			temp_mask = event->attr.config2;

[Severity: Medium]
Will this silently bypass user-provided counter constraints if only bits above
31 are set in config2?

event->attr.config2 is a u64, but temp_mask is defined as a u32. When config2
is assigned to temp_mask, the upper 32 bits are truncated. If the resulting
temp_mask evaluates to 0, it skips the constraint application entirely:

    if (temp_mask)
        hw_ctr_mask &= temp_mask;

Would this result in the kernel incorrectly programming the event on any
available programmable counter instead of rejecting the invalid constraint?

> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (temp_mask)
> +		hw_ctr_mask &= temp_mask;
> +
> +	if (!hw_ctr_mask)
> +		return -EINVAL;
>  
> -	/* Select only hpmcounters */
> -	hw_ctr_mask = cmask & (~0x7);
> -	hw_ctr_mask &= ~(cpuc->used_hw_ctrs[0]);
>  	return __ffs(hw_ctr_mask);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260701-counter_delegation-v8-0-7909f863a645@meta.com?part=16

  reply	other threads:[~2026-07-01  9:35 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-01  8:46 [PATCH v8 00/22] Add Counter delegation ISA extension support Atish Patra
2026-07-01  8:46 ` [PATCH v8 01/22] RISC-V: perf: fix resource cleanup on driver probe failure Atish Patra
2026-07-01  9:11   ` sashiko-bot
2026-07-01  8:46 ` [PATCH v8 02/22] RISC-V: Add Sxcsrind ISA extension CSR definitions Atish Patra
2026-07-01  8:46 ` [PATCH v8 03/22] RISC-V: Add Sxcsrind ISA extension definition and parsing Atish Patra
2026-07-01  8:46 ` [PATCH v8 04/22] dt-bindings: riscv: add Sxcsrind ISA extension description Atish Patra
2026-07-01  8:46 ` [PATCH v8 05/22] RISC-V: Define indirect CSR access helpers Atish Patra
2026-07-01  8:46 ` [PATCH v8 06/22] RISC-V: Add Smcntrpmf extension parsing Atish Patra
2026-07-01  8:46 ` [PATCH v8 07/22] dt-bindings: riscv: add Smcntrpmf ISA extension description Atish Patra
2026-07-01  8:46 ` [PATCH v8 08/22] RISC-V: Add Sscfg extension CSR definition Atish Patra
2026-07-01  8:46 ` [PATCH v8 09/22] RISC-V: Add Ssccfg/Smcdeleg ISA extension definition and parsing Atish Patra
2026-07-01  9:11   ` sashiko-bot
2026-07-01  8:46 ` [PATCH v8 10/22] dt-bindings: riscv: add Counter delegation ISA extensions description Atish Patra
2026-07-01  8:46 ` [PATCH v8 11/22] RISC-V: perf: Restructure the SBI PMU code Atish Patra
2026-07-01  8:47 ` [PATCH v8 12/22] RISC-V: perf: Modify the counter discovery mechanism Atish Patra
2026-07-01  9:20   ` sashiko-bot
2026-07-01  8:47 ` [PATCH v8 13/22] RISC-V: perf: Add a mechanism to defined legacy event encoding Atish Patra
2026-07-01  9:19   ` sashiko-bot
2026-07-01  8:47 ` [PATCH v8 14/22] RISC-V: perf: Implement supervisor counter delegation support Atish Patra
2026-07-01  9:27   ` sashiko-bot
2026-07-01  8:47 ` [PATCH v8 15/22] RISC-V: perf: Skip PMU SBI extension when not implemented Atish Patra
2026-07-01  9:26   ` sashiko-bot
2026-07-01  8:47 ` [PATCH v8 16/22] RISC-V: perf: Use config2/vendor table for event to counter mapping Atish Patra
2026-07-01  9:35   ` sashiko-bot [this message]
2026-07-01  8:47 ` [PATCH v8 17/22] RISC-V: perf: Add legacy event encodings via sysfs Atish Patra
2026-07-01  8:47 ` [PATCH v8 18/22] RISC-V: perf: Add Qemu virt machine events Atish Patra
2026-07-01  8:47 ` [PATCH v8 19/22] tools/perf: Support event code for arch standard events Atish Patra
2026-07-01 17:44   ` Ian Rogers
2026-07-01  8:47 ` [PATCH v8 20/22] tools/perf: Add RISC-V CounterIDMask event field Atish Patra
2026-07-01 17:44   ` Ian Rogers
2026-07-01  8:47 ` [PATCH v8 21/22] TEST(do-not-upstream): fake qemu-virt PMU events for cdeleg counter-mask testing Atish Patra
2026-07-01  9:38   ` sashiko-bot
2026-07-01  8:47 ` [PATCH v8 22/22] TEST(do-not-upstream): fake qemu vendor JSON + mapfile entry for CounterIDMask path Atish Patra
2026-07-01  9:34   ` sashiko-bot

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=20260701093500.6A6F01F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=atish.patra@linux.dev \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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