@@ -293,6 +293,13 @@ pre-defined by configuration using physical address ranges.
Status, ARM: Tech Preview
+### Static Heap
+
+Allow reserving parts of RAM through the device tree using physical
+address ranges as heap.
+
+ Status, ARM: Tech Preview
+
### Memory Sharing
Allow sharing of identical pages between guests
@@ -378,3 +378,47 @@ device-tree:
This will reserve a 512MB region starting at the host physical address
0x30000000 to be exclusively used by DomU1.
+
+
+Static Heap Memory
+==================
+
+The static heap memory refers to parts of RAM reserved in the beginning of
+boot time for heap. The memory is reserved by configuration in the device
+tree using physical address ranges.
+
+The static heap memory declared in the device tree defines the memory areas
+that will be reserved to be used exclusively as heap.
+
+- For Arm32, since there are separated heaps, the static heap will be used
+for both domheap and xenheap. The admin should make sure that the static
+heap region should contain enough memory below 4GB to cater 32-bit DMA.
+
+- For Arm64, since there is a single heap, the defined static heap areas
+shall always go to the heap allocator.
+
+The static heap memory is an optional feature and can be enabled by adding
+below device tree property.
+
+- xen,static-heap
+
+ Property under the top-level "chosen" node. It specifies the address
+ and size of Xen static heap memory. Number of address and size cells
+ for the "xen,static-heap" property is determined by the root node
+ "#address-cells" and "#size-cells". Note that at least a 64KB alignment
+ is required.
+
+Below is an example on how to specify the static heap in device tree:
+
+ / {
+ #address-cells = <0x2>;
+ #size-cells = <0x2>;
+ ...
+ chosen {
+ xen,static-heap = <0x0 0x30000000 0x0 0x40000000>;
+ ...
+ };
+ };
+
+RAM starting from the host physical address 0x30000000 of 1GB size will
+be reserved as static heap.
@@ -64,7 +64,7 @@ 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, enum membank_type type)
{
const struct fdt_property *prop;
unsigned int i, banks;
@@ -95,7 +95,7 @@ static int __init device_tree_get_meminfo(const void *fdt, int node,
continue;
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].type = type;
mem->nr_banks++;
}
@@ -185,7 +185,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, MEMBANK_DEFAULT);
}
static int __init process_reserved_memory_node(const void *fdt, int node,
@@ -301,6 +301,20 @@ static int __init process_chosen_node(const void *fdt, int node,
paddr_t start, end;
int len;
+ if ( fdt_get_property(fdt, node, "xen,static-heap", NULL) )
+ {
+ int rc;
+
+ printk("Checking for static heap in /chosen\n");
+
+ rc = device_tree_get_meminfo(fdt, node, "xen,static-heap",
+ address_cells, size_cells,
+ &bootinfo.reserved_mem,
+ MEMBANK_STATIC_HEAP);
+ if ( rc )
+ return rc;
+ }
+
printk("Checking for initrd in /chosen\n");
prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
@@ -360,7 +374,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,
+ MEMBANK_STATIC_DOMAIN);
}
static int __init early_scan_node(const void *fdt,
@@ -1038,9 +1038,11 @@ static int __init make_memory_node(const struct domain *d,
if ( mem->nr_banks == 0 )
return -ENOENT;
- /* find first memory range not bound to a Xen domain */
- for ( i = 0; i < mem->nr_banks && mem->bank[i].xen_domain; i++ )
+ /* find the first memory range that is reserved for device (or firmware) */
+ for ( i = 0; i < mem->nr_banks &&
+ (mem->bank[i].type != MEMBANK_DEFAULT); i++ )
;
+
if ( i == mem->nr_banks )
return 0;
@@ -1062,7 +1064,7 @@ static int __init make_memory_node(const struct domain *d,
u64 start = mem->bank[i].start;
u64 size = mem->bank[i].size;
- if ( mem->bank[i].xen_domain )
+ if ( mem->bank[i].type == MEMBANK_STATIC_DOMAIN )
continue;
dt_dprintk(" Bank %d: %#"PRIx64"->%#"PRIx64"\n",
@@ -22,11 +22,31 @@ typedef enum {
BOOTMOD_UNKNOWN
} bootmodule_kind;
+enum membank_type {
+ /*
+ * The MEMBANK_DEFAULT type refers to either reserved memory for the
+ * device/firmware (when the bank is in 'reserved_mem') or any RAM (when
+ * the bank is in 'mem').
+ */
+ MEMBANK_DEFAULT,
+ /*
+ * The MEMBANK_STATIC_DOMAIN type is used to indicate whether the memory
+ * bank is bound to a static Xen domain. It is only valid when the bank
+ * is in reserved_mem.
+ */
+ MEMBANK_STATIC_DOMAIN,
+ /*
+ * The MEMBANK_STATIC_HEAP type is used to indicate whether the memory
+ * bank is reserved as static heap. It is only valid when the bank is
+ * in reserved_mem.
+ */
+ MEMBANK_STATIC_HEAP,
+};
struct membank {
paddr_t start;
paddr_t size;
- bool xen_domain; /* whether the memory bank is bound to a Xen domain. */
+ enum membank_type type;
};
struct meminfo {
@@ -644,7 +644,7 @@ static void __init init_staticmem_pages(void)
for ( bank = 0 ; bank < bootinfo.reserved_mem.nr_banks; bank++ )
{
- if ( bootinfo.reserved_mem.bank[bank].xen_domain )
+ if ( bootinfo.reserved_mem.bank[bank].type == MEMBANK_STATIC_DOMAIN )
{
mfn_t bank_start = _mfn(PFN_UP(bootinfo.reserved_mem.bank[bank].start));
unsigned long bank_pages = PFN_DOWN(bootinfo.reserved_mem.bank[bank].size);