The current SBI DBTR extension implementation accesses tdata2 and tdata3
without first checking whether either register is implemented on the
underlying hart. This produces an illegal instruction exception on
otherwise spec-compliant cores that legitimately omit one or both
registers.
Per the RISC-V Debug Specification, Chapter 5 (Sdtrig ISA Extension)
and Section 5.7 (Trigger Module Registers):
Section 5 (Sdtrig introduction):
"If Sdtrig is implemented, the Trigger Module must support at least
one trigger. Accessing trigger CSRs that are not used by any of the
implemented triggers must result in an illegal instruction
exception. M-Mode and Debug Mode accesses to trigger CSRs that are
used by any of the implemented triggers must succeed, regardless of
the current type of the currently selected trigger."
Section 5.7 (Trigger Module Registers):
"Attempts to access an unimplemented Trigger Module Register raise
an illegal instruction exception."
Per-register optionality is also explicit:
Section 5.7.3 (Trigger Data 2, at 0x7a2):
"Trigger-specific data. It is optional if no implemented triggers
use it."
Section 5.7.4 (Trigger Data 3, at 0x7a3):
"Trigger-specific data. It is optional if no implemented triggers
use it."
Section 5.7.17 (Trigger Extra (RV32), at 0x7a3), which also applies
via textra64 on RV64:
"All functionality in this register is optional. Any number of
upper bits of mhvalue and svalue may be tied to 0. mhselect and
sselect may only support 0 (ignore)."
Unconditionally accessing tdata2/tdata3 in the install/update/read/
uninstall paths causes SBI calls to fail with an illegal instruction
exception on hardware that does not implement one or both CSRs, even
if the supervisor-supplied trigger configuration does not require the
missing CSR(s).
This patch:
1. Introduces tdata_read_safe() / tdata_write_safe() helpers that
wrap csr_read_allowed / csr_write_allowed so that an illegal-
instruction trap raised by an unimplemented CSR is caught locally
rather than propagated. On the read path, a trapped read yields
zero; on the write path, the trap is silently absorbed (writes to
an unimplemented CSR are no-ops by definition). Every tdata2/tdata3
read and write in the install/update/read/uninstall paths is
converted to these helpers.
2. On the install and update paths, rejects requests that program
a non-zero trig_tdata2 or trig_tdata3 into an unimplemented CSR
with SBI_ERR_NOT_SUPPORTED, matching the SBI spec
wording in sections 19.4 / 19.5:
"One of the trigger configuration can't be programmed due to
unimplemented optional bits in tdata1, tdata2, or tdata3
CSRs."
Implementation status is probed once per call via the
tdata_implemented() helper. This only catches the "whole CSR
unimplemented" case; tied-off WARL bits inside an otherwise-
implemented CSR are not caught here and would require programming
the trigger and reading the value back for comparison, which can
be addressed separately.
3. Enable tdata3 configuration in the debug trigger install path.
References:
- RISC-V Debug Specification, Chapter 5 (Sdtrig), sections 5, 5.7,
5.7.3, 5.7.4, 5.7.17.
- RISC-V SBI Specification v3.0, Chapter 19 (Debug Triggers
Extension), sections 19.4, 19.5.
Fixes: 97f234f15c ("lib: sbi: Introduce the SBI debug triggers extension support")
Suggested-by: Nicholas Piggin <npiggin@gmail.com>
Suggested-by: Himanshu Chauhan <himanshu.chauhan@oss.qualcomm.com>
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-By: Himanshu Chauhan <himanshu.chauhan@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260616170118.3515676-1-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
sbi_pmu_ctr_cfg_match() only acts on SBI_PMU_CFG_FLAG_CLEAR_VALUE and
SBI_PMU_CFG_FLAG_AUTO_START when the event type is SBI_PMU_EVENT_TYPE_HW.
However, pmu_ctr_find_hw() allocates a hardware counter from the same
hw_event_map for SBI_PMU_EVENT_TYPE_HW_CACHE, SBI_PMU_EVENT_TYPE_HW_RAW,
and SBI_PMU_EVENT_TYPE_HW_RAW_V2 as well, and the start/clear helpers
(pmu_ctr_start_hw, pmu_ctr_write_hw) operate on the counter index alone
and are agnostic to the event type. As a result, when a supervisor
configures a HW_CACHE/HW_RAW/HW_RAW_V2 event with these flags, the
counter is programmed and recorded in active_events[] but is never
cleared or started, requiring an extra SBI call to make it count.
Extend the check to cover all hardware-counter event types so that
the configuration flags take effect for HW_CACHE and raw events too.
Deliberately avoiding using "not FW" logic to be explicit about
HW-backed events only.
Fixes: 13d40f21 ("lib: sbi: Add PMU support")
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260522144608.3433470-1-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Add rpmi_event_notification_state enum with disable, enable, and return
current state IDs. Also, add req_state field to rpmi_enable_notification_req
and current_state field to rpmi_enable_notification_resp for RPMI specification
compliance.
Add notification event ID enum and data structures for RPMI Performance
service group events: power change, limit change, and level change.
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260608125257.3220114-4-anup.patel@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Add bit-field defines for the RPMI performance domain attributes flags
and fast-channel attributes flags as specified in the RPMI specification.
These are needed by platform implementations that provide RPMI
performance services (e.g. DVFS controllers).
Also add the missing db_write_value field to
rpmi_perf_get_fast_chn_attr_resp to match the RPMI spec layout.
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260328054347.3706029-5-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
The reg_stride field represents the address stride in bytes between
consecutive registers. The Linux kernel regmap framework validates
register accesses using IS_ALIGNED(reg, map->reg_stride) as an address
alignment check (drivers/base/regmap/regmap.c). The Linux kernel syscon
driver (drivers/mfd/syscon.c) sets reg_stride directly to reg_io_width:
syscon_config.reg_stride = reg_io_width;
The current OpenSBI code incorrectly multiplies reg_io_width by 8,
converting a byte value to bits. Fix this by using reg_io_width directly
as the stride value, consistent with the Linux kernel.
Fixes: f21d8f7d59 ("lib: utils/regmap: Add simple FDT based syscon regmap driver")
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260403202903.3407945-1-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>