|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] xen/arm: split DTB/initrd placement helpers
commit 0656627b898afe8fb29b93d3e85c55df8f141d1a
Author: Mykola Kvach <mykola_kvach@xxxxxxxx>
AuthorDate: Mon Jun 8 07:39:18 2026 +0100
Commit: Michal Orzel <michal.orzel@xxxxxxx>
CommitDate: Tue Jun 9 16:08:16 2026 +0100
xen/arm: split DTB/initrd placement helpers
The Arm zImage loader currently computes the kernel load address and
places the DTB/initrd in one local flow. The hardware-domain memory
allocator needs to reuse those placement rules before it chooses bank 0,
but open-coding the same calculations there would make the fix harder to
audit.
Split the existing logic into small helpers:
- kernel_zimage_place_in_bank() computes the zImage load address for a
given bank.
- first_bank_can_fit_modules() checks the aggregate first-bank
footprint.
- find_dtb_initrd_placement() chooses the DTB/initrd location within a
known bank and kernel range.
Rename place_modules() to place_dtb_initrd() so the code distinguishes
the kernel image from the DTB/initrd placement area. Also update the
comments linking the hypervisor and toolstack placement paths.
While moving the code, spell the 2MB alignment mask with MB(2) rather
than open-coding (2 << 20). This is mechanical and keeps the generated
value unchanged.
The caller still panics in the same cases as before, so this is intended
to be behavior preserving.
Signed-off-by: Mykola Kvach <mykola_kvach@xxxxxxxx>
Reviewed-by: Michal Orzel <michal.orzel@xxxxxxx>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
tools/libs/guest/xg_dom_arm.c | 2 +-
xen/arch/arm/kernel.c | 147 ++++++++++++++++++++++------------
xen/common/device-tree/domain-build.c | 6 +-
3 files changed, 98 insertions(+), 57 deletions(-)
diff --git a/tools/libs/guest/xg_dom_arm.c b/tools/libs/guest/xg_dom_arm.c
index 739ec1c338..cb0af9f35a 100644
--- a/tools/libs/guest/xg_dom_arm.c
+++ b/tools/libs/guest/xg_dom_arm.c
@@ -429,7 +429,7 @@ static int meminit(struct xc_dom_image *dom)
* just before the kernel.
*
* If changing this then consider
- * xen/arch/arm/kernel.c:place_modules as well.
+ * xen/arch/arm/kernel.c:place_dtb_initrd as well.
*/
bank0end = bankbase[0] + ((uint64_t)dom->rambank_size[0] << XC_PAGE_SHIFT);
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index b72585b7fe..d1be4d8074 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -40,27 +40,59 @@ struct minimal_dtb_header {
/* There are other fields but we don't use them yet. */
};
-static void __init place_modules(struct kernel_info *info,
- paddr_t kernbase, paddr_t kernend)
+static paddr_t __init
+kernel_zimage_place_in_bank(const struct kernel_info *info,
+ paddr_t bank_start, paddr_t bank_size)
{
- /* Align DTB and initrd size to 2Mb. Linux only requires 4 byte alignment
*/
- const struct boot_module *mod = info->bd.initrd;
- const struct membanks *mem = kernel_info_get_mem(info);
- const paddr_t initrd_len = ROUNDUP(mod ? mod->size : 0, MB(2));
- const paddr_t dtb_len = ROUNDUP(fdt_totalsize(info->fdt), MB(2));
- const paddr_t modsize = initrd_len + dtb_len;
+ paddr_t load_addr;
- /* Convenient */
- const paddr_t rambase = mem->bank[0].start;
- const paddr_t ramsize = mem->bank[0].size;
- const paddr_t ramend = rambase + ramsize;
+#ifdef CONFIG_HAS_DOMAIN_TYPE
+ if ( (info->type == DOMAIN_64BIT) && (info->image.start == 0) )
+ return bank_start + info->image.text_offset;
+#endif
+
+ /*
+ * If start is zero, the zImage is position independent, in this
+ * case Documentation/arm/Booting recommends loading below 128MiB
+ * and above 32MiB. Load it as high as possible within these
+ * constraints, while also avoiding the DTB.
+ */
+ if ( info->image.start == 0 )
+ {
+ paddr_t load_end;
+
+ load_end = bank_start + bank_size;
+ load_end = MIN(bank_start + MB(128), load_end);
+
+ load_addr = load_end - info->image.len;
+ /* Align to 2MB */
+ load_addr &= ~(MB(2) - 1);
+ }
+ else
+ load_addr = info->image.start;
+
+ return load_addr;
+}
+
+static bool __init first_bank_can_fit_modules(paddr_t ramsize,
+ paddr_t kernbase, paddr_t
kernend,
+ paddr_t dtb_initrd_size)
+{
const paddr_t kernsize = ROUNDUP(kernend, MB(2)) - kernbase;
- const paddr_t ram128mb = rambase + MB(128);
- paddr_t modbase;
+ /*
+ * Check only the aggregate kernel + DTB/initrd footprint. The actual
+ * DTB/initrd location is selected by find_dtb_initrd_placement().
+ */
+ return dtb_initrd_size + kernsize <= ramsize;
+}
- if ( modsize + kernsize > ramsize )
- panic("Not enough memory in the first bank for the
kernel+dtb+initrd\n");
+static bool __init find_dtb_initrd_placement(paddr_t rambase, paddr_t ramend,
+ paddr_t kernbase, paddr_t kernend,
+ paddr_t dtb_initrd_size,
+ paddr_t *dtb_base)
+{
+ const paddr_t ram128mb = rambase + MB(128);
/*
* DTB must be loaded such that it does not conflict with the
@@ -77,55 +109,64 @@ static void __init place_modules(struct kernel_info *info,
* just before the kernel.
*
* If changing this then consider
- * tools/libxc/xc_dom_arm.c:arch_setup_meminit as well.
+ * tools/libs/guest/xg_dom_arm.c:meminit as well.
*/
- if ( ramend >= ram128mb + modsize && kernend < ram128mb )
- modbase = ram128mb;
- else if ( ramend - modsize > ROUNDUP(kernend, MB(2)) )
- modbase = ramend - modsize;
- else if ( kernbase - rambase > modsize )
- modbase = kernbase - modsize;
- else
+ if ( ramend >= ram128mb + dtb_initrd_size && kernend < ram128mb )
{
- panic("Unable to find suitable location for dtb+initrd\n");
- return;
+ *dtb_base = ram128mb;
+ return true;
}
- info->dtb_paddr = modbase;
- info->initrd_paddr = info->dtb_paddr + dtb_len;
+ if ( ramend - dtb_initrd_size > ROUNDUP(kernend, MB(2)) )
+ {
+ *dtb_base = ramend - dtb_initrd_size;
+ return true;
+ }
+
+ if ( kernbase - rambase > dtb_initrd_size )
+ {
+ *dtb_base = kernbase - dtb_initrd_size;
+ return true;
+ }
+
+ return false;
}
-static paddr_t __init kernel_zimage_place(struct kernel_info *info)
+static void __init place_dtb_initrd(struct kernel_info *info,
+ paddr_t kernbase, paddr_t kernend)
{
+ /* Align DTB and initrd size to 2Mb. Linux only requires 4 byte alignment
*/
+ const struct boot_module *initrd = info->bd.initrd;
const struct membanks *mem = kernel_info_get_mem(info);
- paddr_t load_addr;
+ const paddr_t initrd_len = ROUNDUP(initrd ? initrd->size : 0, MB(2));
+ const paddr_t dtb_len = ROUNDUP(fdt_totalsize(info->fdt), MB(2));
+ const paddr_t dtb_initrd_size = initrd_len + dtb_len;
-#ifdef CONFIG_HAS_DOMAIN_TYPE
- if ( (info->type == DOMAIN_64BIT) && (info->image.start == 0) )
- return mem->bank[0].start + info->image.text_offset;
-#endif
+ /* Convenient */
+ const paddr_t rambase = mem->bank[0].start;
+ const paddr_t ramsize = mem->bank[0].size;
+ const paddr_t ramend = rambase + ramsize;
- /*
- * If start is zero, the zImage is position independent, in this
- * case Documentation/arm/Booting recommends loading below 128MiB
- * and above 32MiB. Load it as high as possible within these
- * constraints, while also avoiding the DTB.
- */
- if ( info->image.start == 0 )
- {
- paddr_t load_end;
+ paddr_t dtb_base;
- load_end = mem->bank[0].start + mem->bank[0].size;
- load_end = MIN(mem->bank[0].start + MB(128), load_end);
+ if ( !first_bank_can_fit_modules(ramsize, kernbase, kernend,
+ dtb_initrd_size) )
+ panic("Not enough memory in the first bank for the
kernel+dtb+initrd\n");
- load_addr = load_end - info->image.len;
- /* Align to 2MB */
- load_addr &= ~((2 << 20) - 1);
- }
- else
- load_addr = info->image.start;
+ if ( !find_dtb_initrd_placement(rambase, ramend, kernbase, kernend,
+ dtb_initrd_size, &dtb_base) )
+ panic("Unable to find suitable location for dtb+initrd\n");
- return load_addr;
+ info->dtb_paddr = dtb_base;
+ info->initrd_paddr = info->dtb_paddr + dtb_len;
+}
+
+static paddr_t __init kernel_zimage_place(struct kernel_info *info)
+{
+ const struct membanks *mem = kernel_info_get_mem(info);
+
+ return kernel_zimage_place_in_bank(info, mem->bank[0].start,
+ mem->bank[0].size);
}
static void __init kernel_zimage_load(struct kernel_info *info)
@@ -143,7 +184,7 @@ static void __init kernel_zimage_load(struct kernel_info
*info)
if ( info->entry == 0 )
info->entry = load_addr;
- place_modules(info, load_addr, load_addr + len);
+ place_dtb_initrd(info, load_addr, load_addr + len);
printk("Loading zImage from %"PRIpaddr" to %"PRIpaddr"-%"PRIpaddr"\n",
paddr, load_addr, load_addr + len);
diff --git a/xen/common/device-tree/domain-build.c
b/xen/common/device-tree/domain-build.c
index 2a760b007b..f3ba496f1e 100644
--- a/xen/common/device-tree/domain-build.c
+++ b/xen/common/device-tree/domain-build.c
@@ -245,8 +245,8 @@ out:
* hardware domain to have memory reachable by devices with limited DMA address
* capabilities (e.g. 32-bit DMA).
*
- * The first bank allocated must be large enough for place_modules() to fit
- * the kernel, DTB and initrd.
+ * The first bank allocated must be large enough for place_dtb_initrd() to
+ * fit the kernel, DTB and initrd.
*/
static bool __init allocate_hwdom_memory(struct kernel_info *kinfo)
{
@@ -302,7 +302,7 @@ static bool __init allocate_hwdom_memory(struct kernel_info
*kinfo)
paddr_t bank_size;
/*
- * The first bank must be large enough for place_modules() to
+ * The first bank must be large enough for place_dtb_initrd() to
* fit the kernel, DTB and initrd. Skip small regions to avoid
* ending up with a tiny first bank.
*/
--
generated by git-patchbot for /home/xen/git/xen.git#master
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |