[PATCH v2 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common

Oleksii Kurochko posted 2 patches 3 months, 2 weeks ago
[PATCH v2 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common
Posted by Oleksii Kurochko 3 months, 2 weeks ago
From: Shawn Anastasio <sanastasio@raptorengineering.com>

Arm's setup.c contains a collection of functions for parsing memory map
and other boot information from a device tree. Since these routines are
generally useful on any architecture that supports device tree booting,
move them into xen/common/device-tree.

Also, common/device_tree.c has been moved to the device-tree folder with
the corresponding updates to common/Makefile and common/device-tree/Makefile.

Mentioning of arm32 is changed to CONFIG_SEPARATE_XENHEAP in comparison with
original ARM's code as now it is moved in common code.

Suggested-by: Julien Grall <julien@xen.org>
Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Julien Grall <jgrall@amazon.com>
---
Changes in V9:
 - rename xen/common/device_tree.c to xen/common/device-tree.c
 - update MAINTAINERS file: drop xen/common/device_tree.c from it.
---
Changes in V8:
 - add the version of Xen from which bootinfo.c was derived from.
 - update the commit message.
 - add Acked-by: Julien Grall <jgrall@amazon.com>.
---
Changes in V7:
 - move obj-$(CONFIG_HAS_DEVICE_TREE) += device-tree/ to proper place in common/Makefile.
 - rename macros __XEN_BOOTFDT_H__ to XEN_BOOTFDT_H to not violate MISRA rule 21.1.
 - drop definition of "#define MAX_FDT_SIZE SZ_2M" in xen/bootfdt.h as it is expected to
   be arch-specific. Back "#define MAX_FDT_SIZE SZ_2M" to arm/setup.h where it was before
   these changes.
 - git mv xen/common/device_tree.c xen/common/device-tree/ and update correspondingly
   Makefiles of common/ and common/device-tree
 - update the commit message
---
Changes in V6:
 - update the version of the patch to v6.   
---
Changes in V5:
 - After rebase the Shawn's patch v4 on top of current staging the following
   was done:
   - add xen/include/xen/bootfdt.h to MAINTAINERS file.
   - drop message "Early device tree parsing and".
   - After rebase on top of the current staging the following changes were done:
     - init bootinfo variable in <common/device-tree/bootinfo.c> with BOOTINFO_INIT;
     - update the code of dt_unreserved_regions():
         CONFIG_STATIC_SHM related changes and getting of reserved_mem
         bootinfo_get_shmem()
     - update the code of meminfo_overlap_check():
         add check ( INVALID_PADDR == bank_start ) to if case.
     - update the code of check_reserved_regions_overlap():
         CONFIG_STATIC_SHM related changes.
     - struct bootinfo was updated ( CONFIG_STATIC_SHM changes )
     - add shared_meminfo ( because of CONFIG_STATIC_SHM )
     - struct struct membanks was update with __struct group so <xen/kernel> is
       neeeded to be included in bootfdt.h
     - move BOOTINFO_ACPI_INIT, BOOTINFO_SHMEM_INIT, BOOTINFO_INIT to generic bootfdt.h
     - bootinfo_get_reserved_mem(), bootinfo_get_mem(), bootinfo_get_acpi(),
       bootinfo_get_shmem() and bootinfo_get_shmem_extra() were moved to xen/bootfdt.h
   - s/arm32/CONFIG_SEPARATE_XENHEAP/
   - add inclusion of <xen/macros.h> because there are function in <xen/bootfdt.h> which
     are using container_of().
 ---
Changes in v4:
  - create new xen/include/bootinfo.h rather than relying on arch's
    asm/setup.h to provide required definitions for bootinfo.c
  - build bootinfo.c as .init.o
  - clean up and sort bootinfo.c's #includes
  - use CONFIG_SEPARATE_XENHEAP rather than CONFIG_ARM_32 to guard
    xenheap-specific behavior of populate_boot_allocator
  - (MAINTAINERS) include all of common/device-tree rather than just
    bootinfo.c
---
 MAINTAINERS                                   |   3 +-
 xen/arch/arm/include/asm/setup.h              | 185 +------
 xen/arch/arm/setup.c                          | 432 -----------------
 xen/common/Makefile                           |   2 +-
 xen/common/device-tree/Makefile               |   2 +
 xen/common/device-tree/bootinfo.c             | 459 ++++++++++++++++++
 .../device-tree.c}                            |   0
 xen/include/xen/bootfdt.h                     | 195 ++++++++
 8 files changed, 660 insertions(+), 618 deletions(-)
 create mode 100644 xen/common/device-tree/Makefile
 create mode 100644 xen/common/device-tree/bootinfo.c
 rename xen/common/{device_tree.c => device-tree/device-tree.c} (100%)
 create mode 100644 xen/include/xen/bootfdt.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7c524a8a93..89be48fdf9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -291,9 +291,10 @@ M:	Bertrand Marquis <bertrand.marquis@arm.com>
 M:	Michal Orzel <michal.orzel@amd.com>
 S:	Supported
 F:	xen/common/libfdt/
-F:	xen/common/device_tree.c
+F:	xen/common/device-tree/
 F:	xen/common/dt-overlay.c
 F:	xen/include/xen/libfdt/
+F:	xen/include/xen/bootfdt.h
 F:	xen/include/xen/device_tree.h
 F:	xen/drivers/passthrough/device_tree.c
 
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index c34179da93..1748be29e5 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -3,159 +3,11 @@
 
 #include <public/version.h>
 #include <asm/p2m.h>
+#include <xen/bootfdt.h>
 #include <xen/device_tree.h>
 
-#define MIN_FDT_ALIGN 8
 #define MAX_FDT_SIZE SZ_2M
 
-#define NR_MEM_BANKS 256
-#define NR_SHMEM_BANKS 32
-
-#define MAX_MODULES 32 /* Current maximum useful modules */
-
-typedef enum {
-    BOOTMOD_XEN,
-    BOOTMOD_FDT,
-    BOOTMOD_KERNEL,
-    BOOTMOD_RAMDISK,
-    BOOTMOD_XSM,
-    BOOTMOD_GUEST_DTB,
-    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,
-    /*
-     * The MEMBANK_FDT_RESVMEM type is used to indicate whether the memory
-     * bank is from the FDT reserve map.
-     */
-    MEMBANK_FDT_RESVMEM,
-};
-
-/* Indicates the maximum number of characters(\0 included) for shm_id */
-#define MAX_SHM_ID_LENGTH 16
-
-struct shmem_membank_extra {
-    char shm_id[MAX_SHM_ID_LENGTH];
-    unsigned int nr_shm_borrowers;
-};
-
-struct membank {
-    paddr_t start;
-    paddr_t size;
-    union {
-        enum membank_type type;
-#ifdef CONFIG_STATIC_SHM
-        struct shmem_membank_extra *shmem_extra;
-#endif
-    };
-};
-
-struct membanks {
-    __struct_group(membanks_hdr, common, ,
-        unsigned int nr_banks;
-        unsigned int max_banks;
-    );
-    struct membank bank[];
-};
-
-struct meminfo {
-    struct membanks_hdr common;
-    struct membank bank[NR_MEM_BANKS];
-};
-
-struct shared_meminfo {
-    struct membanks_hdr common;
-    struct membank bank[NR_SHMEM_BANKS];
-    struct shmem_membank_extra extra[NR_SHMEM_BANKS];
-};
-
-/*
- * The domU flag is set for kernels and ramdisks of "xen,domain" nodes.
- * The purpose of the domU flag is to avoid getting confused in
- * kernel_probe, where we try to guess which is the dom0 kernel and
- * initrd to be compatible with all versions of the multiboot spec. 
- */
-#define BOOTMOD_MAX_CMDLINE 1024
-struct bootmodule {
-    bootmodule_kind kind;
-    bool domU;
-    paddr_t start;
-    paddr_t size;
-};
-
-/* DT_MAX_NAME is the node name max length according the DT spec */
-#define DT_MAX_NAME 41
-struct bootcmdline {
-    bootmodule_kind kind;
-    bool domU;
-    paddr_t start;
-    char dt_name[DT_MAX_NAME];
-    char cmdline[BOOTMOD_MAX_CMDLINE];
-};
-
-struct bootmodules {
-    int nr_mods;
-    struct bootmodule module[MAX_MODULES];
-};
-
-struct bootcmdlines {
-    unsigned int nr_mods;
-    struct bootcmdline cmdline[MAX_MODULES];
-};
-
-struct bootinfo {
-    struct meminfo mem;
-    /* The reserved regions are only used when booting using Device-Tree */
-    struct meminfo reserved_mem;
-    struct bootmodules modules;
-    struct bootcmdlines cmdlines;
-#ifdef CONFIG_ACPI
-    struct meminfo acpi;
-#endif
-#ifdef CONFIG_STATIC_SHM
-    struct shared_meminfo shmem;
-#endif
-    bool static_heap;
-};
-
-#ifdef CONFIG_ACPI
-#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS,
-#else
-#define BOOTINFO_ACPI_INIT
-#endif
-
-#ifdef CONFIG_STATIC_SHM
-#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS,
-#else
-#define BOOTINFO_SHMEM_INIT
-#endif
-
-#define BOOTINFO_INIT                               \
-{                                                   \
-    .mem.common.max_banks = NR_MEM_BANKS,           \
-    .reserved_mem.common.max_banks = NR_MEM_BANKS,  \
-    BOOTINFO_ACPI_INIT                              \
-    BOOTINFO_SHMEM_INIT                             \
-}
-
 struct map_range_data
 {
     struct domain *d;
@@ -167,39 +19,8 @@ struct map_range_data
     struct rangeset *irq_ranges;
 };
 
-extern struct bootinfo bootinfo;
-
 extern domid_t max_init_domid;
 
-static inline struct membanks *bootinfo_get_mem(void)
-{
-    return container_of(&bootinfo.mem.common, struct membanks, common);
-}
-
-static inline struct membanks *bootinfo_get_reserved_mem(void)
-{
-    return container_of(&bootinfo.reserved_mem.common, struct membanks, common);
-}
-
-#ifdef CONFIG_ACPI
-static inline struct membanks *bootinfo_get_acpi(void)
-{
-    return container_of(&bootinfo.acpi.common, struct membanks, common);
-}
-#endif
-
-#ifdef CONFIG_STATIC_SHM
-static inline struct membanks *bootinfo_get_shmem(void)
-{
-    return container_of(&bootinfo.shmem.common, struct membanks, common);
-}
-
-static inline struct shmem_membank_extra *bootinfo_get_shmem_extra(void)
-{
-    return bootinfo.shmem.extra;
-}
-#endif
-
 void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
 
 size_t estimate_efi_size(unsigned int mem_nr_banks);
@@ -220,9 +41,6 @@ void fw_unreserved_regions(paddr_t s, paddr_t e,
                            void (*cb)(paddr_t ps, paddr_t pe),
                            unsigned int first);
 
-size_t boot_fdt_info(const void *fdt, paddr_t paddr);
-const char *boot_fdt_cmdline(const void *fdt);
-
 bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size);
 
 struct bootmodule *add_boot_module(bootmodule_kind kind,
@@ -237,7 +55,6 @@ struct bootcmdline * boot_cmdline_find_by_name(const char *name);
 const char *boot_module_kind_as_string(bootmodule_kind kind);
 
 void init_pdx(void);
-void populate_boot_allocator(void);
 void setup_mm(void);
 
 extern uint32_t hyp_traps_vector[];
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 0c2fdaceaf..cb2c0a16b8 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -48,8 +48,6 @@
 #include <xsm/xsm.h>
 #include <asm/acpi.h>
 
-struct bootinfo __initdata bootinfo = BOOTINFO_INIT;
-
 /*
  * Sanitized version of cpuinfo containing only features available on all
  * cores (only on arm64 as there is no sanitization support on arm32).
@@ -203,321 +201,6 @@ static void __init processor_id(void)
     processor_setup();
 }
 
-static void __init dt_unreserved_regions(paddr_t s, paddr_t e,
-                                         void (*cb)(paddr_t ps, paddr_t pe),
-                                         unsigned int first)
-{
-    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
-#ifdef CONFIG_STATIC_SHM
-    const struct membanks *shmem = bootinfo_get_shmem();
-    unsigned int offset;
-#endif
-    unsigned int i;
-
-    /*
-     * i is the current bootmodule we are evaluating across all possible
-     * kinds.
-     */
-    for ( i = first; i < reserved_mem->nr_banks; i++ )
-    {
-        paddr_t r_s = reserved_mem->bank[i].start;
-        paddr_t r_e = r_s + reserved_mem->bank[i].size;
-
-        if ( s < r_e && r_s < e )
-        {
-            dt_unreserved_regions(r_e, e, cb, i + 1);
-            dt_unreserved_regions(s, r_s, cb, i + 1);
-            return;
-        }
-    }
-
-#ifdef CONFIG_STATIC_SHM
-    /*
-     * When retrieving the corresponding shared memory addresses
-     * below, we need to index the shmem->bank starting from 0, hence
-     * we need to use i - reserved_mem->nr_banks.
-    */
-    offset = reserved_mem->nr_banks;
-    for ( ; i - offset < shmem->nr_banks; i++ )
-    {
-        paddr_t r_s, r_e;
-
-        r_s = shmem->bank[i - offset].start;
-
-        /* Shared memory banks can contain INVALID_PADDR as start */
-        if ( INVALID_PADDR == r_s )
-            continue;
-
-        r_e = r_s + shmem->bank[i - offset].size;
-
-        if ( s < r_e && r_s < e )
-        {
-            dt_unreserved_regions(r_e, e, cb, i + 1);
-            dt_unreserved_regions(s, r_s, cb, i + 1);
-            return;
-        }
-    }
-#endif
-
-    cb(s, e);
-}
-
-/*
- * TODO: '*_end' could be 0 if the bank/region is at the end of the physical
- * address space. This is for now not handled as it requires more rework.
- */
-static bool __init meminfo_overlap_check(const struct membanks *mem,
-                                         paddr_t region_start,
-                                         paddr_t region_size)
-{
-    paddr_t bank_start = INVALID_PADDR, bank_end = 0;
-    paddr_t region_end = region_start + region_size;
-    unsigned int i, bank_num = mem->nr_banks;
-
-    for ( i = 0; i < bank_num; i++ )
-    {
-        bank_start = mem->bank[i].start;
-        bank_end = bank_start + mem->bank[i].size;
-
-        if ( INVALID_PADDR == bank_start || region_end <= bank_start ||
-             region_start >= bank_end )
-            continue;
-        else
-        {
-            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
-                   region_start, region_end, i, bank_start, bank_end);
-            return true;
-        }
-    }
-
-    return false;
-}
-
-/*
- * TODO: '*_end' could be 0 if the module/region is at the end of the physical
- * address space. This is for now not handled as it requires more rework.
- */
-static bool __init bootmodules_overlap_check(struct bootmodules *bootmodules,
-                                             paddr_t region_start,
-                                             paddr_t region_size)
-{
-    paddr_t mod_start = INVALID_PADDR, mod_end = 0;
-    paddr_t region_end = region_start + region_size;
-    unsigned int i, mod_num = bootmodules->nr_mods;
-
-    for ( i = 0; i < mod_num; i++ )
-    {
-        mod_start = bootmodules->module[i].start;
-        mod_end = mod_start + bootmodules->module[i].size;
-
-        if ( region_end <= mod_start || region_start >= mod_end )
-            continue;
-        else
-        {
-            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with mod[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
-                   region_start, region_end, i, mod_start, mod_end);
-            return true;
-        }
-    }
-
-    return false;
-}
-
-void __init fw_unreserved_regions(paddr_t s, paddr_t e,
-                                  void (*cb)(paddr_t ps, paddr_t pe),
-                                  unsigned int first)
-{
-    if ( acpi_disabled )
-        dt_unreserved_regions(s, e, cb, first);
-    else
-        cb(s, e);
-}
-
-/*
- * Given an input physical address range, check if this range is overlapping
- * with the existing reserved memory regions defined in bootinfo.
- * Return true if the input physical address range is overlapping with any
- * existing reserved memory regions, otherwise false.
- */
-bool __init check_reserved_regions_overlap(paddr_t region_start,
-                                           paddr_t region_size)
-{
-    const struct membanks *mem_banks[] = {
-        bootinfo_get_reserved_mem(),
-#ifdef CONFIG_ACPI
-        bootinfo_get_acpi(),
-#endif
-#ifdef CONFIG_STATIC_SHM
-        bootinfo_get_shmem(),
-#endif
-    };
-    unsigned int i;
-
-    /*
-     * Check if input region is overlapping with reserved memory banks or
-     * ACPI EfiACPIReclaimMemory (when ACPI feature is enabled) or static
-     * shared memory banks (when static shared memory feature is enabled)
-     */
-    for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ )
-        if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) )
-            return true;
-
-    /* Check if input region is overlapping with bootmodules */
-    if ( bootmodules_overlap_check(&bootinfo.modules,
-                                   region_start, region_size) )
-        return true;
-
-    return false;
-}
-
-struct bootmodule __init *add_boot_module(bootmodule_kind kind,
-                                          paddr_t start, paddr_t size,
-                                          bool domU)
-{
-    struct bootmodules *mods = &bootinfo.modules;
-    struct bootmodule *mod;
-    unsigned int i;
-
-    if ( mods->nr_mods == MAX_MODULES )
-    {
-        printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" (too many)\n",
-               boot_module_kind_as_string(kind), start, start + size);
-        return NULL;
-    }
-
-    if ( check_reserved_regions_overlap(start, size) )
-        return NULL;
-
-    for ( i = 0 ; i < mods->nr_mods ; i++ )
-    {
-        mod = &mods->module[i];
-        if ( mod->kind == kind && mod->start == start )
-        {
-            if ( !domU )
-                mod->domU = false;
-            return mod;
-        }
-    }
-
-    mod = &mods->module[mods->nr_mods++];
-    mod->kind = kind;
-    mod->start = start;
-    mod->size = size;
-    mod->domU = domU;
-
-    return mod;
-}
-
-/*
- * boot_module_find_by_kind can only be used to return Xen modules (e.g
- * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest
- * modules.
- */
-struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
-{
-    struct bootmodules *mods = &bootinfo.modules;
-    struct bootmodule *mod;
-    int i;
-    for (i = 0 ; i < mods->nr_mods ; i++ )
-    {
-        mod = &mods->module[i];
-        if ( mod->kind == kind && !mod->domU )
-            return mod;
-    }
-    return NULL;
-}
-
-void __init add_boot_cmdline(const char *name, const char *cmdline,
-                             bootmodule_kind kind, paddr_t start, bool domU)
-{
-    struct bootcmdlines *cmds = &bootinfo.cmdlines;
-    struct bootcmdline *cmd;
-
-    if ( cmds->nr_mods == MAX_MODULES )
-    {
-        printk("Ignoring %s cmdline (too many)\n", name);
-        return;
-    }
-
-    cmd = &cmds->cmdline[cmds->nr_mods++];
-    cmd->kind = kind;
-    cmd->domU = domU;
-    cmd->start = start;
-
-    ASSERT(strlen(name) <= DT_MAX_NAME);
-    safe_strcpy(cmd->dt_name, name);
-
-    if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE )
-        panic("module %s command line too long\n", name);
-    safe_strcpy(cmd->cmdline, cmdline);
-}
-
-/*
- * boot_cmdline_find_by_kind can only be used to return Xen modules (e.g
- * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest
- * modules.
- */
-struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
-{
-    struct bootcmdlines *cmds = &bootinfo.cmdlines;
-    struct bootcmdline *cmd;
-    int i;
-
-    for ( i = 0 ; i < cmds->nr_mods ; i++ )
-    {
-        cmd = &cmds->cmdline[i];
-        if ( cmd->kind == kind && !cmd->domU )
-            return cmd;
-    }
-    return NULL;
-}
-
-struct bootcmdline * __init boot_cmdline_find_by_name(const char *name)
-{
-    struct bootcmdlines *mods = &bootinfo.cmdlines;
-    struct bootcmdline *mod;
-    unsigned int i;
-
-    for (i = 0 ; i < mods->nr_mods ; i++ )
-    {
-        mod = &mods->cmdline[i];
-        if ( strcmp(mod->dt_name, name) == 0 )
-            return mod;
-    }
-    return NULL;
-}
-
-struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind,
-                                                             paddr_t start)
-{
-    struct bootmodules *mods = &bootinfo.modules;
-    struct bootmodule *mod;
-    unsigned int i;
-
-    for (i = 0 ; i < mods->nr_mods ; i++ )
-    {
-        mod = &mods->module[i];
-        if ( mod->kind == kind && mod->start == start )
-            return mod;
-    }
-    return NULL;
-}
-
-const char * __init boot_module_kind_as_string(bootmodule_kind kind)
-{
-    switch ( kind )
-    {
-    case BOOTMOD_XEN:     return "Xen";
-    case BOOTMOD_FDT:     return "Device Tree";
-    case BOOTMOD_KERNEL:  return "Kernel";
-    case BOOTMOD_RAMDISK: return "Ramdisk";
-    case BOOTMOD_XSM:     return "XSM";
-    case BOOTMOD_GUEST_DTB:     return "DTB";
-    case BOOTMOD_UNKNOWN: return "Unknown";
-    default: BUG();
-    }
-}
-
 void __init discard_initial_modules(void)
 {
     struct bootmodules *mi = &bootinfo.modules;
@@ -556,40 +239,6 @@ static void * __init relocate_fdt(paddr_t dtb_paddr, size_t dtb_size)
     return fdt;
 }
 
-/*
- * Return the end of the non-module region starting at s. In other
- * words return s the start of the next modules after s.
- *
- * On input *end is the end of the region which should be considered
- * and it is updated to reflect the end of the module, clipped to the
- * end of the region if it would run over.
- */
-static paddr_t __init next_module(paddr_t s, paddr_t *end)
-{
-    struct bootmodules *mi = &bootinfo.modules;
-    paddr_t lowest = ~(paddr_t)0;
-    int i;
-
-    for ( i = 0; i < mi->nr_mods; i++ )
-    {
-        paddr_t mod_s = mi->module[i].start;
-        paddr_t mod_e = mod_s + mi->module[i].size;
-
-        if ( !mi->module[i].size )
-            continue;
-
-        if ( mod_s < s )
-            continue;
-        if ( mod_s > lowest )
-            continue;
-        if ( mod_s > *end )
-            continue;
-        lowest = mod_s;
-        *end = min(*end, mod_e);
-    }
-    return lowest;
-}
-
 void __init init_pdx(void)
 {
     const struct membanks *mem = bootinfo_get_mem();
@@ -635,87 +284,6 @@ void __init init_pdx(void)
     }
 }
 
-/*
- * Populate the boot allocator.
- * If a static heap was not provided by the admin, all the RAM but the
- * following regions will be added:
- *  - Modules (e.g., Xen, Kernel)
- *  - Reserved regions
- *  - Xenheap (arm32 only)
- * If a static heap was provided by the admin, populate the boot
- * allocator with the corresponding regions only, but with Xenheap excluded
- * on arm32.
- */
-void __init populate_boot_allocator(void)
-{
-    unsigned int i;
-    const struct membanks *banks = bootinfo_get_mem();
-    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
-    paddr_t s, e;
-
-    if ( bootinfo.static_heap )
-    {
-        for ( i = 0 ; i < reserved_mem->nr_banks; i++ )
-        {
-            if ( reserved_mem->bank[i].type != MEMBANK_STATIC_HEAP )
-                continue;
-
-            s = reserved_mem->bank[i].start;
-            e = s + reserved_mem->bank[i].size;
-#ifdef CONFIG_ARM_32
-            /* Avoid the xenheap, note that the xenheap cannot across a bank */
-            if ( s <= mfn_to_maddr(directmap_mfn_start) &&
-                 e >= mfn_to_maddr(directmap_mfn_end) )
-            {
-                init_boot_pages(s, mfn_to_maddr(directmap_mfn_start));
-                init_boot_pages(mfn_to_maddr(directmap_mfn_end), e);
-            }
-            else
-#endif
-                init_boot_pages(s, e);
-        }
-
-        return;
-    }
-
-    for ( i = 0; i < banks->nr_banks; i++ )
-    {
-        const struct membank *bank = &banks->bank[i];
-        paddr_t bank_end = bank->start + bank->size;
-
-        s = bank->start;
-        while ( s < bank_end )
-        {
-            paddr_t n = bank_end;
-
-            e = next_module(s, &n);
-
-            if ( e == ~(paddr_t)0 )
-                e = n = bank_end;
-
-            /*
-             * Module in a RAM bank other than the one which we are
-             * not dealing with here.
-             */
-            if ( e > bank_end )
-                e = bank_end;
-
-#ifdef CONFIG_ARM_32
-            /* Avoid the xenheap */
-            if ( s < mfn_to_maddr(directmap_mfn_end) &&
-                 mfn_to_maddr(directmap_mfn_start) < e )
-            {
-                e = mfn_to_maddr(directmap_mfn_start);
-                n = mfn_to_maddr(directmap_mfn_end);
-            }
-#endif
-
-            fw_unreserved_regions(s, e, init_boot_pages, 0);
-            s = n;
-        }
-    }
-}
-
 size_t __read_mostly dcache_line_bytes;
 
 /* C entry point for boot CPU */
diff --git a/xen/common/Makefile b/xen/common/Makefile
index f12a474d40..7e66802a9e 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
 obj-$(CONFIG_CORE_PARKING) += core_parking.o
 obj-y += cpu.o
 obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
-obj-$(CONFIG_HAS_DEVICE_TREE) += device_tree.o
+obj-$(CONFIG_HAS_DEVICE_TREE) += device-tree/
 obj-$(CONFIG_IOREQ_SERVER) += dm.o
 obj-y += domain.o
 obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o
diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile
new file mode 100644
index 0000000000..f813f7555f
--- /dev/null
+++ b/xen/common/device-tree/Makefile
@@ -0,0 +1,2 @@
+obj-y += bootinfo.init.o
+obj-y += device-tree.o
diff --git a/xen/common/device-tree/bootinfo.c b/xen/common/device-tree/bootinfo.c
new file mode 100644
index 0000000000..f2e6a1145b
--- /dev/null
+++ b/xen/common/device-tree/bootinfo.c
@@ -0,0 +1,459 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Derived from Xen 4.19's $xen/arch/arm/setup.c.
+ *
+ * bookkeeping routines.
+ *
+ * Tim Deegan <tim@xen.org>
+ * Copyright (c) 2011 Citrix Systems.
+ * Copyright (c) 2024 Raptor Engineering LLC
+ */
+
+#include <xen/acpi.h>
+#include <xen/bootfdt.h>
+#include <xen/bug.h>
+#include <xen/device_tree.h>
+#include <xen/init.h>
+#include <xen/libfdt/libfdt-xen.h>
+#include <xen/mm.h>
+
+struct bootinfo __initdata bootinfo = BOOTINFO_INIT;
+
+const char * __init boot_module_kind_as_string(bootmodule_kind kind)
+{
+    switch ( kind )
+    {
+    case BOOTMOD_XEN:     return "Xen";
+    case BOOTMOD_FDT:     return "Device Tree";
+    case BOOTMOD_KERNEL:  return "Kernel";
+    case BOOTMOD_RAMDISK: return "Ramdisk";
+    case BOOTMOD_XSM:     return "XSM";
+    case BOOTMOD_GUEST_DTB:     return "DTB";
+    case BOOTMOD_UNKNOWN: return "Unknown";
+    default: BUG();
+    }
+}
+
+static void __init dt_unreserved_regions(paddr_t s, paddr_t e,
+                                         void (*cb)(paddr_t ps, paddr_t pe),
+                                         unsigned int first)
+{
+    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
+#ifdef CONFIG_STATIC_SHM
+    const struct membanks *shmem = bootinfo_get_shmem();
+    unsigned int offset;
+#endif
+    unsigned int i;
+
+    /*
+     * i is the current bootmodule we are evaluating across all possible
+     * kinds.
+     */
+    for ( i = first; i < reserved_mem->nr_banks; i++ )
+    {
+        paddr_t r_s = reserved_mem->bank[i].start;
+        paddr_t r_e = r_s + reserved_mem->bank[i].size;
+
+        if ( s < r_e && r_s < e )
+        {
+            dt_unreserved_regions(r_e, e, cb, i + 1);
+            dt_unreserved_regions(s, r_s, cb, i + 1);
+            return;
+        }
+    }
+
+#ifdef CONFIG_STATIC_SHM
+    /*
+     * When retrieving the corresponding shared memory addresses
+     * below, we need to index the shmem->bank starting from 0, hence
+     * we need to use i - reserved_mem->nr_banks.
+    */
+    offset = reserved_mem->nr_banks;
+    for ( ; i - offset < shmem->nr_banks; i++ )
+    {
+        paddr_t r_s, r_e;
+
+        r_s = shmem->bank[i - offset].start;
+
+        /* Shared memory banks can contain INVALID_PADDR as start */
+        if ( INVALID_PADDR == r_s )
+            continue;
+
+        r_e = r_s + shmem->bank[i - offset].size;
+
+        if ( s < r_e && r_s < e )
+        {
+            dt_unreserved_regions(r_e, e, cb, i + 1);
+            dt_unreserved_regions(s, r_s, cb, i + 1);
+            return;
+        }
+    }
+#endif
+
+    cb(s, e);
+}
+
+/*
+ * TODO: '*_end' could be 0 if the bank/region is at the end of the physical
+ * address space. This is for now not handled as it requires more rework.
+ */
+static bool __init meminfo_overlap_check(const struct membanks *mem,
+                                         paddr_t region_start,
+                                         paddr_t region_size)
+{
+    paddr_t bank_start = INVALID_PADDR, bank_end = 0;
+    paddr_t region_end = region_start + region_size;
+    unsigned int i, bank_num = mem->nr_banks;
+
+    for ( i = 0; i < bank_num; i++ )
+    {
+        bank_start = mem->bank[i].start;
+        bank_end = bank_start + mem->bank[i].size;
+
+        if ( INVALID_PADDR == bank_start || region_end <= bank_start ||
+             region_start >= bank_end )
+            continue;
+        else
+        {
+            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
+                   region_start, region_end, i, bank_start, bank_end);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/*
+ * TODO: '*_end' could be 0 if the module/region is at the end of the physical
+ * address space. This is for now not handled as it requires more rework.
+ */
+static bool __init bootmodules_overlap_check(struct bootmodules *bootmodules,
+                                             paddr_t region_start,
+                                             paddr_t region_size)
+{
+    paddr_t mod_start = INVALID_PADDR, mod_end = 0;
+    paddr_t region_end = region_start + region_size;
+    unsigned int i, mod_num = bootmodules->nr_mods;
+
+    for ( i = 0; i < mod_num; i++ )
+    {
+        mod_start = bootmodules->module[i].start;
+        mod_end = mod_start + bootmodules->module[i].size;
+
+        if ( region_end <= mod_start || region_start >= mod_end )
+            continue;
+        else
+        {
+            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with mod[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
+                   region_start, region_end, i, mod_start, mod_end);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void __init fw_unreserved_regions(paddr_t s, paddr_t e,
+                                  void (*cb)(paddr_t ps, paddr_t pe),
+                                  unsigned int first)
+{
+    if ( acpi_disabled )
+        dt_unreserved_regions(s, e, cb, first);
+    else
+        cb(s, e);
+}
+
+/*
+ * Given an input physical address range, check if this range is overlapping
+ * with the existing reserved memory regions defined in bootinfo.
+ * Return true if the input physical address range is overlapping with any
+ * existing reserved memory regions, otherwise false.
+ */
+bool __init check_reserved_regions_overlap(paddr_t region_start,
+                                           paddr_t region_size)
+{
+    const struct membanks *mem_banks[] = {
+        bootinfo_get_reserved_mem(),
+#ifdef CONFIG_ACPI
+        bootinfo_get_acpi(),
+#endif
+#ifdef CONFIG_STATIC_SHM
+        bootinfo_get_shmem(),
+#endif
+    };
+    unsigned int i;
+
+    /*
+     * Check if input region is overlapping with reserved memory banks or
+     * ACPI EfiACPIReclaimMemory (when ACPI feature is enabled) or static
+     * shared memory banks (when static shared memory feature is enabled)
+     */
+    for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ )
+        if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) )
+            return true;
+
+    /* Check if input region is overlapping with bootmodules */
+    if ( bootmodules_overlap_check(&bootinfo.modules,
+                                   region_start, region_size) )
+        return true;
+
+    return false;
+}
+
+struct bootmodule __init *add_boot_module(bootmodule_kind kind,
+                                          paddr_t start, paddr_t size,
+                                          bool domU)
+{
+    struct bootmodules *mods = &bootinfo.modules;
+    struct bootmodule *mod;
+    unsigned int i;
+
+    if ( mods->nr_mods == MAX_MODULES )
+    {
+        printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" (too many)\n",
+               boot_module_kind_as_string(kind), start, start + size);
+        return NULL;
+    }
+
+    if ( check_reserved_regions_overlap(start, size) )
+        return NULL;
+
+    for ( i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && mod->start == start )
+        {
+            if ( !domU )
+                mod->domU = false;
+            return mod;
+        }
+    }
+
+    mod = &mods->module[mods->nr_mods++];
+    mod->kind = kind;
+    mod->start = start;
+    mod->size = size;
+    mod->domU = domU;
+
+    return mod;
+}
+
+/*
+ * boot_module_find_by_kind can only be used to return Xen modules (e.g
+ * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest
+ * modules.
+ */
+struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
+{
+    struct bootmodules *mods = &bootinfo.modules;
+    struct bootmodule *mod;
+    int i;
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && !mod->domU )
+            return mod;
+    }
+    return NULL;
+}
+
+void __init add_boot_cmdline(const char *name, const char *cmdline,
+                             bootmodule_kind kind, paddr_t start, bool domU)
+{
+    struct bootcmdlines *cmds = &bootinfo.cmdlines;
+    struct bootcmdline *cmd;
+
+    if ( cmds->nr_mods == MAX_MODULES )
+    {
+        printk("Ignoring %s cmdline (too many)\n", name);
+        return;
+    }
+
+    cmd = &cmds->cmdline[cmds->nr_mods++];
+    cmd->kind = kind;
+    cmd->domU = domU;
+    cmd->start = start;
+
+    ASSERT(strlen(name) <= DT_MAX_NAME);
+    safe_strcpy(cmd->dt_name, name);
+
+    if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE )
+        panic("module %s command line too long\n", name);
+    safe_strcpy(cmd->cmdline, cmdline);
+}
+
+/*
+ * boot_cmdline_find_by_kind can only be used to return Xen modules (e.g
+ * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest
+ * modules.
+ */
+struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
+{
+    struct bootcmdlines *cmds = &bootinfo.cmdlines;
+    struct bootcmdline *cmd;
+    int i;
+
+    for ( i = 0 ; i < cmds->nr_mods ; i++ )
+    {
+        cmd = &cmds->cmdline[i];
+        if ( cmd->kind == kind && !cmd->domU )
+            return cmd;
+    }
+    return NULL;
+}
+
+struct bootcmdline * __init boot_cmdline_find_by_name(const char *name)
+{
+    struct bootcmdlines *mods = &bootinfo.cmdlines;
+    struct bootcmdline *mod;
+    unsigned int i;
+
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->cmdline[i];
+        if ( strcmp(mod->dt_name, name) == 0 )
+            return mod;
+    }
+    return NULL;
+}
+
+struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind,
+                                                             paddr_t start)
+{
+    struct bootmodules *mods = &bootinfo.modules;
+    struct bootmodule *mod;
+    unsigned int i;
+
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && mod->start == start )
+            return mod;
+    }
+    return NULL;
+}
+
+/*
+ * Return the end of the non-module region starting at s. In other
+ * words return s the start of the next modules after s.
+ *
+ * On input *end is the end of the region which should be considered
+ * and it is updated to reflect the end of the module, clipped to the
+ * end of the region if it would run over.
+ */
+static paddr_t __init next_module(paddr_t s, paddr_t *end)
+{
+    struct bootmodules *mi = &bootinfo.modules;
+    paddr_t lowest = ~(paddr_t)0;
+    int i;
+
+    for ( i = 0; i < mi->nr_mods; i++ )
+    {
+        paddr_t mod_s = mi->module[i].start;
+        paddr_t mod_e = mod_s + mi->module[i].size;
+
+        if ( !mi->module[i].size )
+            continue;
+
+        if ( mod_s < s )
+            continue;
+        if ( mod_s > lowest )
+            continue;
+        if ( mod_s > *end )
+            continue;
+        lowest = mod_s;
+        *end = min(*end, mod_e);
+    }
+    return lowest;
+}
+
+/*
+ * Populate the boot allocator.
+ * If a static heap was not provided by the admin, all the RAM but the
+ * following regions will be added:
+ *  - Modules (e.g., Xen, Kernel)
+ *  - Reserved regions
+ *  - Xenheap (CONFIG_SEPARATE_XENHEAP only)
+ * If a static heap was provided by the admin, populate the boot
+ * allocator with the corresponding regions only, but with Xenheap excluded
+ * on CONFIG_SEPARATE_XENHEAP.
+ */
+void __init populate_boot_allocator(void)
+{
+    unsigned int i;
+    const struct membanks *banks = bootinfo_get_mem();
+    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
+    paddr_t s, e;
+
+    if ( bootinfo.static_heap )
+    {
+        for ( i = 0 ; i < reserved_mem->nr_banks; i++ )
+        {
+            if ( reserved_mem->bank[i].type != MEMBANK_STATIC_HEAP )
+                continue;
+
+            s = reserved_mem->bank[i].start;
+            e = s + reserved_mem->bank[i].size;
+#ifdef CONFIG_SEPARATE_XENHEAP
+            /* Avoid the xenheap, note that the xenheap cannot across a bank */
+            if ( s <= mfn_to_maddr(directmap_mfn_start) &&
+                 e >= mfn_to_maddr(directmap_mfn_end) )
+            {
+                init_boot_pages(s, mfn_to_maddr(directmap_mfn_start));
+                init_boot_pages(mfn_to_maddr(directmap_mfn_end), e);
+            }
+            else
+#endif
+                init_boot_pages(s, e);
+        }
+
+        return;
+    }
+
+    for ( i = 0; i < banks->nr_banks; i++ )
+    {
+        const struct membank *bank = &banks->bank[i];
+        paddr_t bank_end = bank->start + bank->size;
+
+        s = bank->start;
+        while ( s < bank_end )
+        {
+            paddr_t n = bank_end;
+
+            e = next_module(s, &n);
+
+            if ( e == ~(paddr_t)0 )
+                e = n = bank_end;
+
+            /*
+             * Module in a RAM bank other than the one which we are
+             * not dealing with here.
+             */
+            if ( e > bank_end )
+                e = bank_end;
+
+#ifdef CONFIG_SEPARATE_XENHEAP
+            /* Avoid the xenheap */
+            if ( s < mfn_to_maddr(directmap_mfn_end) &&
+                 mfn_to_maddr(directmap_mfn_start) < e )
+            {
+                e = mfn_to_maddr(directmap_mfn_start);
+                n = mfn_to_maddr(directmap_mfn_end);
+            }
+#endif
+
+            fw_unreserved_regions(s, e, init_boot_pages, 0);
+            s = n;
+        }
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/device_tree.c b/xen/common/device-tree/device-tree.c
similarity index 100%
rename from xen/common/device_tree.c
rename to xen/common/device-tree/device-tree.c
diff --git a/xen/include/xen/bootfdt.h b/xen/include/xen/bootfdt.h
new file mode 100644
index 0000000000..c39428d5f5
--- /dev/null
+++ b/xen/include/xen/bootfdt.h
@@ -0,0 +1,195 @@
+#ifndef XEN_BOOTFDT_H
+#define XEN_BOOTFDT_H
+
+#include <xen/types.h>
+#include <xen/kernel.h>
+#include <xen/macros.h>
+
+#define MIN_FDT_ALIGN 8
+
+#define NR_MEM_BANKS 256
+#define NR_SHMEM_BANKS 32
+
+#define MAX_MODULES 32 /* Current maximum useful modules */
+
+typedef enum {
+    BOOTMOD_XEN,
+    BOOTMOD_FDT,
+    BOOTMOD_KERNEL,
+    BOOTMOD_RAMDISK,
+    BOOTMOD_XSM,
+    BOOTMOD_GUEST_DTB,
+    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,
+    /*
+     * The MEMBANK_FDT_RESVMEM type is used to indicate whether the memory
+     * bank is from the FDT reserve map.
+     */
+    MEMBANK_FDT_RESVMEM,
+};
+
+/* Indicates the maximum number of characters(\0 included) for shm_id */
+#define MAX_SHM_ID_LENGTH 16
+
+struct shmem_membank_extra {
+    char shm_id[MAX_SHM_ID_LENGTH];
+    unsigned int nr_shm_borrowers;
+};
+
+struct membank {
+    paddr_t start;
+    paddr_t size;
+    union {
+        enum membank_type type;
+#ifdef CONFIG_STATIC_SHM
+        struct shmem_membank_extra *shmem_extra;
+#endif
+    };
+};
+
+struct membanks {
+    __struct_group(membanks_hdr, common, ,
+        unsigned int nr_banks;
+        unsigned int max_banks;
+    );
+    struct membank bank[];
+};
+
+struct meminfo {
+    struct membanks_hdr common;
+    struct membank bank[NR_MEM_BANKS];
+};
+
+struct shared_meminfo {
+    struct membanks_hdr common;
+    struct membank bank[NR_SHMEM_BANKS];
+    struct shmem_membank_extra extra[NR_SHMEM_BANKS];
+};
+
+/*
+ * The domU flag is set for kernels and ramdisks of "xen,domain" nodes.
+ * The purpose of the domU flag is to avoid getting confused in
+ * kernel_probe, where we try to guess which is the dom0 kernel and
+ * initrd to be compatible with all versions of the multiboot spec.
+ */
+#define BOOTMOD_MAX_CMDLINE 1024
+struct bootmodule {
+    bootmodule_kind kind;
+    bool domU;
+    paddr_t start;
+    paddr_t size;
+};
+
+/* DT_MAX_NAME is the node name max length according the DT spec */
+#define DT_MAX_NAME 41
+struct bootcmdline {
+    bootmodule_kind kind;
+    bool domU;
+    paddr_t start;
+    char dt_name[DT_MAX_NAME];
+    char cmdline[BOOTMOD_MAX_CMDLINE];
+};
+
+struct bootmodules {
+    int nr_mods;
+    struct bootmodule module[MAX_MODULES];
+};
+
+struct bootcmdlines {
+    unsigned int nr_mods;
+    struct bootcmdline cmdline[MAX_MODULES];
+};
+
+struct bootinfo {
+    struct meminfo mem;
+    /* The reserved regions are only used when booting using Device-Tree */
+    struct meminfo reserved_mem;
+    struct bootmodules modules;
+    struct bootcmdlines cmdlines;
+#ifdef CONFIG_ACPI
+    struct meminfo acpi;
+#endif
+#ifdef CONFIG_STATIC_SHM
+    struct shared_meminfo shmem;
+#endif
+    bool static_heap;
+};
+
+#ifdef CONFIG_ACPI
+#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS,
+#else
+#define BOOTINFO_ACPI_INIT
+#endif
+
+#ifdef CONFIG_STATIC_SHM
+#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS,
+#else
+#define BOOTINFO_SHMEM_INIT
+#endif
+
+#define BOOTINFO_INIT                               \
+{                                                   \
+    .mem.common.max_banks = NR_MEM_BANKS,           \
+    .reserved_mem.common.max_banks = NR_MEM_BANKS,  \
+    BOOTINFO_ACPI_INIT                              \
+    BOOTINFO_SHMEM_INIT                             \
+}
+
+extern struct bootinfo bootinfo;
+
+void populate_boot_allocator(void);
+
+size_t boot_fdt_info(const void *fdt, paddr_t paddr);
+
+const char *boot_fdt_cmdline(const void *fdt);
+
+static inline struct membanks *bootinfo_get_reserved_mem(void)
+{
+    return container_of(&bootinfo.reserved_mem.common, struct membanks, common);
+}
+
+static inline struct membanks *bootinfo_get_mem(void)
+{
+    return container_of(&bootinfo.mem.common, struct membanks, common);
+}
+
+#ifdef CONFIG_ACPI
+static inline struct membanks *bootinfo_get_acpi(void)
+{
+    return container_of(&bootinfo.acpi.common, struct membanks, common);
+}
+#endif
+
+#ifdef CONFIG_STATIC_SHM
+static inline struct membanks *bootinfo_get_shmem(void)
+{
+    return container_of(&bootinfo.shmem.common, struct membanks, common);
+}
+
+static inline struct shmem_membank_extra *bootinfo_get_shmem_extra(void)
+{
+    return bootinfo.shmem.extra;
+}
+#endif
+
+#endif /* XEN_BOOTFDT_H */
-- 
2.45.2
Re: [PATCH v2 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common
Posted by Nicola Vetrini 3 months, 2 weeks ago
On 2024-08-06 13:41, Oleksii Kurochko wrote:
> From: Shawn Anastasio <sanastasio@raptorengineering.com>
> 
> Arm's setup.c contains a collection of functions for parsing memory map
> and other boot information from a device tree. Since these routines are
> generally useful on any architecture that supports device tree booting,
> move them into xen/common/device-tree.
> 
> Also, common/device_tree.c has been moved to the device-tree folder 
> with
> the corresponding updates to common/Makefile and 
> common/device-tree/Makefile.
> 
> Mentioning of arm32 is changed to CONFIG_SEPARATE_XENHEAP in comparison 
> with
> original ARM's code as now it is moved in common code.
> 

Hi,

chiming in to this thread to note that fw_unreserved_regions is probably 
a leftover from this commit that ought to be moved to bootdft.h, as it 
generates a MISRA C Rule 8.4 violation [1] (non-blocking).

I made a tentative patch here [2], but not all builds are passing.

[1] 
https://saas.eclairit.com:3787/fs/var/local/eclair/xen-project.ecdf/xen-project/xen/ECLAIR_normal/staging/ARM64/7520607251/PROJECT.ecd;/by_service/MC3R1.R8.4.html

[2] 
https://gitlab.com/xen-project/people/bugseng/xen/-/commits/MC3R1.R8.4

> Suggested-by: Julien Grall <julien@xen.org>
> Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
> Acked-by: Julien Grall <jgrall@amazon.com>
> ---
> Changes in V9:
>  - rename xen/common/device_tree.c to xen/common/device-tree.c
>  - update MAINTAINERS file: drop xen/common/device_tree.c from it.
> ---
> Changes in V8:
>  - add the version of Xen from which bootinfo.c was derived from.
>  - update the commit message.
>  - add Acked-by: Julien Grall <jgrall@amazon.com>.
> ---
> Changes in V7:
>  - move obj-$(CONFIG_HAS_DEVICE_TREE) += device-tree/ to proper place 
> in common/Makefile.
>  - rename macros __XEN_BOOTFDT_H__ to XEN_BOOTFDT_H to not violate 
> MISRA rule 21.1.
>  - drop definition of "#define MAX_FDT_SIZE SZ_2M" in xen/bootfdt.h as 
> it is expected to
>    be arch-specific. Back "#define MAX_FDT_SIZE SZ_2M" to arm/setup.h 
> where it was before
>    these changes.
>  - git mv xen/common/device_tree.c xen/common/device-tree/ and update 
> correspondingly
>    Makefiles of common/ and common/device-tree
>  - update the commit message
> ---
> Changes in V6:
>  - update the version of the patch to v6.
> ---
> Changes in V5:
>  - After rebase the Shawn's patch v4 on top of current staging the 
> following
>    was done:
>    - add xen/include/xen/bootfdt.h to MAINTAINERS file.
>    - drop message "Early device tree parsing and".
>    - After rebase on top of the current staging the following changes 
> were done:
>      - init bootinfo variable in <common/device-tree/bootinfo.c> with 
> BOOTINFO_INIT;
>      - update the code of dt_unreserved_regions():
>          CONFIG_STATIC_SHM related changes and getting of reserved_mem
>          bootinfo_get_shmem()
>      - update the code of meminfo_overlap_check():
>          add check ( INVALID_PADDR == bank_start ) to if case.
>      - update the code of check_reserved_regions_overlap():
>          CONFIG_STATIC_SHM related changes.
>      - struct bootinfo was updated ( CONFIG_STATIC_SHM changes )
>      - add shared_meminfo ( because of CONFIG_STATIC_SHM )
>      - struct struct membanks was update with __struct group so 
> <xen/kernel> is
>        neeeded to be included in bootfdt.h
>      - move BOOTINFO_ACPI_INIT, BOOTINFO_SHMEM_INIT, BOOTINFO_INIT to 
> generic bootfdt.h
>      - bootinfo_get_reserved_mem(), bootinfo_get_mem(), 
> bootinfo_get_acpi(),
>        bootinfo_get_shmem() and bootinfo_get_shmem_extra() were moved 
> to xen/bootfdt.h
>    - s/arm32/CONFIG_SEPARATE_XENHEAP/
>    - add inclusion of <xen/macros.h> because there are function in 
> <xen/bootfdt.h> which
>      are using container_of().
>  ---
> Changes in v4:
>   - create new xen/include/bootinfo.h rather than relying on arch's
>     asm/setup.h to provide required definitions for bootinfo.c
>   - build bootinfo.c as .init.o
>   - clean up and sort bootinfo.c's #includes
>   - use CONFIG_SEPARATE_XENHEAP rather than CONFIG_ARM_32 to guard
>     xenheap-specific behavior of populate_boot_allocator
>   - (MAINTAINERS) include all of common/device-tree rather than just
>     bootinfo.c
> ---
>  MAINTAINERS                                   |   3 +-
>  xen/arch/arm/include/asm/setup.h              | 185 +------
>  xen/arch/arm/setup.c                          | 432 -----------------
>  xen/common/Makefile                           |   2 +-
>  xen/common/device-tree/Makefile               |   2 +
>  xen/common/device-tree/bootinfo.c             | 459 ++++++++++++++++++
>  .../device-tree.c}                            |   0
>  xen/include/xen/bootfdt.h                     | 195 ++++++++
>  8 files changed, 660 insertions(+), 618 deletions(-)
>  create mode 100644 xen/common/device-tree/Makefile
>  create mode 100644 xen/common/device-tree/bootinfo.c
>  rename xen/common/{device_tree.c => device-tree/device-tree.c} (100%)
>  create mode 100644 xen/include/xen/bootfdt.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7c524a8a93..89be48fdf9 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -291,9 +291,10 @@ M:	Bertrand Marquis <bertrand.marquis@arm.com>
>  M:	Michal Orzel <michal.orzel@amd.com>
>  S:	Supported
>  F:	xen/common/libfdt/
> -F:	xen/common/device_tree.c
> +F:	xen/common/device-tree/
>  F:	xen/common/dt-overlay.c
>  F:	xen/include/xen/libfdt/
> +F:	xen/include/xen/bootfdt.h
>  F:	xen/include/xen/device_tree.h
>  F:	xen/drivers/passthrough/device_tree.c
> 
> diff --git a/xen/arch/arm/include/asm/setup.h 
> b/xen/arch/arm/include/asm/setup.h
> index c34179da93..1748be29e5 100644
> --- a/xen/arch/arm/include/asm/setup.h
> +++ b/xen/arch/arm/include/asm/setup.h
> @@ -3,159 +3,11 @@
> 
>  #include <public/version.h>
>  #include <asm/p2m.h>
> +#include <xen/bootfdt.h>
>  #include <xen/device_tree.h>
> 
> -#define MIN_FDT_ALIGN 8
>  #define MAX_FDT_SIZE SZ_2M
> 
> -#define NR_MEM_BANKS 256
> -#define NR_SHMEM_BANKS 32
> -
> -#define MAX_MODULES 32 /* Current maximum useful modules */
> -
> -typedef enum {
> -    BOOTMOD_XEN,
> -    BOOTMOD_FDT,
> -    BOOTMOD_KERNEL,
> -    BOOTMOD_RAMDISK,
> -    BOOTMOD_XSM,
> -    BOOTMOD_GUEST_DTB,
> -    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,
> -    /*
> -     * The MEMBANK_FDT_RESVMEM type is used to indicate whether the 
> memory
> -     * bank is from the FDT reserve map.
> -     */
> -    MEMBANK_FDT_RESVMEM,
> -};
> -
> -/* Indicates the maximum number of characters(\0 included) for shm_id 
> */
> -#define MAX_SHM_ID_LENGTH 16
> -
> -struct shmem_membank_extra {
> -    char shm_id[MAX_SHM_ID_LENGTH];
> -    unsigned int nr_shm_borrowers;
> -};
> -
> -struct membank {
> -    paddr_t start;
> -    paddr_t size;
> -    union {
> -        enum membank_type type;
> -#ifdef CONFIG_STATIC_SHM
> -        struct shmem_membank_extra *shmem_extra;
> -#endif
> -    };
> -};
> -
> -struct membanks {
> -    __struct_group(membanks_hdr, common, ,
> -        unsigned int nr_banks;
> -        unsigned int max_banks;
> -    );
> -    struct membank bank[];
> -};
> -
> -struct meminfo {
> -    struct membanks_hdr common;
> -    struct membank bank[NR_MEM_BANKS];
> -};
> -
> -struct shared_meminfo {
> -    struct membanks_hdr common;
> -    struct membank bank[NR_SHMEM_BANKS];
> -    struct shmem_membank_extra extra[NR_SHMEM_BANKS];
> -};
> -
> -/*
> - * The domU flag is set for kernels and ramdisks of "xen,domain" 
> nodes.
> - * The purpose of the domU flag is to avoid getting confused in
> - * kernel_probe, where we try to guess which is the dom0 kernel and
> - * initrd to be compatible with all versions of the multiboot spec.
> - */
> -#define BOOTMOD_MAX_CMDLINE 1024
> -struct bootmodule {
> -    bootmodule_kind kind;
> -    bool domU;
> -    paddr_t start;
> -    paddr_t size;
> -};
> -
> -/* DT_MAX_NAME is the node name max length according the DT spec */
> -#define DT_MAX_NAME 41
> -struct bootcmdline {
> -    bootmodule_kind kind;
> -    bool domU;
> -    paddr_t start;
> -    char dt_name[DT_MAX_NAME];
> -    char cmdline[BOOTMOD_MAX_CMDLINE];
> -};
> -
> -struct bootmodules {
> -    int nr_mods;
> -    struct bootmodule module[MAX_MODULES];
> -};
> -
> -struct bootcmdlines {
> -    unsigned int nr_mods;
> -    struct bootcmdline cmdline[MAX_MODULES];
> -};
> -
> -struct bootinfo {
> -    struct meminfo mem;
> -    /* The reserved regions are only used when booting using 
> Device-Tree */
> -    struct meminfo reserved_mem;
> -    struct bootmodules modules;
> -    struct bootcmdlines cmdlines;
> -#ifdef CONFIG_ACPI
> -    struct meminfo acpi;
> -#endif
> -#ifdef CONFIG_STATIC_SHM
> -    struct shared_meminfo shmem;
> -#endif
> -    bool static_heap;
> -};
> -
> -#ifdef CONFIG_ACPI
> -#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS,
> -#else
> -#define BOOTINFO_ACPI_INIT
> -#endif
> -
> -#ifdef CONFIG_STATIC_SHM
> -#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS,
> -#else
> -#define BOOTINFO_SHMEM_INIT
> -#endif
> -
> -#define BOOTINFO_INIT                               \
> -{                                                   \
> -    .mem.common.max_banks = NR_MEM_BANKS,           \
> -    .reserved_mem.common.max_banks = NR_MEM_BANKS,  \
> -    BOOTINFO_ACPI_INIT                              \
> -    BOOTINFO_SHMEM_INIT                             \
> -}
> -
>  struct map_range_data
>  {
>      struct domain *d;
> @@ -167,39 +19,8 @@ struct map_range_data
>      struct rangeset *irq_ranges;
>  };
> 
> -extern struct bootinfo bootinfo;
> -
>  extern domid_t max_init_domid;
> 
> -static inline struct membanks *bootinfo_get_mem(void)
> -{
> -    return container_of(&bootinfo.mem.common, struct membanks, 
> common);
> -}
> -
> -static inline struct membanks *bootinfo_get_reserved_mem(void)
> -{
> -    return container_of(&bootinfo.reserved_mem.common, struct 
> membanks, common);
> -}
> -
> -#ifdef CONFIG_ACPI
> -static inline struct membanks *bootinfo_get_acpi(void)
> -{
> -    return container_of(&bootinfo.acpi.common, struct membanks, 
> common);
> -}
> -#endif
> -
> -#ifdef CONFIG_STATIC_SHM
> -static inline struct membanks *bootinfo_get_shmem(void)
> -{
> -    return container_of(&bootinfo.shmem.common, struct membanks, 
> common);
> -}
> -
> -static inline struct shmem_membank_extra 
> *bootinfo_get_shmem_extra(void)
> -{
> -    return bootinfo.shmem.extra;
> -}
> -#endif
> -
>  void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
> 
>  size_t estimate_efi_size(unsigned int mem_nr_banks);
> @@ -220,9 +41,6 @@ void fw_unreserved_regions(paddr_t s, paddr_t e,
>                             void (*cb)(paddr_t ps, paddr_t pe),
>                             unsigned int first);
> 
> -size_t boot_fdt_info(const void *fdt, paddr_t paddr);
> -const char *boot_fdt_cmdline(const void *fdt);
> -
>  bool check_reserved_regions_overlap(paddr_t region_start, paddr_t 
> region_size);
> 
>  struct bootmodule *add_boot_module(bootmodule_kind kind,
> @@ -237,7 +55,6 @@ struct bootcmdline * boot_cmdline_find_by_name(const 
> char *name);
>  const char *boot_module_kind_as_string(bootmodule_kind kind);
> 
>  void init_pdx(void);
> -void populate_boot_allocator(void);
>  void setup_mm(void);
> 
>  extern uint32_t hyp_traps_vector[];
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 0c2fdaceaf..cb2c0a16b8 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -48,8 +48,6 @@
>  #include <xsm/xsm.h>
>  #include <asm/acpi.h>
> 
> -struct bootinfo __initdata bootinfo = BOOTINFO_INIT;
> -
>  /*
>   * Sanitized version of cpuinfo containing only features available on 
> all
>   * cores (only on arm64 as there is no sanitization support on arm32).
> @@ -203,321 +201,6 @@ static void __init processor_id(void)
>      processor_setup();
>  }
> 
> -static void __init dt_unreserved_regions(paddr_t s, paddr_t e,
> -                                         void (*cb)(paddr_t ps, 
> paddr_t pe),
> -                                         unsigned int first)
> -{
> -    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
> -#ifdef CONFIG_STATIC_SHM
> -    const struct membanks *shmem = bootinfo_get_shmem();
> -    unsigned int offset;
> -#endif
> -    unsigned int i;
> -
> -    /*
> -     * i is the current bootmodule we are evaluating across all 
> possible
> -     * kinds.
> -     */
> -    for ( i = first; i < reserved_mem->nr_banks; i++ )
> -    {
> -        paddr_t r_s = reserved_mem->bank[i].start;
> -        paddr_t r_e = r_s + reserved_mem->bank[i].size;
> -
> -        if ( s < r_e && r_s < e )
> -        {
> -            dt_unreserved_regions(r_e, e, cb, i + 1);
> -            dt_unreserved_regions(s, r_s, cb, i + 1);
> -            return;
> -        }
> -    }
> -
> -#ifdef CONFIG_STATIC_SHM
> -    /*
> -     * When retrieving the corresponding shared memory addresses
> -     * below, we need to index the shmem->bank starting from 0, hence
> -     * we need to use i - reserved_mem->nr_banks.
> -    */
> -    offset = reserved_mem->nr_banks;
> -    for ( ; i - offset < shmem->nr_banks; i++ )
> -    {
> -        paddr_t r_s, r_e;
> -
> -        r_s = shmem->bank[i - offset].start;
> -
> -        /* Shared memory banks can contain INVALID_PADDR as start */
> -        if ( INVALID_PADDR == r_s )
> -            continue;
> -
> -        r_e = r_s + shmem->bank[i - offset].size;
> -
> -        if ( s < r_e && r_s < e )
> -        {
> -            dt_unreserved_regions(r_e, e, cb, i + 1);
> -            dt_unreserved_regions(s, r_s, cb, i + 1);
> -            return;
> -        }
> -    }
> -#endif
> -
> -    cb(s, e);
> -}
> -
> -/*
> - * TODO: '*_end' could be 0 if the bank/region is at the end of the 
> physical
> - * address space. This is for now not handled as it requires more 
> rework.
> - */
> -static bool __init meminfo_overlap_check(const struct membanks *mem,
> -                                         paddr_t region_start,
> -                                         paddr_t region_size)
> -{
> -    paddr_t bank_start = INVALID_PADDR, bank_end = 0;
> -    paddr_t region_end = region_start + region_size;
> -    unsigned int i, bank_num = mem->nr_banks;
> -
> -    for ( i = 0; i < bank_num; i++ )
> -    {
> -        bank_start = mem->bank[i].start;
> -        bank_end = bank_start + mem->bank[i].size;
> -
> -        if ( INVALID_PADDR == bank_start || region_end <= bank_start 
> ||
> -             region_start >= bank_end )
> -            continue;
> -        else
> -        {
> -            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping 
> with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
> -                   region_start, region_end, i, bank_start, bank_end);
> -            return true;
> -        }
> -    }
> -
> -    return false;
> -}
> -
> -/*
> - * TODO: '*_end' could be 0 if the module/region is at the end of the 
> physical
> - * address space. This is for now not handled as it requires more 
> rework.
> - */
> -static bool __init bootmodules_overlap_check(struct bootmodules 
> *bootmodules,
> -                                             paddr_t region_start,
> -                                             paddr_t region_size)
> -{
> -    paddr_t mod_start = INVALID_PADDR, mod_end = 0;
> -    paddr_t region_end = region_start + region_size;
> -    unsigned int i, mod_num = bootmodules->nr_mods;
> -
> -    for ( i = 0; i < mod_num; i++ )
> -    {
> -        mod_start = bootmodules->module[i].start;
> -        mod_end = mod_start + bootmodules->module[i].size;
> -
> -        if ( region_end <= mod_start || region_start >= mod_end )
> -            continue;
> -        else
> -        {
> -            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping 
> with mod[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
> -                   region_start, region_end, i, mod_start, mod_end);
> -            return true;
> -        }
> -    }
> -
> -    return false;
> -}
> -
> -void __init fw_unreserved_regions(paddr_t s, paddr_t e,
> -                                  void (*cb)(paddr_t ps, paddr_t pe),
> -                                  unsigned int first)
> -{
> -    if ( acpi_disabled )
> -        dt_unreserved_regions(s, e, cb, first);
> -    else
> -        cb(s, e);
> -}
> -
> -/*
> - * Given an input physical address range, check if this range is 
> overlapping
> - * with the existing reserved memory regions defined in bootinfo.
> - * Return true if the input physical address range is overlapping with 
> any
> - * existing reserved memory regions, otherwise false.
> - */
> -bool __init check_reserved_regions_overlap(paddr_t region_start,
> -                                           paddr_t region_size)
> -{
> -    const struct membanks *mem_banks[] = {
> -        bootinfo_get_reserved_mem(),
> -#ifdef CONFIG_ACPI
> -        bootinfo_get_acpi(),
> -#endif
> -#ifdef CONFIG_STATIC_SHM
> -        bootinfo_get_shmem(),
> -#endif
> -    };
> -    unsigned int i;
> -
> -    /*
> -     * Check if input region is overlapping with reserved memory banks 
> or
> -     * ACPI EfiACPIReclaimMemory (when ACPI feature is enabled) or 
> static
> -     * shared memory banks (when static shared memory feature is 
> enabled)
> -     */
> -    for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ )
> -        if ( meminfo_overlap_check(mem_banks[i], region_start, 
> region_size) )
> -            return true;
> -
> -    /* Check if input region is overlapping with bootmodules */
> -    if ( bootmodules_overlap_check(&bootinfo.modules,
> -                                   region_start, region_size) )
> -        return true;
> -
> -    return false;
> -}
> -
> -struct bootmodule __init *add_boot_module(bootmodule_kind kind,
> -                                          paddr_t start, paddr_t size,
> -                                          bool domU)
> -{
> -    struct bootmodules *mods = &bootinfo.modules;
> -    struct bootmodule *mod;
> -    unsigned int i;
> -
> -    if ( mods->nr_mods == MAX_MODULES )
> -    {
> -        printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" 
> (too many)\n",
> -               boot_module_kind_as_string(kind), start, start + size);
> -        return NULL;
> -    }
> -
> -    if ( check_reserved_regions_overlap(start, size) )
> -        return NULL;
> -
> -    for ( i = 0 ; i < mods->nr_mods ; i++ )
> -    {
> -        mod = &mods->module[i];
> -        if ( mod->kind == kind && mod->start == start )
> -        {
> -            if ( !domU )
> -                mod->domU = false;
> -            return mod;
> -        }
> -    }
> -
> -    mod = &mods->module[mods->nr_mods++];
> -    mod->kind = kind;
> -    mod->start = start;
> -    mod->size = size;
> -    mod->domU = domU;
> -
> -    return mod;
> -}
> -
> -/*
> - * boot_module_find_by_kind can only be used to return Xen modules 
> (e.g
> - * XSM, DTB) or Dom0 modules. This is not suitable for looking up 
> guest
> - * modules.
> - */
> -struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind 
> kind)
> -{
> -    struct bootmodules *mods = &bootinfo.modules;
> -    struct bootmodule *mod;
> -    int i;
> -    for (i = 0 ; i < mods->nr_mods ; i++ )
> -    {
> -        mod = &mods->module[i];
> -        if ( mod->kind == kind && !mod->domU )
> -            return mod;
> -    }
> -    return NULL;
> -}
> -
> -void __init add_boot_cmdline(const char *name, const char *cmdline,
> -                             bootmodule_kind kind, paddr_t start, bool 
> domU)
> -{
> -    struct bootcmdlines *cmds = &bootinfo.cmdlines;
> -    struct bootcmdline *cmd;
> -
> -    if ( cmds->nr_mods == MAX_MODULES )
> -    {
> -        printk("Ignoring %s cmdline (too many)\n", name);
> -        return;
> -    }
> -
> -    cmd = &cmds->cmdline[cmds->nr_mods++];
> -    cmd->kind = kind;
> -    cmd->domU = domU;
> -    cmd->start = start;
> -
> -    ASSERT(strlen(name) <= DT_MAX_NAME);
> -    safe_strcpy(cmd->dt_name, name);
> -
> -    if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE )
> -        panic("module %s command line too long\n", name);
> -    safe_strcpy(cmd->cmdline, cmdline);
> -}
> -
> -/*
> - * boot_cmdline_find_by_kind can only be used to return Xen modules 
> (e.g
> - * XSM, DTB) or Dom0 modules. This is not suitable for looking up 
> guest
> - * modules.
> - */
> -struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind 
> kind)
> -{
> -    struct bootcmdlines *cmds = &bootinfo.cmdlines;
> -    struct bootcmdline *cmd;
> -    int i;
> -
> -    for ( i = 0 ; i < cmds->nr_mods ; i++ )
> -    {
> -        cmd = &cmds->cmdline[i];
> -        if ( cmd->kind == kind && !cmd->domU )
> -            return cmd;
> -    }
> -    return NULL;
> -}
> -
> -struct bootcmdline * __init boot_cmdline_find_by_name(const char 
> *name)
> -{
> -    struct bootcmdlines *mods = &bootinfo.cmdlines;
> -    struct bootcmdline *mod;
> -    unsigned int i;
> -
> -    for (i = 0 ; i < mods->nr_mods ; i++ )
> -    {
> -        mod = &mods->cmdline[i];
> -        if ( strcmp(mod->dt_name, name) == 0 )
> -            return mod;
> -    }
> -    return NULL;
> -}
> -
> -struct bootmodule * __init 
> boot_module_find_by_addr_and_kind(bootmodule_kind kind,
> -                                                             paddr_t 
> start)
> -{
> -    struct bootmodules *mods = &bootinfo.modules;
> -    struct bootmodule *mod;
> -    unsigned int i;
> -
> -    for (i = 0 ; i < mods->nr_mods ; i++ )
> -    {
> -        mod = &mods->module[i];
> -        if ( mod->kind == kind && mod->start == start )
> -            return mod;
> -    }
> -    return NULL;
> -}
> -
> -const char * __init boot_module_kind_as_string(bootmodule_kind kind)
> -{
> -    switch ( kind )
> -    {
> -    case BOOTMOD_XEN:     return "Xen";
> -    case BOOTMOD_FDT:     return "Device Tree";
> -    case BOOTMOD_KERNEL:  return "Kernel";
> -    case BOOTMOD_RAMDISK: return "Ramdisk";
> -    case BOOTMOD_XSM:     return "XSM";
> -    case BOOTMOD_GUEST_DTB:     return "DTB";
> -    case BOOTMOD_UNKNOWN: return "Unknown";
> -    default: BUG();
> -    }
> -}
> -
>  void __init discard_initial_modules(void)
>  {
>      struct bootmodules *mi = &bootinfo.modules;
> @@ -556,40 +239,6 @@ static void * __init relocate_fdt(paddr_t 
> dtb_paddr, size_t dtb_size)
>      return fdt;
>  }
> 
> -/*
> - * Return the end of the non-module region starting at s. In other
> - * words return s the start of the next modules after s.
> - *
> - * On input *end is the end of the region which should be considered
> - * and it is updated to reflect the end of the module, clipped to the
> - * end of the region if it would run over.
> - */
> -static paddr_t __init next_module(paddr_t s, paddr_t *end)
> -{
> -    struct bootmodules *mi = &bootinfo.modules;
> -    paddr_t lowest = ~(paddr_t)0;
> -    int i;
> -
> -    for ( i = 0; i < mi->nr_mods; i++ )
> -    {
> -        paddr_t mod_s = mi->module[i].start;
> -        paddr_t mod_e = mod_s + mi->module[i].size;
> -
> -        if ( !mi->module[i].size )
> -            continue;
> -
> -        if ( mod_s < s )
> -            continue;
> -        if ( mod_s > lowest )
> -            continue;
> -        if ( mod_s > *end )
> -            continue;
> -        lowest = mod_s;
> -        *end = min(*end, mod_e);
> -    }
> -    return lowest;
> -}
> -
>  void __init init_pdx(void)
>  {
>      const struct membanks *mem = bootinfo_get_mem();
> @@ -635,87 +284,6 @@ void __init init_pdx(void)
>      }
>  }
> 
> -/*
> - * Populate the boot allocator.
> - * If a static heap was not provided by the admin, all the RAM but the
> - * following regions will be added:
> - *  - Modules (e.g., Xen, Kernel)
> - *  - Reserved regions
> - *  - Xenheap (arm32 only)
> - * If a static heap was provided by the admin, populate the boot
> - * allocator with the corresponding regions only, but with Xenheap 
> excluded
> - * on arm32.
> - */
> -void __init populate_boot_allocator(void)
> -{
> -    unsigned int i;
> -    const struct membanks *banks = bootinfo_get_mem();
> -    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
> -    paddr_t s, e;
> -
> -    if ( bootinfo.static_heap )
> -    {
> -        for ( i = 0 ; i < reserved_mem->nr_banks; i++ )
> -        {
> -            if ( reserved_mem->bank[i].type != MEMBANK_STATIC_HEAP )
> -                continue;
> -
> -            s = reserved_mem->bank[i].start;
> -            e = s + reserved_mem->bank[i].size;
> -#ifdef CONFIG_ARM_32
> -            /* Avoid the xenheap, note that the xenheap cannot across 
> a bank */
> -            if ( s <= mfn_to_maddr(directmap_mfn_start) &&
> -                 e >= mfn_to_maddr(directmap_mfn_end) )
> -            {
> -                init_boot_pages(s, mfn_to_maddr(directmap_mfn_start));
> -                init_boot_pages(mfn_to_maddr(directmap_mfn_end), e);
> -            }
> -            else
> -#endif
> -                init_boot_pages(s, e);
> -        }
> -
> -        return;
> -    }
> -
> -    for ( i = 0; i < banks->nr_banks; i++ )
> -    {
> -        const struct membank *bank = &banks->bank[i];
> -        paddr_t bank_end = bank->start + bank->size;
> -
> -        s = bank->start;
> -        while ( s < bank_end )
> -        {
> -            paddr_t n = bank_end;
> -
> -            e = next_module(s, &n);
> -
> -            if ( e == ~(paddr_t)0 )
> -                e = n = bank_end;
> -
> -            /*
> -             * Module in a RAM bank other than the one which we are
> -             * not dealing with here.
> -             */
> -            if ( e > bank_end )
> -                e = bank_end;
> -
> -#ifdef CONFIG_ARM_32
> -            /* Avoid the xenheap */
> -            if ( s < mfn_to_maddr(directmap_mfn_end) &&
> -                 mfn_to_maddr(directmap_mfn_start) < e )
> -            {
> -                e = mfn_to_maddr(directmap_mfn_start);
> -                n = mfn_to_maddr(directmap_mfn_end);
> -            }
> -#endif
> -
> -            fw_unreserved_regions(s, e, init_boot_pages, 0);
> -            s = n;
> -        }
> -    }
> -}
> -
>  size_t __read_mostly dcache_line_bytes;
> 
>  /* C entry point for boot CPU */
> diff --git a/xen/common/Makefile b/xen/common/Makefile
> index f12a474d40..7e66802a9e 100644
> --- a/xen/common/Makefile
> +++ b/xen/common/Makefile
> @@ -6,7 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
>  obj-$(CONFIG_CORE_PARKING) += core_parking.o
>  obj-y += cpu.o
>  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
> -obj-$(CONFIG_HAS_DEVICE_TREE) += device_tree.o
> +obj-$(CONFIG_HAS_DEVICE_TREE) += device-tree/
>  obj-$(CONFIG_IOREQ_SERVER) += dm.o
>  obj-y += domain.o
>  obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o
> diff --git a/xen/common/device-tree/Makefile 
> b/xen/common/device-tree/Makefile
> new file mode 100644
> index 0000000000..f813f7555f
> --- /dev/null
> +++ b/xen/common/device-tree/Makefile
> @@ -0,0 +1,2 @@
> +obj-y += bootinfo.init.o
> +obj-y += device-tree.o
> diff --git a/xen/common/device-tree/bootinfo.c 
> b/xen/common/device-tree/bootinfo.c
> new file mode 100644
> index 0000000000..f2e6a1145b
> --- /dev/null
> +++ b/xen/common/device-tree/bootinfo.c
> @@ -0,0 +1,459 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Derived from Xen 4.19's $xen/arch/arm/setup.c.
> + *
> + * bookkeeping routines.
> + *
> + * Tim Deegan <tim@xen.org>
> + * Copyright (c) 2011 Citrix Systems.
> + * Copyright (c) 2024 Raptor Engineering LLC
> + */
> +
> +#include <xen/acpi.h>
> +#include <xen/bootfdt.h>
> +#include <xen/bug.h>
> +#include <xen/device_tree.h>
> +#include <xen/init.h>
> +#include <xen/libfdt/libfdt-xen.h>
> +#include <xen/mm.h>
> +
> +struct bootinfo __initdata bootinfo = BOOTINFO_INIT;
> +
> +const char * __init boot_module_kind_as_string(bootmodule_kind kind)
> +{
> +    switch ( kind )
> +    {
> +    case BOOTMOD_XEN:     return "Xen";
> +    case BOOTMOD_FDT:     return "Device Tree";
> +    case BOOTMOD_KERNEL:  return "Kernel";
> +    case BOOTMOD_RAMDISK: return "Ramdisk";
> +    case BOOTMOD_XSM:     return "XSM";
> +    case BOOTMOD_GUEST_DTB:     return "DTB";
> +    case BOOTMOD_UNKNOWN: return "Unknown";
> +    default: BUG();
> +    }
> +}
> +
> +static void __init dt_unreserved_regions(paddr_t s, paddr_t e,
> +                                         void (*cb)(paddr_t ps, 
> paddr_t pe),
> +                                         unsigned int first)
> +{
> +    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
> +#ifdef CONFIG_STATIC_SHM
> +    const struct membanks *shmem = bootinfo_get_shmem();
> +    unsigned int offset;
> +#endif
> +    unsigned int i;
> +
> +    /*
> +     * i is the current bootmodule we are evaluating across all 
> possible
> +     * kinds.
> +     */
> +    for ( i = first; i < reserved_mem->nr_banks; i++ )
> +    {
> +        paddr_t r_s = reserved_mem->bank[i].start;
> +        paddr_t r_e = r_s + reserved_mem->bank[i].size;
> +
> +        if ( s < r_e && r_s < e )
> +        {
> +            dt_unreserved_regions(r_e, e, cb, i + 1);
> +            dt_unreserved_regions(s, r_s, cb, i + 1);
> +            return;
> +        }
> +    }
> +
> +#ifdef CONFIG_STATIC_SHM
> +    /*
> +     * When retrieving the corresponding shared memory addresses
> +     * below, we need to index the shmem->bank starting from 0, hence
> +     * we need to use i - reserved_mem->nr_banks.
> +    */
> +    offset = reserved_mem->nr_banks;
> +    for ( ; i - offset < shmem->nr_banks; i++ )
> +    {
> +        paddr_t r_s, r_e;
> +
> +        r_s = shmem->bank[i - offset].start;
> +
> +        /* Shared memory banks can contain INVALID_PADDR as start */
> +        if ( INVALID_PADDR == r_s )
> +            continue;
> +
> +        r_e = r_s + shmem->bank[i - offset].size;
> +
> +        if ( s < r_e && r_s < e )
> +        {
> +            dt_unreserved_regions(r_e, e, cb, i + 1);
> +            dt_unreserved_regions(s, r_s, cb, i + 1);
> +            return;
> +        }
> +    }
> +#endif
> +
> +    cb(s, e);
> +}
> +
> +/*
> + * TODO: '*_end' could be 0 if the bank/region is at the end of the 
> physical
> + * address space. This is for now not handled as it requires more 
> rework.
> + */
> +static bool __init meminfo_overlap_check(const struct membanks *mem,
> +                                         paddr_t region_start,
> +                                         paddr_t region_size)
> +{
> +    paddr_t bank_start = INVALID_PADDR, bank_end = 0;
> +    paddr_t region_end = region_start + region_size;
> +    unsigned int i, bank_num = mem->nr_banks;
> +
> +    for ( i = 0; i < bank_num; i++ )
> +    {
> +        bank_start = mem->bank[i].start;
> +        bank_end = bank_start + mem->bank[i].size;
> +
> +        if ( INVALID_PADDR == bank_start || region_end <= bank_start 
> ||
> +             region_start >= bank_end )
> +            continue;
> +        else
> +        {
> +            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping 
> with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
> +                   region_start, region_end, i, bank_start, bank_end);
> +            return true;
> +        }
> +    }
> +
> +    return false;
> +}
> +
> +/*
> + * TODO: '*_end' could be 0 if the module/region is at the end of the 
> physical
> + * address space. This is for now not handled as it requires more 
> rework.
> + */
> +static bool __init bootmodules_overlap_check(struct bootmodules 
> *bootmodules,
> +                                             paddr_t region_start,
> +                                             paddr_t region_size)
> +{
> +    paddr_t mod_start = INVALID_PADDR, mod_end = 0;
> +    paddr_t region_end = region_start + region_size;
> +    unsigned int i, mod_num = bootmodules->nr_mods;
> +
> +    for ( i = 0; i < mod_num; i++ )
> +    {
> +        mod_start = bootmodules->module[i].start;
> +        mod_end = mod_start + bootmodules->module[i].size;
> +
> +        if ( region_end <= mod_start || region_start >= mod_end )
> +            continue;
> +        else
> +        {
> +            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping 
> with mod[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
> +                   region_start, region_end, i, mod_start, mod_end);
> +            return true;
> +        }
> +    }
> +
> +    return false;
> +}
> +
> +void __init fw_unreserved_regions(paddr_t s, paddr_t e,
> +                                  void (*cb)(paddr_t ps, paddr_t pe),
> +                                  unsigned int first)
> +{
> +    if ( acpi_disabled )
> +        dt_unreserved_regions(s, e, cb, first);
> +    else
> +        cb(s, e);
> +}
> +
> +/*
> + * Given an input physical address range, check if this range is 
> overlapping
> + * with the existing reserved memory regions defined in bootinfo.
> + * Return true if the input physical address range is overlapping with 
> any
> + * existing reserved memory regions, otherwise false.
> + */
> +bool __init check_reserved_regions_overlap(paddr_t region_start,
> +                                           paddr_t region_size)
> +{
> +    const struct membanks *mem_banks[] = {
> +        bootinfo_get_reserved_mem(),
> +#ifdef CONFIG_ACPI
> +        bootinfo_get_acpi(),
> +#endif
> +#ifdef CONFIG_STATIC_SHM
> +        bootinfo_get_shmem(),
> +#endif
> +    };
> +    unsigned int i;
> +
> +    /*
> +     * Check if input region is overlapping with reserved memory banks 
> or
> +     * ACPI EfiACPIReclaimMemory (when ACPI feature is enabled) or 
> static
> +     * shared memory banks (when static shared memory feature is 
> enabled)
> +     */
> +    for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ )
> +        if ( meminfo_overlap_check(mem_banks[i], region_start, 
> region_size) )
> +            return true;
> +
> +    /* Check if input region is overlapping with bootmodules */
> +    if ( bootmodules_overlap_check(&bootinfo.modules,
> +                                   region_start, region_size) )
> +        return true;
> +
> +    return false;
> +}
> +
> +struct bootmodule __init *add_boot_module(bootmodule_kind kind,
> +                                          paddr_t start, paddr_t size,
> +                                          bool domU)
> +{
> +    struct bootmodules *mods = &bootinfo.modules;
> +    struct bootmodule *mod;
> +    unsigned int i;
> +
> +    if ( mods->nr_mods == MAX_MODULES )
> +    {
> +        printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" 
> (too many)\n",
> +               boot_module_kind_as_string(kind), start, start + size);
> +        return NULL;
> +    }
> +
> +    if ( check_reserved_regions_overlap(start, size) )
> +        return NULL;
> +
> +    for ( i = 0 ; i < mods->nr_mods ; i++ )
> +    {
> +        mod = &mods->module[i];
> +        if ( mod->kind == kind && mod->start == start )
> +        {
> +            if ( !domU )
> +                mod->domU = false;
> +            return mod;
> +        }
> +    }
> +
> +    mod = &mods->module[mods->nr_mods++];
> +    mod->kind = kind;
> +    mod->start = start;
> +    mod->size = size;
> +    mod->domU = domU;
> +
> +    return mod;
> +}
> +
> +/*
> + * boot_module_find_by_kind can only be used to return Xen modules 
> (e.g
> + * XSM, DTB) or Dom0 modules. This is not suitable for looking up 
> guest
> + * modules.
> + */
> +struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind 
> kind)
> +{
> +    struct bootmodules *mods = &bootinfo.modules;
> +    struct bootmodule *mod;
> +    int i;
> +    for (i = 0 ; i < mods->nr_mods ; i++ )
> +    {
> +        mod = &mods->module[i];
> +        if ( mod->kind == kind && !mod->domU )
> +            return mod;
> +    }
> +    return NULL;
> +}
> +
> +void __init add_boot_cmdline(const char *name, const char *cmdline,
> +                             bootmodule_kind kind, paddr_t start, bool 
> domU)
> +{
> +    struct bootcmdlines *cmds = &bootinfo.cmdlines;
> +    struct bootcmdline *cmd;
> +
> +    if ( cmds->nr_mods == MAX_MODULES )
> +    {
> +        printk("Ignoring %s cmdline (too many)\n", name);
> +        return;
> +    }
> +
> +    cmd = &cmds->cmdline[cmds->nr_mods++];
> +    cmd->kind = kind;
> +    cmd->domU = domU;
> +    cmd->start = start;
> +
> +    ASSERT(strlen(name) <= DT_MAX_NAME);
> +    safe_strcpy(cmd->dt_name, name);
> +
> +    if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE )
> +        panic("module %s command line too long\n", name);
> +    safe_strcpy(cmd->cmdline, cmdline);
> +}
> +
> +/*
> + * boot_cmdline_find_by_kind can only be used to return Xen modules 
> (e.g
> + * XSM, DTB) or Dom0 modules. This is not suitable for looking up 
> guest
> + * modules.
> + */
> +struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind 
> kind)
> +{
> +    struct bootcmdlines *cmds = &bootinfo.cmdlines;
> +    struct bootcmdline *cmd;
> +    int i;
> +
> +    for ( i = 0 ; i < cmds->nr_mods ; i++ )
> +    {
> +        cmd = &cmds->cmdline[i];
> +        if ( cmd->kind == kind && !cmd->domU )
> +            return cmd;
> +    }
> +    return NULL;
> +}
> +
> +struct bootcmdline * __init boot_cmdline_find_by_name(const char 
> *name)
> +{
> +    struct bootcmdlines *mods = &bootinfo.cmdlines;
> +    struct bootcmdline *mod;
> +    unsigned int i;
> +
> +    for (i = 0 ; i < mods->nr_mods ; i++ )
> +    {
> +        mod = &mods->cmdline[i];
> +        if ( strcmp(mod->dt_name, name) == 0 )
> +            return mod;
> +    }
> +    return NULL;
> +}
> +
> +struct bootmodule * __init 
> boot_module_find_by_addr_and_kind(bootmodule_kind kind,
> +                                                             paddr_t 
> start)
> +{
> +    struct bootmodules *mods = &bootinfo.modules;
> +    struct bootmodule *mod;
> +    unsigned int i;
> +
> +    for (i = 0 ; i < mods->nr_mods ; i++ )
> +    {
> +        mod = &mods->module[i];
> +        if ( mod->kind == kind && mod->start == start )
> +            return mod;
> +    }
> +    return NULL;
> +}
> +
> +/*
> + * Return the end of the non-module region starting at s. In other
> + * words return s the start of the next modules after s.
> + *
> + * On input *end is the end of the region which should be considered
> + * and it is updated to reflect the end of the module, clipped to the
> + * end of the region if it would run over.
> + */
> +static paddr_t __init next_module(paddr_t s, paddr_t *end)
> +{
> +    struct bootmodules *mi = &bootinfo.modules;
> +    paddr_t lowest = ~(paddr_t)0;
> +    int i;
> +
> +    for ( i = 0; i < mi->nr_mods; i++ )
> +    {
> +        paddr_t mod_s = mi->module[i].start;
> +        paddr_t mod_e = mod_s + mi->module[i].size;
> +
> +        if ( !mi->module[i].size )
> +            continue;
> +
> +        if ( mod_s < s )
> +            continue;
> +        if ( mod_s > lowest )
> +            continue;
> +        if ( mod_s > *end )
> +            continue;
> +        lowest = mod_s;
> +        *end = min(*end, mod_e);
> +    }
> +    return lowest;
> +}
> +
> +/*
> + * Populate the boot allocator.
> + * If a static heap was not provided by the admin, all the RAM but the
> + * following regions will be added:
> + *  - Modules (e.g., Xen, Kernel)
> + *  - Reserved regions
> + *  - Xenheap (CONFIG_SEPARATE_XENHEAP only)
> + * If a static heap was provided by the admin, populate the boot
> + * allocator with the corresponding regions only, but with Xenheap 
> excluded
> + * on CONFIG_SEPARATE_XENHEAP.
> + */
> +void __init populate_boot_allocator(void)
> +{
> +    unsigned int i;
> +    const struct membanks *banks = bootinfo_get_mem();
> +    const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
> +    paddr_t s, e;
> +
> +    if ( bootinfo.static_heap )
> +    {
> +        for ( i = 0 ; i < reserved_mem->nr_banks; i++ )
> +        {
> +            if ( reserved_mem->bank[i].type != MEMBANK_STATIC_HEAP )
> +                continue;
> +
> +            s = reserved_mem->bank[i].start;
> +            e = s + reserved_mem->bank[i].size;
> +#ifdef CONFIG_SEPARATE_XENHEAP
> +            /* Avoid the xenheap, note that the xenheap cannot across 
> a bank */
> +            if ( s <= mfn_to_maddr(directmap_mfn_start) &&
> +                 e >= mfn_to_maddr(directmap_mfn_end) )
> +            {
> +                init_boot_pages(s, mfn_to_maddr(directmap_mfn_start));
> +                init_boot_pages(mfn_to_maddr(directmap_mfn_end), e);
> +            }
> +            else
> +#endif
> +                init_boot_pages(s, e);
> +        }
> +
> +        return;
> +    }
> +
> +    for ( i = 0; i < banks->nr_banks; i++ )
> +    {
> +        const struct membank *bank = &banks->bank[i];
> +        paddr_t bank_end = bank->start + bank->size;
> +
> +        s = bank->start;
> +        while ( s < bank_end )
> +        {
> +            paddr_t n = bank_end;
> +
> +            e = next_module(s, &n);
> +
> +            if ( e == ~(paddr_t)0 )
> +                e = n = bank_end;
> +
> +            /*
> +             * Module in a RAM bank other than the one which we are
> +             * not dealing with here.
> +             */
> +            if ( e > bank_end )
> +                e = bank_end;
> +
> +#ifdef CONFIG_SEPARATE_XENHEAP
> +            /* Avoid the xenheap */
> +            if ( s < mfn_to_maddr(directmap_mfn_end) &&
> +                 mfn_to_maddr(directmap_mfn_start) < e )
> +            {
> +                e = mfn_to_maddr(directmap_mfn_start);
> +                n = mfn_to_maddr(directmap_mfn_end);
> +            }
> +#endif
> +
> +            fw_unreserved_regions(s, e, init_boot_pages, 0);
> +            s = n;
> +        }
> +    }
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/common/device_tree.c 
> b/xen/common/device-tree/device-tree.c
> similarity index 100%
> rename from xen/common/device_tree.c
> rename to xen/common/device-tree/device-tree.c
> diff --git a/xen/include/xen/bootfdt.h b/xen/include/xen/bootfdt.h
> new file mode 100644
> index 0000000000..c39428d5f5
> --- /dev/null
> +++ b/xen/include/xen/bootfdt.h
> @@ -0,0 +1,195 @@
> +#ifndef XEN_BOOTFDT_H
> +#define XEN_BOOTFDT_H
> +
> +#include <xen/types.h>
> +#include <xen/kernel.h>
> +#include <xen/macros.h>
> +
> +#define MIN_FDT_ALIGN 8
> +
> +#define NR_MEM_BANKS 256
> +#define NR_SHMEM_BANKS 32
> +
> +#define MAX_MODULES 32 /* Current maximum useful modules */
> +
> +typedef enum {
> +    BOOTMOD_XEN,
> +    BOOTMOD_FDT,
> +    BOOTMOD_KERNEL,
> +    BOOTMOD_RAMDISK,
> +    BOOTMOD_XSM,
> +    BOOTMOD_GUEST_DTB,
> +    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,
> +    /*
> +     * The MEMBANK_FDT_RESVMEM type is used to indicate whether the 
> memory
> +     * bank is from the FDT reserve map.
> +     */
> +    MEMBANK_FDT_RESVMEM,
> +};
> +
> +/* Indicates the maximum number of characters(\0 included) for shm_id 
> */
> +#define MAX_SHM_ID_LENGTH 16
> +
> +struct shmem_membank_extra {
> +    char shm_id[MAX_SHM_ID_LENGTH];
> +    unsigned int nr_shm_borrowers;
> +};
> +
> +struct membank {
> +    paddr_t start;
> +    paddr_t size;
> +    union {
> +        enum membank_type type;
> +#ifdef CONFIG_STATIC_SHM
> +        struct shmem_membank_extra *shmem_extra;
> +#endif
> +    };
> +};
> +
> +struct membanks {
> +    __struct_group(membanks_hdr, common, ,
> +        unsigned int nr_banks;
> +        unsigned int max_banks;
> +    );
> +    struct membank bank[];
> +};
> +
> +struct meminfo {
> +    struct membanks_hdr common;
> +    struct membank bank[NR_MEM_BANKS];
> +};
> +
> +struct shared_meminfo {
> +    struct membanks_hdr common;
> +    struct membank bank[NR_SHMEM_BANKS];
> +    struct shmem_membank_extra extra[NR_SHMEM_BANKS];
> +};
> +
> +/*
> + * The domU flag is set for kernels and ramdisks of "xen,domain" 
> nodes.
> + * The purpose of the domU flag is to avoid getting confused in
> + * kernel_probe, where we try to guess which is the dom0 kernel and
> + * initrd to be compatible with all versions of the multiboot spec.
> + */
> +#define BOOTMOD_MAX_CMDLINE 1024
> +struct bootmodule {
> +    bootmodule_kind kind;
> +    bool domU;
> +    paddr_t start;
> +    paddr_t size;
> +};
> +
> +/* DT_MAX_NAME is the node name max length according the DT spec */
> +#define DT_MAX_NAME 41
> +struct bootcmdline {
> +    bootmodule_kind kind;
> +    bool domU;
> +    paddr_t start;
> +    char dt_name[DT_MAX_NAME];
> +    char cmdline[BOOTMOD_MAX_CMDLINE];
> +};
> +
> +struct bootmodules {
> +    int nr_mods;
> +    struct bootmodule module[MAX_MODULES];
> +};
> +
> +struct bootcmdlines {
> +    unsigned int nr_mods;
> +    struct bootcmdline cmdline[MAX_MODULES];
> +};
> +
> +struct bootinfo {
> +    struct meminfo mem;
> +    /* The reserved regions are only used when booting using 
> Device-Tree */
> +    struct meminfo reserved_mem;
> +    struct bootmodules modules;
> +    struct bootcmdlines cmdlines;
> +#ifdef CONFIG_ACPI
> +    struct meminfo acpi;
> +#endif
> +#ifdef CONFIG_STATIC_SHM
> +    struct shared_meminfo shmem;
> +#endif
> +    bool static_heap;
> +};
> +
> +#ifdef CONFIG_ACPI
> +#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS,
> +#else
> +#define BOOTINFO_ACPI_INIT
> +#endif
> +
> +#ifdef CONFIG_STATIC_SHM
> +#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS,
> +#else
> +#define BOOTINFO_SHMEM_INIT
> +#endif
> +
> +#define BOOTINFO_INIT                               \
> +{                                                   \
> +    .mem.common.max_banks = NR_MEM_BANKS,           \
> +    .reserved_mem.common.max_banks = NR_MEM_BANKS,  \
> +    BOOTINFO_ACPI_INIT                              \
> +    BOOTINFO_SHMEM_INIT                             \
> +}
> +
> +extern struct bootinfo bootinfo;
> +
> +void populate_boot_allocator(void);
> +
> +size_t boot_fdt_info(const void *fdt, paddr_t paddr);
> +
> +const char *boot_fdt_cmdline(const void *fdt);
> +
> +static inline struct membanks *bootinfo_get_reserved_mem(void)
> +{
> +    return container_of(&bootinfo.reserved_mem.common, struct 
> membanks, common);
> +}
> +
> +static inline struct membanks *bootinfo_get_mem(void)
> +{
> +    return container_of(&bootinfo.mem.common, struct membanks, 
> common);
> +}
> +
> +#ifdef CONFIG_ACPI
> +static inline struct membanks *bootinfo_get_acpi(void)
> +{
> +    return container_of(&bootinfo.acpi.common, struct membanks, 
> common);
> +}
> +#endif
> +
> +#ifdef CONFIG_STATIC_SHM
> +static inline struct membanks *bootinfo_get_shmem(void)
> +{
> +    return container_of(&bootinfo.shmem.common, struct membanks, 
> common);
> +}
> +
> +static inline struct shmem_membank_extra 
> *bootinfo_get_shmem_extra(void)
> +{
> +    return bootinfo.shmem.extra;
> +}
> +#endif
> +
> +#endif /* XEN_BOOTFDT_H */

-- 
Nicola Vetrini, BSc
Software Engineer, BUGSENG srl (https://bugseng.com)