[RFC v2 PATCH 1/2] lib: sbi: Improve pmp_get/pmp_set
Xiang W
wxjstz at 126.com
Fri Nov 8 05:15:15 PST 2024
The previous code used byte addresses, which limited the address
range to 0-2^XLEN. Changing to word addresses allows access to
all address ranges.
Signed-off-by: Xiang W <wxjstz at 126.com>
---
lib/sbi/riscv_asm.c | 42 +++++++++++++++++++-----------------------
lib/sbi/sbi_hart.c | 9 ++++++---
2 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c7d75ac..6c9780a 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -309,7 +309,7 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long addrmask, pmpaddr;
/* check parameters */
- if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
+ if (n >= PMP_COUNT || log2len > __riscv_xlen + 1)
return SBI_EINVAL;
/* calculate PMP register and offset */
@@ -326,22 +326,22 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
/* encode PMP config */
prot &= ~PMP_A;
- prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
+ prot |= (log2len == 0) ? PMP_A_NA4 : PMP_A_NAPOT;
cfgmask = ~(0xffUL << pmpcfg_shift);
pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask);
/* encode PMP address */
- if (log2len == PMP_SHIFT) {
- pmpaddr = (addr >> PMP_SHIFT);
+ if (log2len == 0) {
+ pmpaddr = addr;
+ } else if (log2len == __riscv_xlen) {
+ pmpaddr = -1UL >> 1;
+ } else if (log2len == __riscv_xlen + 1) {
+ pmpaddr = -1UL;
} else {
- if (log2len == __riscv_xlen) {
- pmpaddr = -1UL;
- } else {
- addrmask = (1UL << (log2len - PMP_SHIFT)) - 1;
- pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask);
- pmpaddr |= (addrmask >> 1);
- }
+ addrmask = (1UL << log2len) - 1;
+ pmpaddr = addr & ~addrmask;
+ pmpaddr |= addrmask >> 1;
}
/* write csrs */
@@ -381,19 +381,15 @@ int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
prot = pmpcfg >> pmpcfg_shift;
/* decode PMP address */
+ addr = csr_read_num(pmpaddr_csr);
+ len = 0;
if ((prot & PMP_A) == PMP_A_NAPOT) {
- addr = csr_read_num(pmpaddr_csr);
- 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 = csr_read_num(pmpaddr_csr) << PMP_SHIFT;
- len = PMP_SHIFT;
+ t1 = ctz(~addr);
+ len = t1 + 1;
+ if (len >= __riscv_xlen)
+ addr = 0;
+ else
+ addr = addr & ~((1UL << t1) - 1);
}
/* return details */
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 0451fcb..832db7a 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -361,7 +361,8 @@ static void sbi_hart_smepmp_set(struct sbi_scratch *scratch,
unsigned long pmp_addr = reg->base >> PMP_SHIFT;
if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) {
- pmp_set(pmp_idx, pmp_flags, reg->base, reg->order);
+ pmp_set(pmp_idx, pmp_flags, reg->base >> PMP_SHIFT,
+ reg->order - PMP_SHIFT);
} else {
sbi_printf("Can not configure pmp for domain %s because"
" memory region address 0x%lx or size 0x%lx "
@@ -478,7 +479,8 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch,
pmp_addr = reg->base >> PMP_SHIFT;
if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) {
- pmp_set(pmp_idx++, pmp_flags, reg->base, reg->order);
+ pmp_set(pmp_idx++, pmp_flags, reg->base >> PMP_SHIFT,
+ reg->order - PMP_SHIFT);
} else {
sbi_printf("Can not configure pmp for domain %s because"
" memory region address 0x%lx or size 0x%lx "
@@ -518,7 +520,8 @@ int sbi_hart_map_saddr(unsigned long addr, unsigned long size)
}
}
- pmp_set(SBI_SMEPMP_RESV_ENTRY, pmp_flags, base, order);
+ pmp_set(SBI_SMEPMP_RESV_ENTRY, pmp_flags, base >> PMP_SHIFT,
+ order - PMP_SHIFT);
return SBI_OK;
}
--
2.45.2
More information about the opensbi
mailing list