diff mbox series

[v3,3/7] arm/mpu: Introduce utility functions for the pr_t type

Message ID 20250411145655.140667-4-luca.fancellu@arm.com (mailing list archive)
State New
Headers show
Series First chunk for Arm R82 and MPU support | expand

Commit Message

Luca Fancellu April 11, 2025, 2:56 p.m. UTC
Introduce few utility function to manipulate and handle the
pr_t type.

Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
---
 xen/arch/arm/include/asm/mpu.h | 40 ++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

Comments

Orzel, Michal April 16, 2025, 10:50 a.m. UTC | #1
On 11/04/2025 16:56, Luca Fancellu wrote:
> Introduce few utility function to manipulate and handle the
> pr_t type.
> 
> Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
> ---
>  xen/arch/arm/include/asm/mpu.h | 40 ++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/xen/arch/arm/include/asm/mpu.h b/xen/arch/arm/include/asm/mpu.h
> index 59ff22c804c1..6971507457fb 100644
> --- a/xen/arch/arm/include/asm/mpu.h
> +++ b/xen/arch/arm/include/asm/mpu.h
> @@ -20,6 +20,46 @@
>  #define NUM_MPU_REGIONS_MASK    (NUM_MPU_REGIONS - 1)
>  #define MAX_MPU_REGIONS         NUM_MPU_REGIONS_MASK
>  
> +#ifndef __ASSEMBLY__
> +
> +/* Set base address of MPU protection region(pr_t). */
What's the use of (pr_t) in this comment? pr_t is a data type. If at all, it
would want to be ...region @pr but I think you can skip it.

> +static inline void pr_set_base(pr_t *pr, paddr_t base)
> +{
> +    pr->prbar.reg.base = (base >> MPU_REGION_SHIFT);
Looking at pr_t definition, base/limit is 46 bits wide. However the spec says
that last 4bits are reserved (i.e. you should not write to them) unless FEAT_LPA
is implemented. What's our plan here?

> +}
> +
> +/* Set limit address of MPU protection region(pr_t). */
> +static inline void pr_set_limit(pr_t *pr, paddr_t limit)
> +{
> +    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
Why -1? AFAIR these registers take inclusive addresses, so is it because you
want caller to pass limit as exclusive and you convert it to inclusive? I think
it's quite error prone.


~Michal
Luca Fancellu April 16, 2025, 12:31 p.m. UTC | #2
Hi Michal,

> On 16 Apr 2025, at 11:50, Orzel, Michal <Michal.Orzel@amd.com> wrote:
> 
> 
> 
> On 11/04/2025 16:56, Luca Fancellu wrote:
>> Introduce few utility function to manipulate and handle the
>> pr_t type.
>> 
>> Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
>> ---
>> xen/arch/arm/include/asm/mpu.h | 40 ++++++++++++++++++++++++++++++++++
>> 1 file changed, 40 insertions(+)
>> 
>> diff --git a/xen/arch/arm/include/asm/mpu.h b/xen/arch/arm/include/asm/mpu.h
>> index 59ff22c804c1..6971507457fb 100644
>> --- a/xen/arch/arm/include/asm/mpu.h
>> +++ b/xen/arch/arm/include/asm/mpu.h
>> @@ -20,6 +20,46 @@
>> #define NUM_MPU_REGIONS_MASK    (NUM_MPU_REGIONS - 1)
>> #define MAX_MPU_REGIONS         NUM_MPU_REGIONS_MASK
>> 
>> +#ifndef __ASSEMBLY__
>> +
>> +/* Set base address of MPU protection region(pr_t). */
> What's the use of (pr_t) in this comment? pr_t is a data type. If at all, it
> would want to be ...region @pr but I think you can skip it.

ok

> 
>> +static inline void pr_set_base(pr_t *pr, paddr_t base)
>> +{
>> +    pr->prbar.reg.base = (base >> MPU_REGION_SHIFT);
> Looking at pr_t definition, base/limit is 46 bits wide. However the spec says
> that last 4bits are reserved (i.e. you should not write to them) unless FEAT_LPA
> is implemented. What's our plan here?

So we’re currently supporting max 1TB, so probably this one needs to be on the
case when FEAT_LPA is considered not implemented, so I’ll change and if we will
later support more than 42 bit we could do something?

> 
>> +}
>> +
>> +/* Set limit address of MPU protection region(pr_t). */
>> +static inline void pr_set_limit(pr_t *pr, paddr_t limit)
>> +{
>> +    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
> Why -1? AFAIR these registers take inclusive addresses, so is it because you
> want caller to pass limit as exclusive and you convert it to inclusive? I think
> it's quite error prone.

Yes it’s meant to be used with exclusive range, shall we document it or use
Inclusive range instead?

Cheers,
Luca
Orzel, Michal April 16, 2025, 12:42 p.m. UTC | #3
On 16/04/2025 14:31, Luca Fancellu wrote:
> Hi Michal,
> 
>> On 16 Apr 2025, at 11:50, Orzel, Michal <Michal.Orzel@amd.com> wrote:
>>
>>
>>
>> On 11/04/2025 16:56, Luca Fancellu wrote:
>>> Introduce few utility function to manipulate and handle the
>>> pr_t type.
>>>
>>> Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
>>> ---
>>> xen/arch/arm/include/asm/mpu.h | 40 ++++++++++++++++++++++++++++++++++
>>> 1 file changed, 40 insertions(+)
>>>
>>> diff --git a/xen/arch/arm/include/asm/mpu.h b/xen/arch/arm/include/asm/mpu.h
>>> index 59ff22c804c1..6971507457fb 100644
>>> --- a/xen/arch/arm/include/asm/mpu.h
>>> +++ b/xen/arch/arm/include/asm/mpu.h
>>> @@ -20,6 +20,46 @@
>>> #define NUM_MPU_REGIONS_MASK    (NUM_MPU_REGIONS - 1)
>>> #define MAX_MPU_REGIONS         NUM_MPU_REGIONS_MASK
>>>
>>> +#ifndef __ASSEMBLY__
>>> +
>>> +/* Set base address of MPU protection region(pr_t). */
>> What's the use of (pr_t) in this comment? pr_t is a data type. If at all, it
>> would want to be ...region @pr but I think you can skip it.
> 
> ok
> 
>>
>>> +static inline void pr_set_base(pr_t *pr, paddr_t base)
>>> +{
>>> +    pr->prbar.reg.base = (base >> MPU_REGION_SHIFT);
>> Looking at pr_t definition, base/limit is 46 bits wide. However the spec says
>> that last 4bits are reserved (i.e. you should not write to them) unless FEAT_LPA
>> is implemented. What's our plan here?
> 
> So we’re currently supporting max 1TB, so probably this one needs to be on the
> case when FEAT_LPA is considered not implemented, so I’ll change and if we will
> later support more than 42 bit we could do something?
I think yes.

> 
>>
>>> +}
>>> +
>>> +/* Set limit address of MPU protection region(pr_t). */
>>> +static inline void pr_set_limit(pr_t *pr, paddr_t limit)
>>> +{
>>> +    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
>> Why -1? AFAIR these registers take inclusive addresses, so is it because you
>> want caller to pass limit as exclusive and you convert it to inclusive? I think
>> it's quite error prone.
> 
> Yes it’s meant to be used with exclusive range, shall we document it or use
> Inclusive range instead?
What's the expected behavior of callers? Are we going to set up protection
region based on regular start+size pair (like with MMU) or start+end? If the
latter for some reason (with size there are less issues), then end usually is
inclusive and you would not need conversion.

~Michal
Luca Fancellu April 16, 2025, 12:57 p.m. UTC | #4
Hi Michal,

>> 
>>> 
>>>> +}
>>>> +
>>>> +/* Set limit address of MPU protection region(pr_t). */
>>>> +static inline void pr_set_limit(pr_t *pr, paddr_t limit)
>>>> +{
>>>> +    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
>>> Why -1? AFAIR these registers take inclusive addresses, so is it because you
>>> want caller to pass limit as exclusive and you convert it to inclusive? I think
>>> it's quite error prone.
>> 
>> Yes it’s meant to be used with exclusive range, shall we document it or use
>> Inclusive range instead?
> What's the expected behavior of callers? Are we going to set up protection
> region based on regular start+size pair (like with MMU) or start+end? If the
> latter for some reason (with size there are less issues), then end usually is
> inclusive and you would not need conversion.

I think we have a mix because for example destroy_xen_mappings and modify_xen_mappings
are start and end, map_pages_to_xen instead is kind of start+size?

I moved the -1 inside pr_set_limit because it was open-coded in all the places, for example when
referencing linker symbols or output of mfn_to_maddr(mfn_add(smfn, nr_mfn)), for this reason I
thought: let’s call this one with exclusive ranges and modify internally for inclusive.
Orzel, Michal April 16, 2025, 1:10 p.m. UTC | #5
On 16/04/2025 14:57, Luca Fancellu wrote:
> Hi Michal,
> 
>>>
>>>>
>>>>> +}
>>>>> +
>>>>> +/* Set limit address of MPU protection region(pr_t). */
>>>>> +static inline void pr_set_limit(pr_t *pr, paddr_t limit)
>>>>> +{
>>>>> +    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
>>>> Why -1? AFAIR these registers take inclusive addresses, so is it because you
>>>> want caller to pass limit as exclusive and you convert it to inclusive? I think
>>>> it's quite error prone.
>>>
>>> Yes it’s meant to be used with exclusive range, shall we document it or use
>>> Inclusive range instead?
>> What's the expected behavior of callers? Are we going to set up protection
>> region based on regular start+size pair (like with MMU) or start+end? If the
>> latter for some reason (with size there are less issues), then end usually is
>> inclusive and you would not need conversion.
> 
> I think we have a mix because for example destroy_xen_mappings and modify_xen_mappings
> are start and end, map_pages_to_xen instead is kind of start+size?
> 
> I moved the -1 inside pr_set_limit because it was open-coded in all the places, for example when
> referencing linker symbols or output of mfn_to_maddr(mfn_add(smfn, nr_mfn)), for this reason I
> thought: let’s call this one with exclusive ranges and modify internally for inclusive.
Hmm, yes. Indeed we have a mix of places where end is inclusive or exclusive. I
think we can stick with exclusive address being passed to this helper unless
others have a different opinion. I know we tried to convert some places to
start+size but I don't remember the future plans.

~Michal
Luca Fancellu April 16, 2025, 1:12 p.m. UTC | #6
> On 16 Apr 2025, at 14:10, Orzel, Michal <Michal.Orzel@amd.com> wrote:
> 
> 
> 
> On 16/04/2025 14:57, Luca Fancellu wrote:
>> Hi Michal,
>> 
>>>> 
>>>>> 
>>>>>> +}
>>>>>> +
>>>>>> +/* Set limit address of MPU protection region(pr_t). */
>>>>>> +static inline void pr_set_limit(pr_t *pr, paddr_t limit)
>>>>>> +{
>>>>>> +    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
>>>>> Why -1? AFAIR these registers take inclusive addresses, so is it because you
>>>>> want caller to pass limit as exclusive and you convert it to inclusive? I think
>>>>> it's quite error prone.
>>>> 
>>>> Yes it’s meant to be used with exclusive range, shall we document it or use
>>>> Inclusive range instead?
>>> What's the expected behavior of callers? Are we going to set up protection
>>> region based on regular start+size pair (like with MMU) or start+end? If the
>>> latter for some reason (with size there are less issues), then end usually is
>>> inclusive and you would not need conversion.
>> 
>> I think we have a mix because for example destroy_xen_mappings and modify_xen_mappings
>> are start and end, map_pages_to_xen instead is kind of start+size?
>> 
>> I moved the -1 inside pr_set_limit because it was open-coded in all the places, for example when
>> referencing linker symbols or output of mfn_to_maddr(mfn_add(smfn, nr_mfn)), for this reason I
>> thought: let’s call this one with exclusive ranges and modify internally for inclusive.
> Hmm, yes. Indeed we have a mix of places where end is inclusive or exclusive. I
> think we can stick with exclusive address being passed to this helper unless
> others have a different opinion. I know we tried to convert some places to
> start+size but I don't remember the future plans.

Ok, I'll document on top of the helper that @limit needs to be exclusive just to be sure it will be used
in this way.
diff mbox series

Patch

diff --git a/xen/arch/arm/include/asm/mpu.h b/xen/arch/arm/include/asm/mpu.h
index 59ff22c804c1..6971507457fb 100644
--- a/xen/arch/arm/include/asm/mpu.h
+++ b/xen/arch/arm/include/asm/mpu.h
@@ -20,6 +20,46 @@ 
 #define NUM_MPU_REGIONS_MASK    (NUM_MPU_REGIONS - 1)
 #define MAX_MPU_REGIONS         NUM_MPU_REGIONS_MASK
 
+#ifndef __ASSEMBLY__
+
+/* Set base address of MPU protection region(pr_t). */
+static inline void pr_set_base(pr_t *pr, paddr_t base)
+{
+    pr->prbar.reg.base = (base >> MPU_REGION_SHIFT);
+}
+
+/* Set limit address of MPU protection region(pr_t). */
+static inline void pr_set_limit(pr_t *pr, paddr_t limit)
+{
+    pr->prlar.reg.limit = ((limit - 1) >> MPU_REGION_SHIFT);
+}
+
+/*
+ * Access to get base address of MPU protection region(pr_t).
+ * The base address shall be zero extended.
+ */
+static inline paddr_t pr_get_base(pr_t *pr)
+{
+    return (paddr_t)(pr->prbar.reg.base << MPU_REGION_SHIFT);
+}
+
+/*
+ * Access to get limit address of MPU protection region(pr_t).
+ * The limit address shall be concatenated with 0x3f.
+ */
+static inline paddr_t pr_get_limit(pr_t *pr)
+{
+    return (paddr_t)((pr->prlar.reg.limit << MPU_REGION_SHIFT)
+                     | ~MPU_REGION_MASK);
+}
+
+static inline bool region_is_valid(pr_t *pr)
+{
+    return pr->prlar.reg.en;
+}
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ARM_MPU_H__ */
 
 /*