diff mbox series

[v2,24/40] xen/mpu: introduce "mpu,xxx-memory-section"

Message ID 20230113052914.3845596-25-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 Jan. 13, 2023, 5:28 a.m. UTC
In MPU system, all kinds of resources, including system resource and
domain resource must be statically configured in Device Tree, i.e,
guest RAM must be statically allocated through "xen,static-mem" property
under domain node.

However, due to limited MPU protection regions and a wide variety of resource,
we could easily exhaust all MPU protection regions very quickly.
So we want to introduce a set of new property, "#mpu,xxx-memory-section"
to mitigate the impact.
Each property limits the available host address range of one kind of
system/domain resource.

This commit also introduces "#mpu,guest-memory-section" as an example, for
limiting the scattering of static memory as guest RAM.
Guest RAM shall be not only statically configured through "xen,static-mem"
property in MPU system, but also shall be defined inside
outside "mpu,guest-memory-section".

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
Signed-off-by: Wei Chen <wei.chen@arm.com>
---
 xen/arch/arm/bootfdt.c           | 13 ++++---
 xen/arch/arm/include/asm/setup.h | 24 +++++++++++++
 xen/arch/arm/setup_mpu.c         | 58 ++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index 0085c28d74..d7a5dd0ede 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -59,10 +59,10 @@  void __init device_tree_get_reg(const __be32 **cell, u32 address_cells,
     *size = dt_next_cell(size_cells, cell);
 }
 
-static int __init device_tree_get_meminfo(const void *fdt, int node,
-                                          const char *prop_name,
-                                          u32 address_cells, u32 size_cells,
-                                          void *data, enum membank_type type)
+int __init device_tree_get_meminfo(const void *fdt, int node,
+                                   const char *prop_name,
+                                   u32 address_cells, u32 size_cells,
+                                   void *data, enum membank_type type)
 {
     const struct fdt_property *prop;
     unsigned int i, banks;
@@ -315,6 +315,11 @@  static int __init process_chosen_node(const void *fdt, int node,
         bootinfo.static_heap = true;
     }
 
+#ifdef CONFIG_HAS_MPU
+    if ( process_mpuinfo(fdt, node, address_cells, size_cells) )
+        return -EINVAL;
+#endif
+
     printk("Checking for initrd in /chosen\n");
 
     prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 8f353b67f8..3581f8f990 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -172,6 +172,11 @@  void device_tree_get_reg(const __be32 **cell, u32 address_cells,
 u32 device_tree_get_u32(const void *fdt, int node,
                         const char *prop_name, u32 dflt);
 
+int device_tree_get_meminfo(const void *fdt, int node,
+                            const char *prop_name,
+                            u32 address_cells, u32 size_cells,
+                            void *data, enum membank_type type);
+
 int map_range_to_domain(const struct dt_device_node *dev,
                         u64 addr, u64 len, void *data);
 
@@ -185,6 +190,25 @@  struct init_info
     unsigned int cpuid;
 };
 
+#ifdef CONFIG_HAS_MPU
+/* Index of MPU memory section */
+enum mpu_section_info {
+    MSINFO_GUEST,
+    MSINFO_MAX
+};
+
+extern const char *mpu_section_info_str[MSINFO_MAX];
+
+struct mpuinfo {
+    struct meminfo sections[MSINFO_MAX];
+};
+
+extern struct mpuinfo mpuinfo;
+
+extern int process_mpuinfo(const void *fdt, int node, uint32_t address_cells,
+                           uint32_t size_cells);
+#endif /* CONFIG_HAS_MPU */
+
 #endif
 /*
  * Local variables:
diff --git a/xen/arch/arm/setup_mpu.c b/xen/arch/arm/setup_mpu.c
index ca0d8237d5..09a38a34a4 100644
--- a/xen/arch/arm/setup_mpu.c
+++ b/xen/arch/arm/setup_mpu.c
@@ -20,12 +20,70 @@ 
  */
 
 #include <xen/init.h>
+#include <xen/libfdt/libfdt.h>
 #include <xen/mm.h>
 #include <xen/pfn.h>
 #include <asm/mm_mpu.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 
+const char *mpu_section_info_str[MSINFO_MAX] = {
+    "mpu,guest-memory-section",
+};
+
+/*
+ * mpuinfo stores mpu memory section info, which is configured under
+ * "mpu,xxx-memory-section" in Device Tree.
+ */
+struct mpuinfo __initdata mpuinfo;
+
+/*
+ * Due to limited MPU protection regions and a wide variety of resource,
+ * "#mpu,xxx-memory-section" is introduced to mitigate the impact.
+ * Each property limits the available host address range of one kind of
+ * system/domain resource.
+ *
+ * "mpu,guest-memory-section": guest RAM must be statically allocated
+ * through "xen,static-mem" property in MPU system. "mpu,guest-memory-section"
+ * limits the scattering of "xen,static-mem", as users could not define
+ * a "xen,static-mem" outside "mpu,guest-memory-section".
+ */
+static int __init process_mpu_memory_section(const void *fdt, int node,
+                                             const char *name, void *data,
+                                             uint32_t address_cells,
+                                             uint32_t size_cells)
+{
+    if ( !fdt_get_property(fdt, node, name, NULL) )
+        return -EINVAL;
+
+    return device_tree_get_meminfo(fdt, node, name, address_cells, size_cells,
+                                   data, MEMBANK_DEFAULT);
+}
+
+int __init process_mpuinfo(const void *fdt, int node,
+                           uint32_t address_cells, uint32_t size_cells)
+{
+    uint8_t idx = 0;
+    const char *prop_name;
+
+    for ( ; idx < MSINFO_MAX; idx++ )
+    {
+        prop_name = mpu_section_info_str[idx];
+
+        printk("Checking for %s in /chosen\n", prop_name);
+
+        if ( process_mpu_memory_section(fdt, node, prop_name,
+                                        &mpuinfo.sections[idx],
+                                        address_cells, size_cells) )
+        {
+            printk(XENLOG_ERR "fdt: failed to process %s\n", prop_name);
+            return -EINVAL;
+        }
+    }
+
+    return 0;
+}
+
 void __init setup_mm(void)
 {
     paddr_t ram_start = ~0, ram_end = 0, ram_size = 0;