@@ -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);
@@ -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:
@@ -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;