All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bo Gan <ganboing@gmail.com>
To: Xiang W <wangxiang@iscas.ac.cn>, Bo Gan <ganboing@gmail.com>,
	opensbi@lists.infradead.org
Cc: linmin@eswincomputing.com, pinkesh.vaghela@einfochips.com,
	gaohan@iscas.ac.cn, samuel@sholland.org
Subject: Re: [PATCH 2/3] lib: sbi: Add pmp_set_tor for setting TOR regions
Date: Wed, 12 Nov 2025 02:50:32 -0800	[thread overview]
Message-ID: <6f5e7381-1090-4d63-8eaf-9676ddd13e5d@gmail.com> (raw)
In-Reply-To: <91f61cff8ec8ec7112d78be99b4b38ef934a9d60.camel@iscas.ac.cn>

On 11/11/25 02:35, Xiang W wrote:
> 在 2025-11-11二的 01:45 -0800,Bo Gan写道:
>> Hi Xiang,
>>
>> On 11/10/25 21:45, Xiang W wrote:
>>> 在 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@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
>>
>> I assume you meant port -> prot. For 1, I don't quite like it because it
>> kind of assumes you always change a pmpaddr[i]/pmpcfg[i] pair. In the TOR
>> case, often times you change pmpaddr[i-1] and pmpaddr[i], then pmpcfg[i].
>> An edge case is when addr == 0 and n == 0, for it we only update pmpaddr0,
>> then pmpcfg0. Perhaps I'm mistaken, and you are suggesting `pmp_set_raw`
>> can handle different cases based on whether prot is TOR? Then I'd say it
>> probably makes the code more complicated than necessary, as the check can
>> already be made on the caller side, or no TOR check is necessary with my
>> different function approach.
> The function pmp_set_raw is used to set pmpaddr[i]/pmpcfg[i].
> 
> Regarding the edge case you mentioned, calling pmp_set_raw once is sufficient.
> For regular Tor types, call it twice:
> 
> pmp_set_raw(n-1, 0, addr >> PMP_SHIFT)
> pmp_set_raw(n,prot, (addr + size) >> PMP_SHIFT)
> 

We shouldn't do pmp_set_raw(n-1, 0, addr >> PMP_SHIFT), because it'll zero-
out the corresponding pmpcfg of n-1.

This is actually the tricky part of TOR. You can have adjacent TOR regions
that share the same pmpaddr, i.e., the same pmpaddr forms the upper-bound
of previous region and lower-bound of current region. If we disallow this
sharing, then potentially we'll end up with 2x the number of TOR regions.
Thus, if lib/ code were to use TOR, either it would have to coordinate
neighboring PMP entries, or a single PMP entry should own 2 pmpcfg/pmpaddr
register pairs.

>>
>> For 2, my rationale on having a different function is that I want to keep
>> all existing pmp_set the same way, and try to discourage the use of TOR.
>> Maybe I should have added a warning in the comment in header file. The
>> reason is because TOR makes the PMP entries dependent on preceding ones,
>> so care must be taken when programming them. The caller must have global
>> knowledge of potentially all PMP entries to be programmed in order to use
>> it properly. I don't feel comfortable unifying to the same interface for
>> TOR and NA4/NAPOT.
> The names pmp_set and pmp_set_tor give the impression that pmp_set is a
> general-purpose method, while pmp_set_tor is for handling special cases.
> In reality, pmp_set is not a general-purpose method.
> 

Given those scenarios I mentioned earlier, I'd like to avoid making it
overly complicated. I.e., lib/ code never set or get TOR regions, and can
still safely assume the 1:1 correspondence of pmp index to pmpcfg/pmpaddr
pair. Everything related to TOR is only used by platform pmp_configure
override. Thus, the different function name, so the caller of set_tor can
be easily identified.

Bo

> Regards,
> Xiang W
>>
>> Let me know what you think. I'm happy to listen. Thanks.
>>
>> Bo
>>
>>>> ---
>>>>    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
>>>>
>>>
> 


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

  reply	other threads:[~2025-11-12 10:52 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-11  3:41 [PATCH 0/3] Initial ESWIN/EIC7700 support Bo Gan
2025-11-11  3:41 ` [PATCH 1/3] lib: sbi: allow platform to override PMP configuration Bo Gan
2025-11-11  5:45   ` Xiang W
2025-11-11  9:18     ` Bo Gan
2025-11-11  3:41 ` [PATCH 2/3] lib: sbi: Add pmp_set_tor for setting TOR regions Bo Gan
2025-11-11  5:45   ` Xiang W
2025-11-11  9:45     ` Bo Gan
2025-11-11 10:35       ` Xiang W
2025-11-12 10:50         ` Bo Gan [this message]
2025-11-12 11:29           ` Xiang W
2025-11-11  3:41 ` [PATCH 3/3] platform: generic: eswin: add EIC7700 Bo Gan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6f5e7381-1090-4d63-8eaf-9676ddd13e5d@gmail.com \
    --to=ganboing@gmail.com \
    --cc=gaohan@iscas.ac.cn \
    --cc=linmin@eswincomputing.com \
    --cc=opensbi@lists.infradead.org \
    --cc=pinkesh.vaghela@einfochips.com \
    --cc=samuel@sholland.org \
    --cc=wangxiang@iscas.ac.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.