[PATCH] xen/arm: mpu: Fix ioremap_attr region size and return value

Michal Orzel posted 1 patch 1 week, 3 days ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/20260402075645.52583-1-michal.orzel@amd.com
xen/arch/arm/mpu/mm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
[PATCH] xen/arm: mpu: Fix ioremap_attr region size and return value
Posted by Michal Orzel 1 week, 3 days ago
ioremap_attr() computes end_pg as round_pgup(start_pg + len), but
start_pg has already had the sub-page offset stripped by round_pgdown().
When start is not page-aligned, the sub-page offset is lost and the
resulting MPU protection region can be one page too small, leaving the
tail of the requested range covered by something else.

Additionally, the function returns maddr_to_virt(start_pg) — the
page-aligned base dropping the sub-page offset that callers (e.g. ioremap
of an unaligned MMIO base) depend on to reach the correct register block.

Fix end_pg to use the original start so the sub-page tail is included
in the rounding, and return the original start address to preserve the
offset, matching the behaviour of other ioremap implementations.

Fixes: efeec4c70798 ("arm/mpu: Implement ioremap_attr for MPU")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
---
 xen/arch/arm/mpu/mm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index 6b3b0b06e95d..aff88bd3a9c1 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -596,13 +596,13 @@ void free_init_memory(void)
 void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned int flags)
 {
     paddr_t start_pg = round_pgdown(start);
-    paddr_t end_pg = round_pgup(start_pg + len);
+    paddr_t end_pg = round_pgup(start + len);
 
     if ( xen_mpumap_update(start_pg, end_pg, flags) )
         return NULL;
 
     /* Mapped or already mapped */
-    return maddr_to_virt(start_pg);
+    return maddr_to_virt(start);
 }
 
 /*
-- 
2.43.0


Re: [PATCH] xen/arm: mpu: Fix ioremap_attr region size and return value
Posted by Luca Fancellu 1 week, 3 days ago
Hi Michal,

> On 2 Apr 2026, at 08:56, Michal Orzel <michal.orzel@amd.com> wrote:
> 
> ioremap_attr() computes end_pg as round_pgup(start_pg + len), but
> start_pg has already had the sub-page offset stripped by round_pgdown().
> When start is not page-aligned, the sub-page offset is lost and the
> resulting MPU protection region can be one page too small, leaving the
> tail of the requested range covered by something else.
> 
> Additionally, the function returns maddr_to_virt(start_pg) — the
> page-aligned base dropping the sub-page offset that callers (e.g. ioremap
> of an unaligned MMIO base) depend on to reach the correct register block.
> 
> Fix end_pg to use the original start so the sub-page tail is included
> in the rounding, and return the original start address to preserve the
> offset, matching the behaviour of other ioremap implementations.
> 
> Fixes: efeec4c70798 ("arm/mpu: Implement ioremap_attr for MPU")
> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
> ---
> xen/arch/arm/mpu/mm.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
> index 6b3b0b06e95d..aff88bd3a9c1 100644
> --- a/xen/arch/arm/mpu/mm.c
> +++ b/xen/arch/arm/mpu/mm.c
> @@ -596,13 +596,13 @@ void free_init_memory(void)
> void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned int flags)
> {
>     paddr_t start_pg = round_pgdown(start);
> -    paddr_t end_pg = round_pgup(start_pg + len);
> +    paddr_t end_pg = round_pgup(start + len);
> 
>     if ( xen_mpumap_update(start_pg, end_pg, flags) )
>         return NULL;
> 
>     /* Mapped or already mapped */
> -    return maddr_to_virt(start_pg);
> +    return maddr_to_virt(start);
> }
> 
> /*
> -- 
> 2.43.0
> 
> 

good catch!

Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>

Cheers,
Luca