The sbi_mpxy_register_channel() currently performs ceiling division by
PAGE_SIZE but stores the resulting page count in mpxy_shmem_size. All
consumers interpret mpxy_shmem_size as a byte count, so channels requiring
more than one page get an undersized shared memory value.
Address the above issue by using ROUNDUP() to keep the rounded value in
bytes.
Fixes: ec09918426 ("lib: sbi: Update MPXY framework and SBI extension as per latest spec")
Signed-off-by: Shibo Zhu <3499129952@qq.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/tencent_14AA3BA0083001905C262A5CD64E442FC205@qq.com
Signed-off-by: Anup Patel <anup@brainfault.org>
fdt_cpu_fixup() reserves a hardcoded 32 extra bytes, plus 16 more per
HART inside the "zicntr" loop. Those 32 bytes also have to cover every
"status" property rewritten to "disabled", so once more than a handful
of HARTs are disabled the fixups fail with FDT_ERR_NOSPACE (-3).
Bumping the reservation to a fixed worst case is not safe either:
fdt_open_into() cannot know how much space the caller's buffer really
has, it just trusts the requested size. As OpenSBI does not own the
memory following a device tree passed in by the previous booting stage,
over-declaring the blob risks corrupting whatever follows it.
Walk the HART nodes once without modifying them instead, and reserve
exactly what the fixups need. The read-only decision logic is factored
into fdt_cpu_fixup_needed() so the sizing and fixup passes cannot drift
apart, which also makes the per-HART fdt_open_into() redundant. Check
the return values of fdt_setprop_string() and fdt_appendprop_string()
as well, as running out of space used to fail silently.
Fixes: dd9439fbac ("lib: utils: Add a fdt_cpu_fixup() helper")
Signed-off-by: Chen Pei <cp0613@linux.alibaba.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260817084303.1232-1-cp0613@linux.alibaba.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Now that the lock relationship between an event and its owner hart is
explicit, add TSA annotations for the SSE handling code. This includes
indicating which fields are protected by a spinlock, as well as
annotating which functions need to run under a spinlock.
Exclude sse_local_init(), which initializes the spinlock to be acquired,
and sse_event_get() / sse_event_put(), which perform conditional locking
that TSA is not able to follow properly.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260909162322.29778-14-carlos.lopezr4096@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Add Thread Safety Analysis (TSA) annotations for the HTIF driver
implementation.
This requires annotating the tohost/fromhost and htif_console_buf
globals to indicate that they are protected by htif_lock.
htif_system_reset() can be excluded since it is only called under
special circumstances from sbi_system_reset(), when all other harts
have been stopped.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260909162322.29778-10-carlos.lopezr4096@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Add Thread Safety Analysis (TSA) annotations for spinlock APIs, allowing
the compiler to reason about lock acquisition and release.
Annotations have a different meaning if used in header declarations vs C
file implementations. In header declarations, they specify the semantics
of the given function, meaning that we must specify that the spinlock
functions acquire and release a lock ("capability" in clang terms).
In function implementations, attributes affect the function body and
callers in the same translation unit; since the spinlock functions
contain inline assembly, they must be excluded from analysis.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260909162322.29778-4-carlos.lopezr4096@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Currently, the domain initialization order is implied by the order
in which domains are populated by sbi_platform_domains_init() from
sbi_domain_finalize(). This is not documented anywhere and forces
unecessary ordering between domain DT nodes.
To address the above, introduce per-domain 32-bit integer to represent
intialization order (aka "init_order") where domain with a lower
initialization order will be booted first and two domains must not
have same initialization order. For DT based domain creation, new
"init-order" DT property can be used in domain DT node to specify
the initialization order. The ROOT domain is assumed to have lowest
initialization order (aka 0xffffffff).
Signed-off-by: Anup Patel <anup.patel@oss.qualcomm.com>
Reviewed-by: Pawandeep Oza <pawandeep.oza@oss.qualcomm.com>
Tested-by: Pawandeep Oza <pawandeep.oza@oss.qualcomm.com>
Reviewed-by: Yu-Chien Peter Lin <peter.lin@sifive.com>
Link: https://lore.kernel.org/r/20260905131748.922920-4-anup.patel@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Align the PMU extension implementation with the error codes required
by the SBI v3.0 specification, chapter 11:
- sbi_pmu_counter_start and sbi_pmu_counter_stop (secs 11.9-11.10,
tables 39-42): the start_flags/stop_flags bits 2:(XLEN-1) are
reserved and must be zero, so return SBI_ERR_INVALID_PARAM when any
reserved flag bit is set. Introduce SBI_PMU_START_FLAGS_MASK and
SBI_PMU_STOP_FLAGS_MASK for the valid bits of each function.
- sbi_pmu_counter_start and sbi_pmu_counter_stop (tables 40 and 42):
return SBI_ERR_ALREADY_STARTED / SBI_ERR_ALREADY_STOPPED when the
set of counters includes a counter which is already started or
stopped, instead of ignoring the error returned for each counter.
- sbi_pmu_event_get_info (sec 11.14, table 47): the output word must
indicate whether the event is supported, but firmware events were
only matched against the hardware event map and were always
reported as unsupported. Report a validated firmware event as
supported.
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260818210023.466462-4-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
sbi_pmu_event_get_info() walks hw_event_map[] to decide whether a
requested event is supported. For SBI_PMU_EVENT_RAW_IDX and
SBI_PMU_EVENT_RAW_V2_IDX it compares the requested event_data against
temp->select / temp->select_mask without first checking that the map
entry being examined is itself a raw event entry.
Non-raw hardware event entries are added via sbi_pmu_add_hw_event_counter_map(),
leave select and select_mask at zero, hence they satisfy:
temp->select == (event_data & temp->select_mask)
so the first non-raw entry visited will always match.
The issue's observability depends purely on the ordering of hw_event_map[]:
if the platform registers its raw events last, every raw event query, including
unsupported ones, will be reported as supported.
Fix it by checking event_idx against temp->start_idx and temp->end_idx before
comparing select/select_mask.
Fixes: e434584216 ("lib: sbi_pmu: Implement SBI PMU event info function")
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260818210023.466462-3-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
As per section 11.14 of the SBI specification (Function: Get PMU Event
Info, FID #8), Table 47, the event_idx word of an event info entry
only uses BIT[0:19]; BIT[20:31] are reserved for the future purpose
and must be zero. Table 48 further requires the SBI implementation to
return SBI_ERR_INVALID_PARAM if any reserved bit in an event_idx word
is set.
sbi_pmu_event_get_info() does not check the reserved bits, so a
malformed event_idx is silently passed on to pmu_event_validate()
instead of failing the call. Add SBI_PMU_EVENT_IDX_MBZ_MASK covering
the must-be-zero bits and return SBI_ERR_INVALID_PARAM when any of
them are set.
Fixes: e434584216 ("lib: sbi_pmu: Implement SBI PMU event info function")
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260818210023.466462-2-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
SSE injection sets hstatus.SPV to the virtualization state of the
interrupted context before entering the supervisor handler. This patch
completes that existing requirement and does not change the SSE ABI.
The existing code sets SPV when the interrupted context is virtualized,
but leaves it unchanged otherwise. A stale SPV value can therefore make
an event that interrupted host execution appear to have interrupted a
guest. Event completion can then resume with virtualization enabled.
Clear SPV when the interrupted context is not virtualized so the
handler-visible state matches the interrupted context. This also lets
supervisor software, such as the Linux PMU and perf code, reliably tell
whether an SSE interrupted host or virtualized execution.
Fixes: c8cdf01d8f ("lib: sbi: Add support for Supervisor Software Events extension")
Signed-off-by: Zhanpeng Zhang <zhangzhanpeng.jasper@bytedance.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260731071820.7318-1-zhangzhanpeng.jasper@bytedance.com
Signed-off-by: Anup Patel <anup@brainfault.org>
A secondary hart may not have reached the target sleep state by the time
the primary checks, so the one-shot check could fail spuriously. Poll
each PCS status instead and give up after HART_SLEEP_TIMEOUT_MS.
Rework atcsmu_pcs_is_sleep() into the atcsmu_hart_is_sleep() predicate so
sbi_timer_waitms_until() can drive it.
Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260728081041.2724668-7-ben717@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
A deep sleep resume leaves the boot hart in SUSPENDED state, so
init_warmboot() dispatches to init_warm_resume(), which calls the SUSP
device's system_resume callback and not sbi_platform_early_init(). The
restore in ae350_early_init() is dead code on that path.
Fixes: b27ecec76b ("lib: utils/suspend: add Andes ATCSMU suspend driver")
Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260728081041.2724668-5-ben717@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
When a hart implements Smepmp, S-mode and U-mode cannot reach either
device unless its region is shared explicitly. Suspend and resume then
take an access violation as soon as the supervisor touches the SMU or
the LLC.
Share both regions, and take their sizes from the DT nodes rather than
ignoring them.
Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260728081041.2724668-3-ben717@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
The tinfo probe only discovers trigger types; WARL fields tied off
inside an implemented trigger CSR (e.g. an mcontrol6 trigger without
load/store address match) are not discoverable. sbi_alloc_trigger()
also selects the first free trigger slot irrespective of the requested
trigger type or configuration. Unsupported configurations are thus
silently dropped by the hardware while SBI reports success, where SBI
v3.0 sections 19.4 / 19.5 require SBI_ERR_NOT_SUPPORTED.
Add an optional platform device, struct sbi_dbtr_device, with a
trigger_supported(idx, tdata1, tdata2, tdata3) callback reporting
whether the trigger slot selected by idx (the tselect value) supports
a given configuration. Use it, together with the probed per-slot
type_mask, to:
- allocate only trigger slots supporting the requested configuration
(new dbtr_find_free_slot() helper)
- reject unsupportable install/update requests with
SBI_ERR_NOT_SUPPORTED
- count only supporting slots in sbi_dbtr_num_trig() (SBI v3.0
section 19.1)
The install path now dry-runs the allocation of the whole batch before
programming any trigger, so a partially-installed batch is never left
behind. Without a registered device, only the type matching applies (unchanged behavior).
Fixes: 97f234f15c ("lib: sbi: Introduce the SBI debug triggers extension 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/20260727183041.258377-2-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
sbi_ecall_get_extensions_str() advanced offset by the nominal extension
name length without checking remaining capacity. When the caller buffer
was smaller than the concatenated extension list, offset could pass
exts_str_size, so (exts_str_size - offset) became negative and was
passed to sbi_snprintf() as a large u32, and the trailing NUL write
could step past the caller buffer.
The helper can write beyond a caller-provided destination when the
registered extension list exceeds the supplied capacity.
Mirror the guard already used by sbi_hart_get_extensions_str(): stop
appending when the next name would not fit. Add an SBIUNIT regression
that registers several extensions into a 16-byte buffer with a redzone
and verifies no out-of-bounds write.
Closes: https://github.com/riscv-software-src/opensbi/issues/416
Signed-off-by: Yudistira Putra <pyudistira519@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260719101125.190314-1-pyudistira519@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Some T-Head based processors, for example the Sophgo SG2044, have a
JTLB errata that requires special handling of certain TLB maintenance
instructions (sfence.vma).
Introduce a sbi_tlb_local_operations structure so platforms can provide
custom local TLB flush implementations. Use it to implement the JTLB
workaround on affected SoCs (currently Sophgo SG2044).
Signed-off-by: Xiang W <wangxiang@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260617112925.1144190-2-wangxiang@iscas.ac.cn
Signed-off-by: Anup Patel <anup@brainfault.org>
Currently, REFERENCE_CTR and DELIVERED_CTR are always read by sending
an RPMI message to the controller. This does not scale well since
these registers are typically polled frequently by CPU frequency
governors.
The reference counter can be simply the TIME csr, so it can be read
locally without going over RPMI. If the fast channel is supported,
the delivered counter can also be emulated locally: the fast channel
exposes the current frequency, which is multiplied by the elapsed
TIME csr ticks since the last read to calculate the delivered
performance counter.
Signed-off-by: Sunil V L <sunilvl@oss.qualcomm.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260703050530.2460037-3-sunilvl@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
The MPXY framework currently stores registered channels in a global
list and exposes them to all callers. However, the intended model is
that each channel is assigned to a single supervisor domain at boot and
remains owned by that domain for its lifetime.
Introduce fixed owner-domain tracking in struct sbi_mpxy_channel and
make channel lookup and enumeration domain-aware. A channel is now
visible only when accessed from its owning domain. Also require the
owner to be set before channel registration.
This allows MPXY to support systems where the same hart may be reused by
multiple domains while keeping channel ownership and visibility fixed to
the domain that owns the service.
Signed-off-by: Oza Pawandeep <pawandeep.oza@oss.qualcomm.com>
Reviewed-by: Rahul Pathak <rahul.pathak@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260721215758.695736-1-pawandeep.oza@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Fix sbi_irqchip_register_msi() that prevented contiguous EIID allocation:
- Gap check condition was inverted: the original `h->first_hwirq -
hwirq < num_hwirq` incorrectly set `found = true` when the gap was
too small to fit num_hwirq entries. Correct to `>= num_hwirq` so
allocation only proceeds when sufficient space exists between
registered handlers.
- Tail-space check `!found && !hwirq` never triggered after iteration
Replace with `(chip->num_hwirq - hwirq) >= num_hwirq` to correctly
allocate if handler list is empty.
Fixes: 79e63bc834 ("irqchip: add sbi_irqchip_register_msi support")
Signed-off-by: Oza Pawandeep <pawandeep.oza@oss.qualcomm.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260721214833.687361-7-pawandeep.oza@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>