diff --git a/SUPPORT.md b/SUPPORT.md index 8e040d1c1e..b02a5d25ca 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -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 diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt index e03e5e9e4c..5395a1077c 100644 --- a/docs/misc/arm/device-tree/booting.txt +++ b/docs/misc/arm/device-tree/booting.txt @@ -425,6 +425,49 @@ The static event channel node has the following properties: link-to-foreign-evtchn is a single phandle to a remote evtchn to which local-evtchn will be connected. +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. + Example ======= diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c index 1a79b969af..0ca7b44446 100644 --- a/xen/arch/arm/bootfdt.c +++ b/xen/arch/arm/bootfdt.c @@ -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, diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 1d6b414c73..7412303d20 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -1040,9 +1040,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; @@ -1064,7 +1066,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", diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h index 5ee28b270f..94b7e74b4d 100644 --- a/xen/arch/arm/include/asm/setup.h +++ b/xen/arch/arm/include/asm/setup.h @@ -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 { diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 909013992e..5b7602fdac 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -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);