[PATCH 2/3] lib: sbi: Add pmp_set_tor for setting TOR regions

Xiang W wangxiang at iscas.ac.cn
Mon Nov 10 21:45:51 PST 2025


在 2025-11-10一的 19:41 -0800,Bo Gan写道:
> TOR can be utilized to cover memory regions that are not aligned with
> their sizes. Given that the address matching is formed bt 2 consecutive
> pmpaddr, i.e., pmpaddr(i-1) and pmpaddr(i), TOR should not be used
> generically to avoid pmpaddr conflict with other NA4/NAPOT regions.
> 
> It's advised to only use them in platform code where the caller can
> ensure the index and order of every pmp region especially when there's
> a mixture of TOR/NA4/NAPOT.
> 
> Signed-off-by: Bo Gan <ganboing at gmail.com>

Some suggestions:
1. Merge pmp_set_addr/pmp_set_port into 
void static void pmp_set_raw(unsigned int n, 
			unsigned long port, unsigned long pmpaddr)

2. Modify the declaration of pmp_set to
int pmp_set(bool is_tor, unsigned int n, unsigned long port, 
			unsigned long addr, unsigned long opaque)

Regards,
Xiang W
> ---
>  include/sbi/riscv_asm.h |  4 +++
>  lib/sbi/riscv_asm.c     | 75 +++++++++++++++++++++++++++++++----------
>  2 files changed, 62 insertions(+), 17 deletions(-)
> 
> diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
> index ef48dc89..c23feab6 100644
> --- a/include/sbi/riscv_asm.h
> +++ b/include/sbi/riscv_asm.h
> @@ -218,6 +218,10 @@ int is_pmp_entry_mapped(unsigned long entry);
>  int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
>  	    unsigned long log2len);
>  
> +/* Top of range (TOR) matching mode. pmpaddr(n-1) will also be changed */
> +int pmp_set_tor(unsigned int n, unsigned long prot, unsigned long addr,
> +		unsigned long size);
> +
>  int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
>  	    unsigned long *log2len);
>  
> diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
> index 3e44320f..8f64f2b5 100644
> --- a/lib/sbi/riscv_asm.c
> +++ b/lib/sbi/riscv_asm.c
> @@ -330,16 +330,10 @@ int is_pmp_entry_mapped(unsigned long entry)
>  	return false;
>  }
>  
> -int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
> -	    unsigned long log2len)
> +static void pmp_set_prot(unsigned int n, unsigned long prot)
>  {
> -	int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
> +	int pmpcfg_csr, pmpcfg_shift;
>  	unsigned long cfgmask, pmpcfg;
> -	unsigned long addrmask, pmpaddr;
> -
> -	/* check parameters */
> -	if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
> -		return SBI_EINVAL;
>  
>  	/* calculate PMP register and offset */
>  #if __riscv_xlen == 32
> @@ -351,15 +345,29 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
>  #else
>  # error "Unexpected __riscv_xlen"
>  #endif
> -	pmpaddr_csr = CSR_PMPADDR0 + n;
> -
> -	/* encode PMP config */
> -	prot &= ~PMP_A;
> -	prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
>  	cfgmask = ~(0xffUL << pmpcfg_shift);
>  	pmpcfg	= (csr_read_num(pmpcfg_csr) & cfgmask);
>  	pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask);
>  
> +	csr_write_num(pmpcfg_csr, pmpcfg);
> +}
> +
> +static void pmp_set_addr(unsigned int n, unsigned long pmpaddr)
> +{
> +	int pmpaddr_csr = CSR_PMPADDR0 + n;
> +
> +	csr_write_num(pmpaddr_csr, pmpaddr);
> +}
> +
> +int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
> +	    unsigned long log2len)
> +{
> +	unsigned long addrmask, pmpaddr;
> +
> +	/* check parameters */
> +	if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
> +		return SBI_EINVAL;
> +
>  	/* encode PMP address */
>  	if (log2len == PMP_SHIFT) {
>  		pmpaddr = (addr >> PMP_SHIFT);
> @@ -373,10 +381,41 @@ 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;
> +
>  	/* write csrs */
> -	csr_write_num(pmpaddr_csr, pmpaddr);
> -	csr_write_num(pmpcfg_csr, pmpcfg);
> +	pmp_set_addr(n, pmpaddr);
> +	pmp_set_prot(n, prot);
> +	return 0;
> +}
> +
> +int pmp_set_tor(unsigned int n, unsigned long prot, unsigned long addr,
> +		unsigned long size)
> +{
> +	unsigned long pmpaddr, pmpaddrp;
> +
> +	/* check parameters */
> +	if (n >= PMP_COUNT)
> +		return SBI_EINVAL;
> +
> +	if (n == 0 && addr != 0)
> +		return SBI_EINVAL;
> +
> +	/* encode PMP address */
> +	pmpaddrp = addr >> PMP_SHIFT;
> +	pmpaddr = (addr + size) >> PMP_SHIFT;
>  
> +	/* encode PMP config */
> +	prot &= ~PMP_A;
> +	prot |= PMP_A_TOR;
> +
> +	/* write csrs */
> +	if (n)
> +		pmp_set_addr(n - 1, pmpaddrp);
> +	pmp_set_addr(n, pmpaddr);
> +	pmp_set_prot(n, prot);
>  	return 0;
>  }
>  
> @@ -420,10 +459,12 @@ int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
>  			addr	= (addr & ~((1UL << t1) - 1)) << PMP_SHIFT;
>  			len	= (t1 + PMP_SHIFT + 1);
>  		}
> -	} else {
> +	} else if ((prot & PMP_A) == PMP_A_NA4) {
>  		addr	= csr_read_num(pmpaddr_csr) << PMP_SHIFT;
>  		len	= PMP_SHIFT;
> -	}
> +	} else
> +		/* Error out for TOR region */
> +		return SBI_EINVAL;
>  
>  	/* return details */
>  	*prot_out    = prot;
> -- 
> 2.34.1
> 




More information about the opensbi mailing list