lib: sbi: Move RISC-V PMP encoding functions to sbi_pmp.c Create a new file for handling the RISC-V PMP format and the new pmp_t type, as opposed to hart PMP CSR specific access. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260430045528.420437-4-npiggin@gmail.com Signed-off-by: Anup Patel <anup@brainfault.org>
diff --git a/include/sbi/sbi_pmp.h b/include/sbi/sbi_pmp.h new file mode 100644 index 0000000..c38dda5 --- /dev/null +++ b/include/sbi/sbi_pmp.h
@@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __SBI_PMP_H__ +#define __SBI_PMP_H__ + +#include <sbi/sbi_types.h> + +struct pmp { + unsigned long addr; + u8 cfg; +}; +typedef struct pmp pmp_t; + +int sbi_pmp_encode(pmp_t *pmp, unsigned long prot, unsigned long addr, + unsigned long log2len); +int sbi_pmp_decode(pmp_t *pmp, unsigned long *prot, unsigned long *addr, + unsigned long *log2len); + +#endif
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk index a01a5ec..a7b4a82 100644 --- a/lib/sbi/objects.mk +++ b/lib/sbi/objects.mk
@@ -87,6 +87,7 @@ libsbi-objs-y += sbi_ipi.o libsbi-objs-y += sbi_irqchip.o libsbi-objs-y += sbi_platform.o +libsbi-objs-y += sbi_pmp.o libsbi-objs-y += sbi_pmu.o libsbi-objs-y += sbi_dbtr.o libsbi-objs-y += sbi_mpxy.o
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c index e33e3c3..da1900e 100644 --- a/lib/sbi/riscv_asm.c +++ b/lib/sbi/riscv_asm.c
@@ -12,6 +12,7 @@ #include <sbi/sbi_error.h> #include <sbi/sbi_platform.h> #include <sbi/sbi_console.h> +#include <sbi/sbi_pmp.h> /* determine CPU extension, return non-zero support */ int misa_extension_imp(char ext) @@ -272,27 +273,6 @@ #undef switchcase_csr_write } -struct pmp { - unsigned long addr; - u8 cfg; -}; -typedef struct pmp pmp_t; - -static unsigned long ctz(unsigned long x) -{ - unsigned long ret = 0; - - if (x == 0) - return 8 * sizeof(x); - - while (!(x & 1UL)) { - ret++; - x = x >> 1; - } - - return ret; -} - int pmp_disable(unsigned int n) { int pmpcfg_csr, pmpcfg_shift; @@ -336,35 +316,6 @@ return false; } -static int pmp_encode(pmp_t *pmp, unsigned long prot, unsigned long addr, - unsigned long log2len) -{ - /* check parameters */ - if (log2len > __riscv_xlen || log2len < PMP_SHIFT) - return SBI_EINVAL; - - /* encode PMP config */ - prot &= ~PMP_A; - prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT; - pmp->cfg = prot; - - /* encode PMP address */ - if (log2len == PMP_SHIFT) { - pmp->addr = (addr >> PMP_SHIFT); - } else { - if (log2len == __riscv_xlen) { - pmp->addr = -1UL; - } else { - unsigned long addrmask; - addrmask = (1UL << (log2len - PMP_SHIFT)) - 1; - pmp->addr = ((addr >> PMP_SHIFT) & ~addrmask); - pmp->addr |= (addrmask >> 1); - } - } - - return SBI_OK; -} - int pmp_set(unsigned int n, unsigned long prot, unsigned long addr, unsigned long log2len) { @@ -377,7 +328,7 @@ if (n >= PMP_COUNT) return SBI_EINVAL; - rc = pmp_encode(&pmp, prot, addr, log2len); + rc = sbi_pmp_encode(&pmp, prot, addr, log2len); if (rc) return rc; @@ -403,44 +354,6 @@ return 0; } -static int pmp_decode(pmp_t *pmp, unsigned long *prot_out, unsigned long *addr_out, - unsigned long *log2len) -{ - unsigned long prot; - unsigned long t1, addr, len; - - /* check parameters */ - if (!prot_out || !addr_out || !log2len) - return SBI_EINVAL; - *prot_out = *addr_out = *log2len = 0; - - /* decode PMP config */ - prot = pmp->cfg; - - /* decode PMP address */ - if ((prot & PMP_A) == PMP_A_NAPOT) { - addr = pmp->addr; - if (addr == -1UL) { - addr = 0; - len = __riscv_xlen; - } else { - t1 = ctz(~addr); - addr = (addr & ~((1UL << t1) - 1)) << PMP_SHIFT; - len = (t1 + PMP_SHIFT + 1); - } - } else { - addr = pmp->addr << PMP_SHIFT; - len = PMP_SHIFT; - } - - /* return details */ - *prot_out = prot; - *addr_out = addr; - *log2len = len; - - return SBI_OK; -} - int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out, unsigned long *log2len) { @@ -468,5 +381,5 @@ pmp.cfg = (csr_read_num(pmpcfg_csr) & cfgmask) >> pmpcfg_shift; pmp.addr = csr_read_num(pmpaddr_csr); - return pmp_decode(&pmp, prot_out, addr_out, log2len); + return sbi_pmp_decode(&pmp, prot_out, addr_out, log2len); }
diff --git a/lib/sbi/sbi_pmp.c b/lib/sbi/sbi_pmp.c new file mode 100644 index 0000000..bb8151c --- /dev/null +++ b/lib/sbi/sbi_pmp.c
@@ -0,0 +1,96 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_encoding.h> +#include <sbi/sbi_error.h> +#include <sbi/sbi_console.h> +#include <sbi/sbi_pmp.h> + +static unsigned long ctz(unsigned long x) +{ + unsigned long ret = 0; + + if (x == 0) + return 8 * sizeof(x); + + while (!(x & 1UL)) { + ret++; + x = x >> 1; + } + + return ret; +} + +int sbi_pmp_encode(pmp_t *pmp, unsigned long prot, unsigned long addr, + unsigned long log2len) +{ + /* check parameters */ + if (log2len > __riscv_xlen || log2len < PMP_SHIFT) + return SBI_EINVAL; + + /* encode PMP config */ + prot &= ~PMP_A; + prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT; + pmp->cfg = prot; + + /* encode PMP address */ + if (log2len == PMP_SHIFT) { + pmp->addr = (addr >> PMP_SHIFT); + } else { + if (log2len == __riscv_xlen) { + pmp->addr = -1UL; + } else { + unsigned long addrmask; + addrmask = (1UL << (log2len - PMP_SHIFT)) - 1; + pmp->addr = ((addr >> PMP_SHIFT) & ~addrmask); + pmp->addr |= (addrmask >> 1); + } + } + + return SBI_OK; +} + +int sbi_pmp_decode(pmp_t *pmp, unsigned long *prot_out, unsigned long *addr_out, + unsigned long *log2len) +{ + unsigned long prot; + unsigned long t1, addr, len; + + /* check parameters */ + if (!prot_out || !addr_out || !log2len) + return SBI_EINVAL; + *prot_out = *addr_out = *log2len = 0; + + /* decode PMP config */ + prot = pmp->cfg; + + /* decode PMP address */ + if ((prot & PMP_A) == PMP_A_NAPOT) { + addr = pmp->addr; + if (addr == -1UL) { + addr = 0; + len = __riscv_xlen; + } else { + t1 = ctz(~addr); + addr = (addr & ~((1UL << t1) - 1)) << PMP_SHIFT; + len = (t1 + PMP_SHIFT + 1); + } + } else { + addr = pmp->addr << PMP_SHIFT; + len = PMP_SHIFT; + } + + /* return details */ + *prot_out = prot; + *addr_out = addr; + *log2len = len; + + return SBI_OK; +}