@@ -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 */
@@ -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;
}
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@126.com> --- lib/sbi/riscv_asm.c | 42 +++++++++++++++++++----------------------- lib/sbi/sbi_hart.c | 9 ++++++--- 2 files changed, 25 insertions(+), 26 deletions(-)