diff mbox series

[v3,3/4] xen/arm: Find unallocated spaces for magic pages of direct-mapped domU

Message ID 20240403081626.375313-4-xin.wang2@amd.com (mailing list archive)
State Superseded
Headers show
Series DOMCTL-based guest magic region allocation for 11 domUs | expand

Commit Message

Henry Wang April 3, 2024, 8:16 a.m. UTC
For 1:1 direct-mapped dom0less DomUs, the magic pages should not clash
with any RAM region. To find a proper region for guest magic pages,
we can reuse the logic of finding domain extended regions.

If the extended region is enabled, since the extended region banks are
at least 64MB, carve out the first 16MB from the first extended region
bank for magic pages of direct-mapped domU. If the extended region is
disabled, call the newly introduced helper find_11_domU_magic_region()
to find a GUEST_MAGIC_SIZE sized unused region.

Reported-by: Alec Kwapis <alec.kwapis@medtronic.com>
Signed-off-by: Henry Wang <xin.wang2@amd.com>
---
v3:
- Extract the logic of finding unallocated spaces for magic pages of
  direct-mapped domU to a dedicated function in static-memory.c
- Properly handle error and free memory in find_11_domU_magic_region()
v2:
- New patch
---
 xen/arch/arm/dom0less-build.c            | 11 +++++++
 xen/arch/arm/domain_build.c              | 24 ++++++++++++++-
 xen/arch/arm/include/asm/domain_build.h  |  2 ++
 xen/arch/arm/include/asm/static-memory.h |  7 +++++
 xen/arch/arm/static-memory.c             | 39 ++++++++++++++++++++++++
 5 files changed, 82 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index fb63ec6fd1..1963f029fe 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -682,6 +682,17 @@  static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
 
     if ( kinfo->dom0less_feature & DOM0LESS_ENHANCED_NO_XS )
     {
+        /*
+         * Find the guest magic region for 1:1 dom0less domU when the extended
+         * region is not enabled.
+         */
+        if ( !opt_ext_regions || is_32bit_domain(d) )
+        {
+            ret = find_11_domU_magic_region(d, kinfo);
+            if ( ret )
+                goto err;
+        }
+
         ret = make_hypervisor_node(d, kinfo, addrcells, sizecells);
         if ( ret )
             goto err;
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d2a9c047ea..a5d1ca7f73 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -46,7 +46,7 @@  integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
  * If true, the extended regions support is enabled for dom0 and
  * dom0less domUs.
  */
-static bool __initdata opt_ext_regions = true;
+bool __initdata opt_ext_regions = true;
 boolean_param("ext_regions", opt_ext_regions);
 
 static u64 __initdata dom0_mem;
@@ -1196,6 +1196,28 @@  int __init make_hypervisor_node(struct domain *d,
             printk(XENLOG_WARNING "%pd: failed to allocate extended regions\n",
                    d);
         nr_ext_regions = ext_regions->nr_banks;
+
+        /*
+         * If extended region is enabled, carve out the 16MB guest magic page
+         * regions from the first bank of extended region (at least 64MB) for
+         * the 1:1 dom0less DomUs
+         */
+        if ( is_domain_direct_mapped(d) && !is_hardware_domain(d) )
+        {
+            struct mem_map_domain *mem_map = &d->arch.mem_map;
+
+            for ( i = 0; i < mem_map->nr_mem_regions; i++ )
+            {
+                if ( mem_map->regions[i].type == GUEST_MEM_REGION_MAGIC )
+                {
+                    mem_map->regions[i].start = ext_regions->bank[0].start;
+                    mem_map->regions[i].size = GUEST_MAGIC_SIZE;
+
+                    ext_regions->bank[0].start += GUEST_MAGIC_SIZE;
+                    ext_regions->bank[0].size -= GUEST_MAGIC_SIZE;
+                }
+            }
+        }
     }
 
     reg = xzalloc_array(__be32, (nr_ext_regions + 1) * (addrcells + sizecells));
diff --git a/xen/arch/arm/include/asm/domain_build.h b/xen/arch/arm/include/asm/domain_build.h
index 74432123fe..063ff727bb 100644
--- a/xen/arch/arm/include/asm/domain_build.h
+++ b/xen/arch/arm/include/asm/domain_build.h
@@ -4,6 +4,8 @@ 
 #include <xen/sched.h>
 #include <asm/kernel.h>
 
+extern bool opt_ext_regions;
+
 typedef __be32 gic_interrupt_t[3];
 
 bool allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
diff --git a/xen/arch/arm/include/asm/static-memory.h b/xen/arch/arm/include/asm/static-memory.h
index 3e3efd70c3..01e51217ca 100644
--- a/xen/arch/arm/include/asm/static-memory.h
+++ b/xen/arch/arm/include/asm/static-memory.h
@@ -12,6 +12,7 @@  void allocate_static_memory(struct domain *d, struct kernel_info *kinfo,
 void assign_static_memory_11(struct domain *d, struct kernel_info *kinfo,
                              const struct dt_device_node *node);
 void init_staticmem_pages(void);
+int find_11_domU_magic_region(struct domain *d, struct kernel_info *kinfo);
 
 #else /* !CONFIG_STATIC_MEMORY */
 
@@ -31,6 +32,12 @@  static inline void assign_static_memory_11(struct domain *d,
 
 static inline void init_staticmem_pages(void) {};
 
+static inline int find_11_domU_magic_region(struct domain *d,
+                                            struct kernel_info *kinfo)
+{
+    return 0;
+}
+
 #endif /* CONFIG_STATIC_MEMORY */
 
 #endif /* __ASM_STATIC_MEMORY_H_ */
diff --git a/xen/arch/arm/static-memory.c b/xen/arch/arm/static-memory.c
index cffbab7241..c280e1d992 100644
--- a/xen/arch/arm/static-memory.c
+++ b/xen/arch/arm/static-memory.c
@@ -2,6 +2,7 @@ 
 
 #include <xen/sched.h>
 
+#include <asm/domain_build.h>
 #include <asm/static-memory.h>
 
 static bool __init append_static_memory_to_bank(struct domain *d,
@@ -276,6 +277,44 @@  void __init init_staticmem_pages(void)
     }
 }
 
+int __init find_11_domU_magic_region(struct domain *d,
+                                     struct kernel_info *kinfo)
+{
+    if ( is_domain_direct_mapped(d) )
+    {
+        struct meminfo *magic_region = xzalloc(struct meminfo);
+        struct mem_map_domain *mem_map = &d->arch.mem_map;
+        unsigned int i;
+        int ret = 0;
+
+        if ( !magic_region )
+            return -ENOMEM;
+
+        ret = find_unused_regions(d, kinfo, magic_region, GUEST_MAGIC_SIZE);
+        if ( ret )
+        {
+            printk(XENLOG_WARNING
+                   "%pd: failed to find a region for domain magic pages\n", d);
+            xfree(magic_region);
+            return -ENOENT;
+        }
+
+        /* Update the domain memory map. */
+        for ( i = 0; i < mem_map->nr_mem_regions; i++ )
+        {
+            if ( mem_map->regions[i].type == GUEST_MEM_REGION_MAGIC )
+            {
+                mem_map->regions[i].start = magic_region->bank[0].start;
+                mem_map->regions[i].size = GUEST_MAGIC_SIZE;
+            }
+        }
+
+        xfree(magic_region);
+    }
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C