@@ -355,3 +355,46 @@ device-tree:
This will reserve a 512MB region starting at the host physical address
0x30000000 to be exclusively used by DomU1.
+
+
+Reserved Xenheap Memory
+=======================
+
+The reserved Xenheap memory (also known as statically configured Xenheap)
+refers to parts of RAM reserved in the beginning for Xenheap. The memory is
+reserved by configuration in the device tree using physical address ranges.
+
+The definition of reserved Xenheap memory in the device tree indicates:
+
+(1) Only the defined reserved memory areas will be used as Xenheap.
+
+(2) The defined reserved heap areas shall always go to the heap allocator
+and only be used as Xenheap.
+
+The reserved Xenheap memory is an optional feature and can be enabled by
+adding a device tree property in the `chosen` node. Currently, this feature
+is only supported on AArch64 and this feature reuses the static memory
+allocation device tree configuration.
+
+The dtb property should look like as follows:
+
+- property name
+
+ "xen,static-mem" (Should be used in the `chosen` node)
+
+- cells
+
+ Specify the start address and the length of the reserved Xenheap memory.
+ The number of cells for the address and the size should be defined
+ using the properties `#xen,static-mem-address-cells` and
+ `#xen,static-mem-size-cells` respectively.
+
+Below is an example on how to specify the reserved Xenheap in device tree:
+
+ chosen {
+ #xen,static-mem-address-cells = <0x2>;
+ #xen,static-mem-size-cells = <0x2>;
+ xen,static-mem = <0x0 0x30000000 0x0 0x40000000>;
+ };
+
+RAM at 0x30000000 of 1G size will be reserved as Xenheap.
@@ -66,7 +66,8 @@ void __init device_tree_get_reg(const __be32 **cell, u32 address_cells,
static int __init device_tree_get_meminfo(const void *fdt, int node,
const char *prop_name,
u32 address_cells, u32 size_cells,
- void *data, bool xen_domain)
+ void *data, bool xen_domain,
+ bool xen_heap)
{
const struct fdt_property *prop;
unsigned int i, banks;
@@ -98,6 +99,7 @@ static int __init device_tree_get_meminfo(const void *fdt, int node,
mem->bank[mem->nr_banks].start = start;
mem->bank[mem->nr_banks].size = size;
mem->bank[mem->nr_banks].xen_domain = xen_domain;
+ mem->bank[mem->nr_banks].xen_heap = xen_heap;
mem->nr_banks++;
}
@@ -187,7 +189,7 @@ static int __init process_memory_node(const void *fdt, int node,
void *data)
{
return device_tree_get_meminfo(fdt, node, "reg", address_cells, size_cells,
- data, false);
+ data, false, false);
}
static int __init process_reserved_memory_node(const void *fdt, int node,
@@ -295,7 +297,7 @@ static void __init process_multiboot_node(const void *fdt, int node,
kind, start, domU);
}
-static void __init process_chosen_node(const void *fdt, int node,
+static int __init process_chosen_node(const void *fdt, int node,
const char *name,
u32 address_cells, u32 size_cells)
{
@@ -303,16 +305,41 @@ static void __init process_chosen_node(const void *fdt, int node,
paddr_t start, end;
int len;
+ printk("Checking for reserved Xenheap in /chosen\n");
+
+ if ( fdt_get_property(fdt, node, "xen,static-mem", NULL) )
+ {
+ u32 address_cells = device_tree_get_u32(fdt, node,
+ "#xen,static-mem-address-cells",
+ 0);
+ u32 size_cells = device_tree_get_u32(fdt, node,
+ "#xen,static-mem-size-cells", 0);
+ int rc;
+
+ if ( address_cells < 1 || size_cells < 1 )
+ {
+ printk("fdt: node `%s': invalid #xen,static-mem-address-cells or #xen,static-mem-size-cells\n",
+ name);
+ return -EINVAL;
+ }
+
+ rc = device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells,
+ size_cells, &bootinfo.reserved_mem, false,
+ true);
+ if ( rc )
+ return rc;
+ }
+
printk("Checking for initrd in /chosen\n");
prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
if ( !prop )
/* No initrd present. */
- return;
+ return 0;
if ( len != sizeof(u32) && len != sizeof(u64) )
{
printk("linux,initrd-start property has invalid length %d\n", len);
- return;
+ return -EINVAL;
}
start = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
@@ -320,12 +347,12 @@ static void __init process_chosen_node(const void *fdt, int node,
if ( !prop )
{
printk("linux,initrd-end not present but -start was\n");
- return;
+ return -EINVAL;
}
if ( len != sizeof(u32) && len != sizeof(u64) )
{
printk("linux,initrd-end property has invalid length %d\n", len);
- return;
+ return -EINVAL;
}
end = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
@@ -333,12 +360,14 @@ static void __init process_chosen_node(const void *fdt, int node,
{
printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
start, end);
- return;
+ return -EINVAL;
}
printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
+
+ return 0;
}
static int __init process_domain_node(const void *fdt, int node,
@@ -360,7 +389,8 @@ static int __init process_domain_node(const void *fdt, int node,
"#xen,static-mem-size-cells", 0);
return device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells,
- size_cells, &bootinfo.reserved_mem, true);
+ size_cells, &bootinfo.reserved_mem, true,
+ false);
}
static int __init early_scan_node(const void *fdt,
@@ -380,7 +410,7 @@ static int __init early_scan_node(const void *fdt,
device_tree_node_compatible(fdt, node, "multiboot,module" )))
process_multiboot_node(fdt, node, name, address_cells, size_cells);
else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
- process_chosen_node(fdt, node, name, address_cells, size_cells);
+ rc = process_chosen_node(fdt, node, name, address_cells, size_cells);
else if ( depth == 2 && device_tree_node_compatible(fdt, node, "xen,domain") )
rc = process_domain_node(fdt, node, name, address_cells, size_cells);
@@ -27,6 +27,7 @@ struct membank {
paddr_t start;
paddr_t size;
bool xen_domain; /* whether the memory bank is bound to a Xen domain. */
+ bool xen_heap; /* whether the memory bank is reserved as Xenheap. */
};
struct meminfo {