[PATCH 2/4] lib: sbi: Move PMP encoding into a new file
Joel Stanley
joel at jms.id.au
Wed Apr 1 05:50:53 PDT 2026
On Tue, 10 Mar 2026 at 11:19, Nicholas Piggin <npiggin at gmail.com> wrote:
>
> The Tenstorrent RISC-V IOMMU PMP MMRs use the same encoding as PMP CSRs.
> In preparation to support it, move the non hart-specific PMP operations
> into their own file where they will also be used to build the IOMMU
> PMPs.
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
> --- a/lib/sbi/riscv_asm.c
> +++ b/lib/sbi/riscv_asm.c
> +int is_pmp_entry_mapped(unsigned int entry)
> +{
> + pmp_t pmp;
> + if (hart_pmp_read(entry, &pmp))
> + return pmp_enabled(&pmp);
The diff is a bit all over the place so I may have confused myself.
The patch keeps is_pmp_entry_mapped but changes the body from
if (pmp_get(entry, &prot, &addr, &log2len) != 0)
return false;
to
if (hart_pmp_read(entry, &pmp))
return pmp_enabled(&pmp);
but hart_pmp_read returns SBI_OK (0) on success. So we should keep the !=0?
> +int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
> + unsigned long *log2len)
> +{
> + pmp_t pmp;
> + int rc;
>
> - /* return details */
> - *prot_out = prot;
It looks like prot_out is no longer written to after your patch. This
hunk never made it into the new pmp_decode:
/* decode PMP config */
cfgmask = (0xffUL << pmpcfg_shift);
pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask;
prot = pmpcfg >> pmpcfg_shift;
> --- /dev/null
> +++ b/lib/sbi/sbi_pmp.c
> @@ -0,0 +1,91 @@
> +int pmp_create(pmp_t *pmp, unsigned long prot, unsigned long addr,
> + unsigned long log2len)
> +{
> + unsigned long addrmask, pmpaddr;
> +
> + /* check parameters */
> + if (log2len > __riscv_xlen || log2len < PMP_SHIFT)
> + return SBI_EINVAL;
Here we check that log2len <=__riscv_xlen, but in pmp_decode below we
set log2len = __riscv_xlen + 3. Is that just how it works, or should
pmp_decode be able to decode what pmp_create does?
> +
> + /* encode PMP config */
> + prot &= ~PMP_A;
> + prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
> +
> + /* encode PMP address */
> + if (log2len == PMP_SHIFT) {
> + pmpaddr = (addr >> PMP_SHIFT);
> + } else {
> + if (log2len == __riscv_xlen) {
> + pmpaddr = -1UL;
> + } else {
> + addrmask = (1UL << (log2len - PMP_SHIFT)) - 1;
> + pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask);
> + pmpaddr |= (addrmask >> 1);
> + }
> + }
> +
> + pmp->cfg = prot;
> + pmp->addr = pmpaddr;
> +
> + return SBI_OK;
> +}
> +
> +int pmp_decode(pmp_t *pmp, unsigned long *prot_out, unsigned long *addr_out,
> + unsigned long *log2len)
> +{
> + /* check parameters */
> + if (!pmp || !prot_out || !addr_out || !log2len)
> + return SBI_EINVAL;
> +
> + if (!pmp_enabled(pmp))
> + return SBI_EINVAL;
> +
> + /* decode PMP address */
> + if ((pmp->cfg & PMP_A) == PMP_A_NAPOT) {
> + if (pmp->addr == -1UL) {
> + *addr_out = 0;
> + *log2len = __riscv_xlen + 3;
> + } else {
> + unsigned long mask = ~((1UL << cto(pmp->addr)) - 1);
> + *addr_out = (pmp->addr & mask) << PMP_SHIFT;
> + *log2len = (cto(pmp->addr) + PMP_SHIFT + 1);
> + }
> + } else {
> + *addr_out = pmp->addr << PMP_SHIFT;
> + *log2len = PMP_SHIFT;
> + }
> +
> + return SBI_OK;
> +}
More information about the opensbi
mailing list