From: Luca Fancellu <luca.fancellu@arm.com>
Add a scheme to distinguish transient MPU regions, to identify MPU
regions which will be mapped for a short period of time.
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Signed-off-by: Hari Limaye <hari.limaye@arm.com>
---
xen/arch/arm/include/asm/arm32/mpu.h | 2 ++
xen/arch/arm/include/asm/arm64/mpu.h | 2 ++
xen/arch/arm/include/asm/mpu/mm.h | 14 +++++++++++++-
xen/arch/arm/include/asm/mpu/regions.inc | 19 +++++++++++++++++--
xen/arch/arm/mpu/mm.c | 23 ++++++++++++++---------
5 files changed, 48 insertions(+), 12 deletions(-)
diff --git a/xen/arch/arm/include/asm/arm32/mpu.h b/xen/arch/arm/include/asm/arm32/mpu.h
index 0a6930b3a0..9906d98809 100644
--- a/xen/arch/arm/include/asm/arm32/mpu.h
+++ b/xen/arch/arm/include/asm/arm32/mpu.h
@@ -39,6 +39,8 @@ typedef union {
typedef struct {
prbar_t prbar;
prlar_t prlar;
+ bool transient;
+ uint8_t pad[7]; /* Pad structure to 16 Bytes */
} pr_t;
#endif /* __ASSEMBLY__ */
diff --git a/xen/arch/arm/include/asm/arm64/mpu.h b/xen/arch/arm/include/asm/arm64/mpu.h
index f0ce344e78..1d1843eda0 100644
--- a/xen/arch/arm/include/asm/arm64/mpu.h
+++ b/xen/arch/arm/include/asm/arm64/mpu.h
@@ -38,6 +38,8 @@ typedef union {
typedef struct {
prbar_t prbar;
prlar_t prlar;
+ bool transient;
+ uint8_t pad[15]; /* Pad structure to 32 Bytes */
} pr_t;
#endif /* __ASSEMBLY__ */
diff --git a/xen/arch/arm/include/asm/mpu/mm.h b/xen/arch/arm/include/asm/mpu/mm.h
index c32fac8905..56ca411af4 100644
--- a/xen/arch/arm/include/asm/mpu/mm.h
+++ b/xen/arch/arm/include/asm/mpu/mm.h
@@ -60,6 +60,16 @@ static inline void context_sync_mpu(void)
isb();
}
+static inline bool region_is_transient(pr_t *pr)
+{
+ return pr->transient;
+}
+
+static inline void region_set_transient(pr_t *pr, bool transient)
+{
+ pr->transient = transient;
+}
+
/*
* The following API requires context_sync_mpu() after being used to modify MPU
* regions:
@@ -80,9 +90,11 @@ void write_protection_region(const pr_t *pr_write, uint8_t sel);
* @param base Base address of the range to map (inclusive).
* @param limit Limit address of the range to map (exclusive).
* @param flags Flags for the memory range to map.
+ * @param transient True for a temporary mapping, otherwise False.
* @return 0 on success, negative on error.
*/
-int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags);
+int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags,
+ bool transient);
/*
* Creates a pr_t structure describing a protection region.
diff --git a/xen/arch/arm/include/asm/mpu/regions.inc b/xen/arch/arm/include/asm/mpu/regions.inc
index 23fead3b21..f9892fe3d8 100644
--- a/xen/arch/arm/include/asm/mpu/regions.inc
+++ b/xen/arch/arm/include/asm/mpu/regions.inc
@@ -14,19 +14,31 @@
#define PRLAR_ELx_EN 0x1
#ifdef CONFIG_ARM_64
-#define XEN_MPUMAP_ENTRY_SHIFT 0x4 /* 16 byte structure */
+#define XEN_MPUMAP_ENTRY_SHIFT 0x5 /* 32 byte structure */
+#define XEN_MPUMAP_ENTRY_ZERO_OFFSET 0x10 /* {PRBAR, PRLAR} is 16 bytes */
.macro store_pair reg1, reg2, dst
stp \reg1, \reg2, [\dst]
.endm
+.macro zero_pair dst, offset, tmp1, tmp2
+ stp xzr, xzr, [\dst, \offset]
+.endm
+
#else
-#define XEN_MPUMAP_ENTRY_SHIFT 0x3 /* 8 byte structure */
+#define XEN_MPUMAP_ENTRY_SHIFT 0x4 /* 16 byte structure */
+#define XEN_MPUMAP_ENTRY_ZERO_OFFSET 0x8 /* {PRBAR, PRLAR} is 8 bytes */
.macro store_pair reg1, reg2, dst
strd \reg1, \reg2, [\dst]
.endm
+.macro zero_pair dst, offset, tmp1, tmp2
+ mov \tmp1, #0
+ mov \tmp2, #0
+ strd \tmp1, \tmp2, [\dst, \offset]
+.endm
+
#endif
/*
@@ -97,6 +109,9 @@
3:
+ /* Clear the rest of the xen_mpumap entry. Clobbers prbar and prlar. */
+ zero_pair \base, #XEN_MPUMAP_ENTRY_ZERO_OFFSET, \prbar, \prlar
+
add \sel, \sel, #1
1:
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index 0b05103180..38474bcfa2 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -251,13 +251,14 @@ static void disable_mpu_region_from_index(uint8_t index)
* Update the entry in the MPU memory region mapping table (xen_mpumap) for the
* given memory range and flags, creating one if none exists.
*
- * @param base Base address (inclusive).
- * @param limit Limit address (exclusive).
- * @param flags Region attributes (a combination of PAGE_HYPERVISOR_XXX)
+ * @param base Base address (inclusive).
+ * @param limit Limit address (exclusive).
+ * @param flags Region attributes (a combination of PAGE_HYPERVISOR_XXX)
+ * @param transient True for a temporary mapping, otherwise False.
* @return 0 on success, otherwise negative on error.
*/
static int xen_mpumap_update_entry(paddr_t base, paddr_t limit,
- unsigned int flags)
+ unsigned int flags, bool transient)
{
bool flags_has_page_present;
uint8_t idx;
@@ -297,6 +298,7 @@ static int xen_mpumap_update_entry(paddr_t base, paddr_t limit,
return -ENOENT;
xen_mpumap[idx] = pr_of_addr(base, limit, flags);
+ region_set_transient(&xen_mpumap[idx], transient);
write_protection_region(&xen_mpumap[idx], idx);
}
@@ -316,7 +318,8 @@ static int xen_mpumap_update_entry(paddr_t base, paddr_t limit,
return 0;
}
-int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags)
+int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags,
+ bool transient)
{
int rc;
@@ -342,7 +345,7 @@ int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags)
spin_lock(&xen_mpumap_lock);
- rc = xen_mpumap_update_entry(base, limit, flags);
+ rc = xen_mpumap_update_entry(base, limit, flags, transient);
if ( !rc )
context_sync_mpu();
@@ -357,14 +360,15 @@ int destroy_xen_mappings(unsigned long s, unsigned long e)
ASSERT(IS_ALIGNED(e, PAGE_SIZE));
ASSERT(s < e);
- return xen_mpumap_update(s, e, 0);
+ return xen_mpumap_update(s, e, 0, false);
}
int map_pages_to_xen(unsigned long virt, mfn_t mfn, unsigned long nr_mfns,
unsigned int flags)
{
/* MPU systems have no translation, ma == va, so pass virt directly */
- return xen_mpumap_update(virt, mfn_to_maddr(mfn_add(mfn, nr_mfns)), flags);
+ return xen_mpumap_update(virt, mfn_to_maddr(mfn_add(mfn, nr_mfns)), flags,
+ false);
}
/*
@@ -385,7 +389,8 @@ static void __init setup_staticheap_mappings(void)
paddr_t bank_end = bank_start + bank_size;
/* Map static heap with one MPU protection region */
- if ( xen_mpumap_update(bank_start, bank_end, PAGE_HYPERVISOR) )
+ if ( xen_mpumap_update(bank_start, bank_end, PAGE_HYPERVISOR,
+ false) )
panic("Failed to map static heap\n");
break;
--
2.34.1
On 30/07/2025 10:45, Hari Limaye wrote:
> From: Luca Fancellu <luca.fancellu@arm.com>
>
> Add a scheme to distinguish transient MPU regions, to identify MPU
> regions which will be mapped for a short period of time.
The commit msg lacks description why this is needed.
>
> Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
> Signed-off-by: Hari Limaye <hari.limaye@arm.com>
> ---
> xen/arch/arm/include/asm/arm32/mpu.h | 2 ++
> xen/arch/arm/include/asm/arm64/mpu.h | 2 ++
> xen/arch/arm/include/asm/mpu/mm.h | 14 +++++++++++++-
> xen/arch/arm/include/asm/mpu/regions.inc | 19 +++++++++++++++++--
> xen/arch/arm/mpu/mm.c | 23 ++++++++++++++---------
> 5 files changed, 48 insertions(+), 12 deletions(-)
>
> diff --git a/xen/arch/arm/include/asm/arm32/mpu.h b/xen/arch/arm/include/asm/arm32/mpu.h
> index 0a6930b3a0..9906d98809 100644
> --- a/xen/arch/arm/include/asm/arm32/mpu.h
> +++ b/xen/arch/arm/include/asm/arm32/mpu.h
> @@ -39,6 +39,8 @@ typedef union {
> typedef struct {
> prbar_t prbar;
> prlar_t prlar;
> + bool transient;
> + uint8_t pad[7]; /* Pad structure to 16 Bytes */
> } pr_t;
>
> #endif /* __ASSEMBLY__ */
> diff --git a/xen/arch/arm/include/asm/arm64/mpu.h b/xen/arch/arm/include/asm/arm64/mpu.h
> index f0ce344e78..1d1843eda0 100644
> --- a/xen/arch/arm/include/asm/arm64/mpu.h
> +++ b/xen/arch/arm/include/asm/arm64/mpu.h
> @@ -38,6 +38,8 @@ typedef union {
> typedef struct {
> prbar_t prbar;
> prlar_t prlar;
> + bool transient;
> + uint8_t pad[15]; /* Pad structure to 32 Bytes */
> } pr_t;
>
> #endif /* __ASSEMBLY__ */
> diff --git a/xen/arch/arm/include/asm/mpu/mm.h b/xen/arch/arm/include/asm/mpu/mm.h
> index c32fac8905..56ca411af4 100644
> --- a/xen/arch/arm/include/asm/mpu/mm.h
> +++ b/xen/arch/arm/include/asm/mpu/mm.h
> @@ -60,6 +60,16 @@ static inline void context_sync_mpu(void)
> isb();
> }
>
> +static inline bool region_is_transient(pr_t *pr)
As this is just a read helper, pr could be const?
~Michal
Hi Hari, On 30/07/2025 09:45, Hari Limaye wrote: > CAUTION: This message has originated from an External Source. Please use proper judgment and caution when opening attachments, clicking links, or responding to this email. > > > From: Luca Fancellu <luca.fancellu@arm.com> > > Add a scheme to distinguish transient MPU regions, to identify MPU > regions which will be mapped for a short period of time. > > Signed-off-by: Luca Fancellu <luca.fancellu@arm.com> > Signed-off-by: Hari Limaye <hari.limaye@arm.com> Reviewed-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com> Tested-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com> (On R82 and R52 with some additional patches) - Ayan
© 2016 - 2025 Red Hat, Inc.