diff mbox series

[v3,39/52] xen/mpu: support free_init_memory in MPU system

Message ID 20230626033443.2943270-40-Penny.Zheng@arm.com (mailing list archive)
State New, archived
Headers show
Series xen/arm: Add Armv8-R64 MPU support to Xen - Part#1 | expand

Commit Message

Penny Zheng June 26, 2023, 3:34 a.m. UTC
This commit refines free_init_memory() to make it support in MPU system.

We are supporting modify_xen_mappings() in MPU system too, and it is
responsible for modifying memory permission of a existing MPU memory region.
Currently, we only support modifying a *WHOLE* MPU memory region,
part-region modification is not supported, as in worst case, it will
leave three fragments behind.

In MPU system, we map init text and init data section, each with a MPU memory
region. So we shall destroy it seperately in free_init_memory().

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
Signed-off-by: Wei Chen <wei.chen@arm.com>
---
v3:
- As MMU and MPU could share a lot of codes, we made the changes in
original function free_init_memory() in mm.c
---
 xen/arch/arm/mm.c     | 14 +++++++++++++-
 xen/arch/arm/mpu/mm.c | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 45 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 247d17cfa1..ba4ae74e18 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -177,7 +177,12 @@  int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int flags)
     ASSERT(IS_ALIGNED(s, PAGE_SIZE));
     ASSERT(IS_ALIGNED(e, PAGE_SIZE));
     ASSERT(s <= e);
+#ifndef CONFIG_HAS_MPU
     return xen_pt_update(s, INVALID_MFN, (e - s) >> PAGE_SHIFT, flags);
+#else
+    return xen_mpumap_update(virt_to_maddr((void *)s),
+                             virt_to_maddr((void *)e), flags);
+#endif
 }
 
 /* Release all __init and __initdata ranges to be reused */
@@ -212,10 +217,17 @@  void free_init_memory(void)
     for ( i = 0; i < nr; i++ )
         *(p + i) = insn;
 
+    /* Remove init text section */
     rc = destroy_xen_mappings((unsigned long)__init_begin,
+                              (unsigned long)inittext_end);
+    if ( rc )
+        panic("Unable to remove the init text section (rc = %d)\n", rc);
+
+    /* Remove init data section */
+    rc = destroy_xen_mappings((unsigned long)inittext_end,
                               (unsigned long)__init_end);
     if ( rc )
-        panic("Unable to remove the init section (rc = %d)\n", rc);
+        panic("Unable to remove the init data section (rc = %d)\n", rc);
 
     if ( !xen_is_using_staticheap() )
     {
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index b2419f0603..79d1c10d05 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -496,8 +496,39 @@  static int xen_mpumap_update_entry(paddr_t base, paddr_t limit,
     if ( (rc < 0) || (rc == MPUMAP_REGION_OVERLAP) )
         return -EINVAL;
 
+    /* We are updating the permission. */
+    if ( (flags & _PAGE_PRESENT) && (rc == MPUMAP_REGION_FOUND ||
+                                     rc == MPUMAP_REGION_INCLUSIVE) )
+    {
+        /*
+         * Currently, we only support modifying a *WHOLE* MPU memory region,
+         * part-region modification is not supported, as in worst case, it will
+         * leave three fragments behind.
+         * part-region modification will be introduced only when actual usage
+         * come
+         */
+        if ( rc == MPUMAP_REGION_INCLUSIVE )
+        {
+            region_printk("mpu: part-region modification is not supported\n");
+            return -EINVAL;
+        }
+
+        /* We don't allow changing memory attributes. */
+        if (xen_mpumap[idx].prlar.reg.ai != PAGE_AI_MASK(flags) )
+        {
+            region_printk("Modifying memory attributes is not allowed (0x%x -> 0x%x).\n",
+                          xen_mpumap[idx].prlar.reg.ai, PAGE_AI_MASK(flags));
+            return -EINVAL;
+        }
+
+        /* Set new permission */
+        xen_mpumap[idx].prbar.reg.ap = PAGE_AP_MASK(flags);
+        xen_mpumap[idx].prbar.reg.xn = PAGE_XN_MASK(flags);
+
+        write_protection_region((const pr_t*)(&xen_mpumap[idx]), idx);
+    }
     /* We are inserting a mapping => Create new region. */
-    if ( flags & _PAGE_PRESENT )
+    else if ( flags & _PAGE_PRESENT )
     {
         if ( rc != MPUMAP_REGION_FAILED )
             return -EINVAL;