All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/2] Common device tree stuff
@ 2024-08-05 11:33 Oleksii Kurochko
  2024-08-05 11:33 ` [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common Oleksii Kurochko
  2024-08-05 11:33 ` [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c " Oleksii Kurochko
  0 siblings, 2 replies; 7+ messages in thread
From: Oleksii Kurochko @ 2024-08-05 11:33 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Andrew Cooper, Jan Beulich, Julien Grall,
	Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Daniel P. Smith

The current patch series introduces the common device tree functions
between several architectures: Arm, PPC, RISC-V.

Originally these patches were a part of Shawn's patch series [1].
At that moment it was v4 version of this patches.

After RISC-V started to need this changes these patches have been
rebased on top of the current staging with addional updates after
rebase.
For some time, these patches from v5 to v7 version were the part of
the patch series [2] but not to block almost ready patches for merging
it was decided to move them to separate patch series.

[1]
https://lore.kernel.org/xen-devel/cover.1712893887.git.sanastasio@raptorengineering.com/

[2]
https://lore.kernel.org/xen-devel/cover.1721834549.git.oleksii.kurochko@gmail.com/

Shawn Anastasio (2):
  xen/device-tree: Move Arm's setup.c bootinfo functions to common
  xen/common: Move Arm's bootfdt.c to common

 MAINTAINERS                             |    2 +
 xen/arch/arm/Makefile                   |    1 -
 xen/arch/arm/bootfdt.c                  |  622 -------
 xen/arch/arm/include/asm/setup.h        |  198 +-
 xen/arch/arm/include/asm/static-shmem.h |    9 -
 xen/arch/arm/setup.c                    |  432 -----
 xen/common/Makefile                     |    2 +-
 xen/common/device-tree/Makefile         |    3 +
 xen/common/device-tree/bootfdt.c        |  635 +++++++
 xen/common/device-tree/bootinfo.c       |  459 +++++
 xen/common/device-tree/device_tree.c    | 2253 +++++++++++++++++++++++
 xen/common/device_tree.c                | 2253 -----------------------
 xen/include/xen/bootfdt.h               |  209 +++
 13 files changed, 3563 insertions(+), 3515 deletions(-)
 delete mode 100644 xen/arch/arm/bootfdt.c
 create mode 100644 xen/common/device-tree/Makefile
 create mode 100644 xen/common/device-tree/bootfdt.c
 create mode 100644 xen/common/device-tree/bootinfo.c
 create mode 100644 xen/common/device-tree/device_tree.c
 delete mode 100644 xen/common/device_tree.c
 create mode 100644 xen/include/xen/bootfdt.h

-- 
2.45.2



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common
  2024-08-05 11:33 [PATCH v1 0/2] Common device tree stuff Oleksii Kurochko
@ 2024-08-05 11:33 ` Oleksii Kurochko
  2024-08-05 11:58   ` Jan Beulich
  2024-08-05 11:33 ` [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c " Oleksii Kurochko
  1 sibling, 1 reply; 7+ messages in thread
From: Oleksii Kurochko @ 2024-08-05 11:33 UTC (permalink / raw)
  To: xen-devel
  Cc: Shawn Anastasio, Andrew Cooper, Jan Beulich, Julien Grall,
	Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Daniel P. Smith, Oleksii Kurochko,
	Julien Grall

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 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                          |    2 +
 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 ++++++
 xen/common/device-tree/device_tree.c | 2253 ++++++++++++++++++++++++++
 xen/common/device_tree.c             | 2253 --------------------------
 xen/include/xen/bootfdt.h            |  195 +++
 9 files changed, 2913 insertions(+), 2870 deletions(-)
 create mode 100644 xen/common/device-tree/Makefile
 create mode 100644 xen/common/device-tree/bootinfo.c
 create mode 100644 xen/common/device-tree/device_tree.c
 delete mode 100644 xen/common/device_tree.c
 create mode 100644 xen/include/xen/bootfdt.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7c524a8a93..96adf60671 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -291,9 +291,11 @@ 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/
 F:	xen/common/device_tree.c
 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..da892dd55d
--- /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/device_tree.c b/xen/common/device-tree/device_tree.c
new file mode 100644
index 0000000000..8d1017a49d
--- /dev/null
+++ b/xen/common/device-tree/device_tree.c
@@ -0,0 +1,2253 @@
+/*
+ * Device Tree
+ *
+ * Copyright (C) 2012 Citrix Systems, Inc.
+ * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
+ * benh@kernel.crashing.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <xen/types.h>
+#include <xen/init.h>
+#include <xen/guest_access.h>
+#include <xen/device_tree.h>
+#include <xen/kernel.h>
+#include <xen/lib.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/mm.h>
+#include <xen/stdarg.h>
+#include <xen/string.h>
+#include <xen/cpumask.h>
+#include <xen/ctype.h>
+#include <asm/setup.h>
+#include <xen/err.h>
+
+const void *device_tree_flattened;
+dt_irq_xlate_func dt_irq_xlate;
+/* Host device tree */
+struct dt_device_node *dt_host;
+/* Interrupt controller node*/
+const struct dt_device_node *dt_interrupt_controller;
+DEFINE_RWLOCK(dt_host_lock);
+
+/**
+ * struct dt_alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct dt_alias_prop {
+    struct list_head link;
+    const char *alias;
+    struct dt_device_node *np;
+    int id;
+    char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
+#ifdef CONFIG_DEVICE_TREE_DEBUG
+static void dt_dump_addr(const char *s, const __be32 *addr, int na)
+{
+    dt_dprintk("%s", s);
+    while ( na-- )
+        dt_dprintk(" %08x", be32_to_cpu(*(addr++)));
+    dt_dprintk("\n");
+}
+#else
+static void dt_dump_addr(const char *s, const __be32 *addr, int na) { }
+#endif
+
+#define DT_BAD_ADDR ((u64)-1)
+
+/* Max address size we deal with */
+#define DT_MAX_ADDR_CELLS 4
+#define DT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= DT_MAX_ADDR_CELLS)
+#define DT_CHECK_COUNTS(na, ns) (DT_CHECK_ADDR_COUNT(na) && (ns) > 0)
+
+/* Callbacks for bus specific translators */
+struct dt_bus
+{
+    const char *name;
+    const char *addresses;
+    bool (*match)(const struct dt_device_node *node);
+    void (*count_cells)(const struct dt_device_node *child,
+                        int *addrc, int *sizec);
+    u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
+    int (*translate)(__be32 *addr, u64 offset, int na);
+    unsigned int (*get_flags)(const __be32 *addr);
+};
+
+void dt_get_range(const __be32 **cellp, const struct dt_device_node *np,
+                  u64 *address, u64 *size)
+{
+    *address = dt_next_cell(dt_n_addr_cells(np), cellp);
+    *size = dt_next_cell(dt_n_size_cells(np), cellp);
+}
+
+void dt_set_cell(__be32 **cellp, int size, u64 val)
+{
+    int cells = size;
+
+    while ( size-- )
+    {
+        (*cellp)[size] = cpu_to_fdt32(val);
+        val >>= 32;
+    }
+
+    (*cellp) += cells;
+}
+
+void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
+                  u64 address, u64 size)
+{
+    dt_set_cell(cellp, dt_n_addr_cells(np), address);
+    dt_set_cell(cellp, dt_n_size_cells(np), size);
+}
+
+void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
+                        u64 address, u64 size)
+{
+    dt_set_cell(cellp, addrcells, address);
+    dt_set_cell(cellp, sizecells, size);
+}
+
+static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+                                       unsigned long align)
+{
+    void *res;
+
+    *mem = ROUNDUP(*mem, align);
+    res = (void *)*mem;
+    *mem += size;
+
+    return res;
+}
+
+/* Find a property with a given name for a given node and return it. */
+const struct dt_property *dt_find_property(const struct dt_device_node *np,
+                                           const char *name, u32 *lenp)
+{
+    const struct dt_property *pp;
+
+    if ( !np )
+        return NULL;
+
+    for ( pp = np->properties; pp; pp = pp->next )
+    {
+        if ( dt_prop_cmp(pp->name, name) == 0 )
+        {
+            if ( lenp )
+                *lenp = pp->length;
+            break;
+        }
+    }
+
+    return pp;
+}
+
+const void *dt_get_property(const struct dt_device_node *np,
+                            const char *name, u32 *lenp)
+{
+    const struct dt_property *pp = dt_find_property(np, name, lenp);
+
+    return pp ? pp->value : NULL;
+}
+
+bool dt_property_read_u32(const struct dt_device_node *np,
+                          const char *name, u32 *out_value)
+{
+    u32 len;
+    const __be32 *val;
+
+    val = dt_get_property(np, name, &len);
+    if ( !val || len < sizeof(*out_value) )
+        return 0;
+
+    *out_value = be32_to_cpup(val);
+
+    return 1;
+}
+
+
+bool dt_property_read_u64(const struct dt_device_node *np,
+                          const char *name, u64 *out_value)
+{
+    u32 len;
+    const __be32 *val;
+
+    val = dt_get_property(np, name, &len);
+    if ( !val || len < sizeof(*out_value) )
+        return 0;
+
+    *out_value = dt_read_number(val, 2);
+
+    return 1;
+}
+int dt_property_read_string(const struct dt_device_node *np,
+                            const char *propname, const char **out_string)
+{
+    const struct dt_property *pp = dt_find_property(np, propname, NULL);
+
+    if ( !pp )
+        return -EINVAL;
+    if ( !pp->length )
+        return -ENODATA;
+    if ( strnlen(pp->value, pp->length) >= pp->length )
+        return -EILSEQ;
+
+    *out_string = pp->value;
+
+    return 0;
+}
+
+/**
+ * dt_find_property_value_of_size
+ *
+ * @np:     device node from which the property value is to be read.
+ * @propname:   name of the property to be searched.
+ * @min:    minimum allowed length of property value
+ * @max:    maximum allowed length of property value (0 means unlimited)
+ * @len:    if !=NULL, actual length is written to here
+ *
+ * Search for a property in a device node and valid the requested size.
+ *
+ * Return: The property value on success, -EINVAL if the property does not
+ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data is too small or too large.
+ */
+static void *dt_find_property_value_of_size(const struct dt_device_node *np,
+                                            const char *propname, u32 min,
+                                            u32 max, size_t *len)
+{
+    const struct dt_property *prop = dt_find_property(np, propname, NULL);
+
+    if ( !prop )
+        return ERR_PTR(-EINVAL);
+    if ( !prop->value )
+        return ERR_PTR(-ENODATA);
+    if ( prop->length < min )
+        return ERR_PTR(-EOVERFLOW);
+    if ( max && prop->length > max )
+        return ERR_PTR(-EOVERFLOW);
+
+    if ( len )
+        *len = prop->length;
+
+    return prop->value;
+}
+
+int dt_property_read_variable_u32_array(const struct dt_device_node *np,
+                                        const char *propname, u32 *out_values,
+                                        size_t sz_min, size_t sz_max)
+{
+    size_t sz, count;
+    const __be32 *val = dt_find_property_value_of_size(np, propname,
+                        (sz_min * sizeof(*out_values)),
+                        (sz_max * sizeof(*out_values)),
+                        &sz);
+
+    if ( IS_ERR(val) )
+        return PTR_ERR(val);
+
+    if ( !sz_max )
+        sz = sz_min;
+    else
+        sz /= sizeof(*out_values);
+
+    count = sz;
+    while ( count-- )
+        *out_values++ = be32_to_cpup(val++);
+
+    return sz;
+}
+
+int dt_property_match_string(const struct dt_device_node *np,
+                             const char *propname, const char *string)
+{
+    const struct dt_property *dtprop = dt_find_property(np, propname, NULL);
+    size_t l;
+    int i;
+    const char *p, *end;
+
+    if ( !dtprop )
+        return -EINVAL;
+    if ( !dtprop->value )
+        return -ENODATA;
+
+    p = dtprop->value;
+    end = p + dtprop->length;
+
+    for ( i = 0; p < end; i++, p += l )
+    {
+        l = strnlen(p, end - p) + 1;
+        if ( p + l > end )
+            return -EILSEQ;
+        if ( strcmp(string, p) == 0 )
+            return i; /* Found it; return index */
+    }
+    return -ENODATA;
+}
+
+bool dt_device_is_compatible(const struct dt_device_node *device,
+                             const char *compat)
+{
+    const char* cp;
+    u32 cplen, l;
+
+    cp = dt_get_property(device, "compatible", &cplen);
+    if ( cp == NULL )
+        return 0;
+    while ( cplen > 0 )
+    {
+        if ( dt_compat_cmp(cp, compat) == 0 )
+            return 1;
+        l = strlen(cp) + 1;
+        cp += l;
+        cplen -= l;
+    }
+
+    return 0;
+}
+
+bool dt_machine_is_compatible(const char *compat)
+{
+    const struct dt_device_node *root;
+    bool rc = false;
+
+    root = dt_find_node_by_path("/");
+    if ( root )
+    {
+        rc = dt_device_is_compatible(root, compat);
+    }
+    return rc;
+}
+
+struct dt_device_node *dt_find_node_by_name(struct dt_device_node *from,
+                                            const char *name)
+{
+    struct dt_device_node *np;
+    struct dt_device_node *dt;
+
+    dt = from ? from->allnext : dt_host;
+    dt_for_each_device_node(dt, np)
+        if ( np->name && (dt_node_cmp(np->name, name) == 0) )
+            break;
+
+    return np;
+}
+
+struct dt_device_node *dt_find_node_by_type(struct dt_device_node *from,
+                                            const char *type)
+{
+    struct dt_device_node *np;
+    struct dt_device_node *dt;
+
+    dt = from ? from->allnext : dt_host;
+    dt_for_each_device_node(dt, np)
+        if ( np->type && (dt_node_cmp(np->type, type) == 0) )
+            break;
+
+    return np;
+}
+
+struct dt_device_node *dt_find_node_by_path_from(struct dt_device_node *from,
+                                                 const char *path)
+{
+    struct dt_device_node *np;
+
+    dt_for_each_device_node(from, np)
+        if ( np->full_name && (dt_node_cmp(np->full_name, path) == 0) )
+            break;
+
+    return np;
+}
+
+int dt_find_node_by_gpath(XEN_GUEST_HANDLE(char) u_path, uint32_t u_plen,
+                          struct dt_device_node **node)
+{
+    char *path;
+
+    path = safe_copy_string_from_guest(u_path, u_plen, PAGE_SIZE);
+    if ( IS_ERR(path) )
+        return PTR_ERR(path);
+
+    *node = dt_find_node_by_path(path);
+
+    xfree(path);
+
+    return (*node == NULL) ? -ESRCH : 0;
+}
+
+struct dt_device_node *dt_find_node_by_alias(const char *alias)
+{
+    const struct dt_alias_prop *app;
+
+    list_for_each_entry( app, &aliases_lookup, link )
+    {
+        if ( !strcmp(app->alias, alias) )
+            return app->np;
+    }
+
+    return NULL;
+}
+
+const struct dt_device_match *
+dt_match_node(const struct dt_device_match *matches,
+              const struct dt_device_node *node)
+{
+    if ( !matches )
+        return NULL;
+
+    while ( matches->path || matches->type ||
+            matches->compatible || matches->not_available || matches->prop )
+    {
+        bool match = true;
+
+        if ( matches->path )
+            match &= dt_node_path_is_equal(node, matches->path);
+
+        if ( matches->type )
+            match &= dt_device_type_is_equal(node, matches->type);
+
+        if ( matches->compatible )
+            match &= dt_device_is_compatible(node, matches->compatible);
+
+        if ( matches->not_available )
+            match &= !dt_device_is_available(node);
+
+        if ( matches->prop )
+            match &= dt_find_property(node, matches->prop, NULL) != NULL;
+
+        if ( match )
+            return matches;
+        matches++;
+    }
+
+    return NULL;
+}
+
+const struct dt_device_node *dt_get_parent(const struct dt_device_node *node)
+{
+    if ( !node )
+        return NULL;
+
+    return node->parent;
+}
+
+struct dt_device_node *
+dt_find_compatible_node(struct dt_device_node *from,
+                        const char *type,
+                        const char *compatible)
+{
+    struct dt_device_node *np;
+    struct dt_device_node *dt;
+
+    dt = from ? from->allnext : dt_host;
+    dt_for_each_device_node(dt, np)
+    {
+        if ( type
+             && !(np->type && (dt_node_cmp(np->type, type) == 0)) )
+            continue;
+        if ( dt_device_is_compatible(np, compatible) )
+            break;
+    }
+
+    return np;
+}
+
+struct dt_device_node *
+dt_find_matching_node(struct dt_device_node *from,
+                      const struct dt_device_match *matches)
+{
+    struct dt_device_node *np;
+    struct dt_device_node *dt;
+
+    dt = from ? from->allnext : dt_host;
+    dt_for_each_device_node(dt, np)
+    {
+        if ( dt_match_node(matches, np) )
+            return np;
+    }
+
+    return NULL;
+}
+
+static int __dt_n_addr_cells(const struct dt_device_node *np, bool parent)
+{
+    const __be32 *ip;
+
+    do {
+        if ( np->parent && !parent )
+            np = np->parent;
+        parent = false;
+
+        ip = dt_get_property(np, "#address-cells", NULL);
+        if ( ip )
+            return be32_to_cpup(ip);
+    } while ( np->parent );
+    /* No #address-cells property for the root node */
+    return DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
+}
+
+static int __dt_n_size_cells(const struct dt_device_node *np, bool parent)
+{
+    const __be32 *ip;
+
+    do {
+        if ( np->parent && !parent )
+            np = np->parent;
+        parent = false;
+
+        ip = dt_get_property(np, "#size-cells", NULL);
+        if ( ip )
+            return be32_to_cpup(ip);
+    } while ( np->parent );
+    /* No #address-cells property for the root node */
+    return DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
+}
+
+int dt_n_addr_cells(const struct dt_device_node *np)
+{
+    return __dt_n_addr_cells(np, false);
+}
+
+int dt_n_size_cells(const struct dt_device_node *np)
+{
+    return __dt_n_size_cells(np, false);
+}
+
+int dt_child_n_addr_cells(const struct dt_device_node *parent)
+{
+    return __dt_n_addr_cells(parent, true);
+}
+
+int dt_child_n_size_cells(const struct dt_device_node *parent)
+{
+    return __dt_n_size_cells(parent, true);
+}
+
+/*
+ * These are defined in Linux where much of this code comes from, but
+ * are currently unused outside this file in the context of Xen.
+ */
+#define IORESOURCE_BITS         0x000000ff      /* Bus-specific bits */
+
+#define IORESOURCE_TYPE_BITS    0x00001f00      /* Resource type */
+#define IORESOURCE_IO           0x00000100      /* PCI/ISA I/O ports */
+#define IORESOURCE_MEM          0x00000200
+#define IORESOURCE_REG          0x00000300      /* Register offsets */
+#define IORESOURCE_IRQ          0x00000400
+#define IORESOURCE_DMA          0x00000800
+#define IORESOURCE_BUS          0x00001000
+
+#define IORESOURCE_PREFETCH     0x00002000      /* No side effects */
+#define IORESOURCE_READONLY     0x00004000
+#define IORESOURCE_CACHEABLE    0x00008000
+#define IORESOURCE_RANGELENGTH  0x00010000
+#define IORESOURCE_SHADOWABLE   0x00020000
+
+/*
+ * Default translator (generic bus)
+ */
+static bool dt_bus_default_match(const struct dt_device_node *node)
+{
+    /* Root node doesn't have "ranges" property */
+    if ( node->parent == NULL )
+        return 1;
+
+    /* The default bus is only used when the "ranges" property exists.
+     * Otherwise we can't translate the address
+     */
+    return (dt_get_property(node, "ranges", NULL) != NULL);
+}
+
+static void dt_bus_default_count_cells(const struct dt_device_node *dev,
+                                int *addrc, int *sizec)
+{
+    if ( addrc )
+        *addrc = dt_n_addr_cells(dev);
+    if ( sizec )
+        *sizec = dt_n_size_cells(dev);
+}
+
+static u64 dt_bus_default_map(__be32 *addr, const __be32 *range,
+                              int na, int ns, int pna)
+{
+    u64 cp, s, da;
+
+    cp = dt_read_number(range, na);
+    s = dt_read_number(range + na + pna, ns);
+    da = dt_read_number(addr, na);
+
+    dt_dprintk("DT: default map, cp=%llx, s=%llx, da=%llx\n",
+               (unsigned long long)cp, (unsigned long long)s,
+               (unsigned long long)da);
+
+    /*
+     * If the number of address cells is larger than 2 we assume the
+     * mapping doesn't specify a physical address. Rather, the address
+     * specifies an identifier that must match exactly.
+     */
+    if ( na > 2 && memcmp(range, addr, na * 4) != 0 )
+        return DT_BAD_ADDR;
+
+    if ( da < cp || da >= (cp + s) )
+        return DT_BAD_ADDR;
+    return da - cp;
+}
+
+static int dt_bus_default_translate(__be32 *addr, u64 offset, int na)
+{
+    u64 a = dt_read_number(addr, na);
+
+    memset(addr, 0, na * 4);
+    a += offset;
+    if ( na > 1 )
+        addr[na - 2] = cpu_to_be32(a >> 32);
+    addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
+
+    return 0;
+}
+static unsigned int dt_bus_default_get_flags(const __be32 *addr)
+{
+    return IORESOURCE_MEM;
+}
+
+/*
+ * PCI bus specific translator
+ */
+
+static bool dt_node_is_pci(const struct dt_device_node *np)
+{
+    bool is_pci = !strcmp(np->name, "pcie") || !strcmp(np->name, "pci");
+
+    if ( is_pci )
+        printk(XENLOG_WARNING "%s: Missing device_type\n", np->full_name);
+
+    return is_pci;
+}
+
+static bool dt_bus_pci_match(const struct dt_device_node *np)
+{
+    /*
+     * "pciex" is PCI Express "vci" is for the /chaos bridge on 1st-gen PCI
+     * powermacs "ht" is hypertransport
+     *
+     * If none of the device_type match, and that the node name is
+     * "pcie" or "pci", accept the device as PCI (with a warning).
+     */
+    return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") ||
+        !strcmp(np->type, "vci") || !strcmp(np->type, "ht") ||
+        dt_node_is_pci(np);
+}
+
+static void dt_bus_pci_count_cells(const struct dt_device_node *np,
+				   int *addrc, int *sizec)
+{
+    if (addrc)
+        *addrc = 3;
+    if (sizec)
+        *sizec = 2;
+}
+
+static unsigned int dt_bus_pci_get_flags(const __be32 *addr)
+{
+    unsigned int flags = 0;
+    u32 w = be32_to_cpup(addr);
+
+    switch((w >> 24) & 0x03) {
+    case 0x01:
+        flags |= IORESOURCE_IO;
+        break;
+    case 0x02: /* 32 bits */
+    case 0x03: /* 64 bits */
+        flags |= IORESOURCE_MEM;
+        break;
+    }
+    if (w & 0x40000000)
+        flags |= IORESOURCE_PREFETCH;
+    return flags;
+}
+
+static u64 dt_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
+		int pna)
+{
+    u64 cp, s, da;
+    unsigned int af, rf;
+
+    af = dt_bus_pci_get_flags(addr);
+    rf = dt_bus_pci_get_flags(range);
+
+    /* Check address type match */
+    if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
+        return DT_BAD_ADDR;
+
+    /* Read address values, skipping high cell */
+    cp = dt_read_number(range + 1, na - 1);
+    s  = dt_read_number(range + na + pna, ns);
+    da = dt_read_number(addr + 1, na - 1);
+
+    dt_dprintk("DT: PCI map, cp=%llx, s=%llx, da=%llx\n",
+               (unsigned long long)cp, (unsigned long long)s,
+               (unsigned long long)da);
+
+    if (da < cp || da >= (cp + s))
+        return DT_BAD_ADDR;
+    return da - cp;
+}
+
+static int dt_bus_pci_translate(__be32 *addr, u64 offset, int na)
+{
+    return dt_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+/*
+ * Array of bus specific translators
+ */
+static const struct dt_bus dt_busses[] =
+{
+    /* PCI */
+    {
+        .name = "pci",
+        .addresses = "assigned-addresses",
+        .match = dt_bus_pci_match,
+        .count_cells = dt_bus_pci_count_cells,
+        .map = dt_bus_pci_map,
+        .translate = dt_bus_pci_translate,
+        .get_flags = dt_bus_pci_get_flags,
+    },
+    /* Default */
+    {
+        .name = "default",
+        .addresses = "reg",
+        .match = dt_bus_default_match,
+        .count_cells = dt_bus_default_count_cells,
+        .map = dt_bus_default_map,
+        .translate = dt_bus_default_translate,
+        .get_flags = dt_bus_default_get_flags,
+    },
+};
+
+static const struct dt_bus *dt_match_bus(const struct dt_device_node *np)
+{
+    int i;
+
+    for ( i = 0; i < ARRAY_SIZE(dt_busses); i++ )
+        if ( !dt_busses[i].match || dt_busses[i].match(np) )
+            return &dt_busses[i];
+
+    return NULL;
+}
+
+static const __be32 *dt_get_address(const struct dt_device_node *dev,
+                                    unsigned int index, u64 *size,
+                                    unsigned int *flags)
+{
+    const __be32 *prop;
+    u32 psize;
+    const struct dt_device_node *parent;
+    const struct dt_bus *bus;
+    int onesize, i, na, ns;
+
+    /* Get parent & match bus type */
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        return NULL;
+
+    bus = dt_match_bus(parent);
+    if ( !bus )
+        return NULL;
+    bus->count_cells(dev, &na, &ns);
+
+    if ( !DT_CHECK_ADDR_COUNT(na) )
+        return NULL;
+
+    /* Get "reg" or "assigned-addresses" property */
+    prop = dt_get_property(dev, bus->addresses, &psize);
+    if ( prop == NULL )
+        return NULL;
+    psize /= 4;
+
+    onesize = na + ns;
+    for ( i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++ )
+    {
+        if ( i == index )
+        {
+            if ( size )
+                *size = dt_read_number(prop + na, ns);
+            if ( flags )
+                *flags = bus->get_flags(prop);
+            return prop;
+        }
+    }
+    return NULL;
+}
+
+static int dt_translate_one(const struct dt_device_node *parent,
+                            const struct dt_bus *bus,
+                            const struct dt_bus *pbus,
+                            __be32 *addr, int na, int ns,
+                            int pna, const char *rprop)
+{
+    const __be32 *ranges;
+    unsigned int rlen;
+    int rone;
+    u64 offset = DT_BAD_ADDR;
+
+    ranges = dt_get_property(parent, rprop, &rlen);
+    if ( ranges == NULL )
+    {
+        printk(XENLOG_ERR "DT: no ranges; cannot translate\n");
+        return 1;
+    }
+    if ( rlen == 0 )
+    {
+        offset = dt_read_number(addr, na);
+        memset(addr, 0, pna * 4);
+        dt_dprintk("DT: empty ranges; 1:1 translation\n");
+        goto finish;
+    }
+
+    dt_dprintk("DT: walking ranges...\n");
+
+    /* Now walk through the ranges */
+    rlen /= 4;
+    rone = na + pna + ns;
+    for ( ; rlen >= rone; rlen -= rone, ranges += rone )
+    {
+        offset = bus->map(addr, ranges, na, ns, pna);
+        if ( offset != DT_BAD_ADDR )
+            break;
+    }
+    if ( offset == DT_BAD_ADDR )
+    {
+        dt_dprintk("DT: not found !\n");
+        return 1;
+    }
+    memcpy(addr, ranges + na, 4 * pna);
+
+finish:
+    dt_dump_addr("DT: parent translation for:", addr, pna);
+    dt_dprintk("DT: with offset: %llx\n", (unsigned long long)offset);
+
+    /* Translate it into parent bus space */
+    return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+static u64 __dt_translate_address(const struct dt_device_node *dev,
+                                  const __be32 *in_addr, const char *rprop)
+{
+    const struct dt_device_node *parent = NULL;
+    const struct dt_bus *bus, *pbus;
+    __be32 addr[DT_MAX_ADDR_CELLS];
+    int na, ns, pna, pns;
+    u64 result = DT_BAD_ADDR;
+
+    dt_dprintk("DT: ** translation for device %s **\n", dev->full_name);
+
+    /* Get parent & match bus type */
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        goto bail;
+    bus = dt_match_bus(parent);
+    if ( !bus )
+        goto bail;
+
+    /* Count address cells & copy address locally */
+    bus->count_cells(dev, &na, &ns);
+    if ( !DT_CHECK_COUNTS(na, ns) )
+    {
+        printk(XENLOG_ERR "dt_parse: Bad cell count for device %s\n",
+                  dev->full_name);
+        goto bail;
+    }
+    memcpy(addr, in_addr, na * 4);
+
+    dt_dprintk("DT: bus is %s (na=%d, ns=%d) on %s\n",
+               bus->name, na, ns, parent->full_name);
+    dt_dump_addr("DT: translating address:", addr, na);
+
+    /* Translate */
+    for ( ;; )
+    {
+        /* Switch to parent bus */
+        dev = parent;
+        parent = dt_get_parent(dev);
+
+        /* If root, we have finished */
+        if ( parent == NULL )
+        {
+            dt_dprintk("DT: reached root node\n");
+            result = dt_read_number(addr, na);
+            break;
+        }
+
+        /* Get new parent bus and counts */
+        pbus = dt_match_bus(parent);
+        if ( pbus == NULL )
+        {
+            printk("DT: %s is not a valid bus\n", parent->full_name);
+            break;
+        }
+        pbus->count_cells(dev, &pna, &pns);
+        if ( !DT_CHECK_COUNTS(pna, pns) )
+        {
+            printk(XENLOG_ERR "dt_parse: Bad cell count for parent %s\n",
+                   dev->full_name);
+            break;
+        }
+
+        dt_dprintk("DT: parent bus is %s (na=%d, ns=%d) on %s\n",
+                   pbus->name, pna, pns, parent->full_name);
+
+        /* Apply bus translation */
+        if ( dt_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop) )
+            break;
+
+        /* Complete the move up one level */
+        na = pna;
+        ns = pns;
+        bus = pbus;
+
+        dt_dump_addr("DT: one level translation:", addr, na);
+    }
+
+bail:
+    return result;
+}
+
+/* dt_device_address - Translate device tree address and return it */
+int dt_device_get_address(const struct dt_device_node *dev, unsigned int index,
+                          u64 *addr, u64 *size)
+{
+    const __be32 *addrp;
+    unsigned int flags;
+
+    addrp = dt_get_address(dev, index, size, &flags);
+    if ( addrp == NULL )
+        return -EINVAL;
+
+    if ( !addr )
+        return -EINVAL;
+
+    *addr = __dt_translate_address(dev, addrp, "ranges");
+
+    if ( *addr == DT_BAD_ADDR )
+        return -EINVAL;
+
+    return 0;
+}
+
+int dt_device_get_paddr(const struct dt_device_node *dev, unsigned int index,
+                        paddr_t *addr, paddr_t *size)
+{
+    uint64_t dt_addr, dt_size;
+    int ret;
+
+    ret = dt_device_get_address(dev, index, &dt_addr, &dt_size);
+    if ( ret )
+        return ret;
+
+    if ( !addr )
+        return -EINVAL;
+
+    if ( dt_addr != (paddr_t)dt_addr )
+    {
+        printk("Error: Physical address 0x%"PRIx64" for node=%s is greater than max width (%zu bytes) supported\n",
+               dt_addr, dev->name, sizeof(paddr_t));
+        return -ERANGE;
+    }
+
+    *addr = dt_addr;
+
+    if ( size )
+    {
+        if ( dt_size != (paddr_t)dt_size )
+        {
+            printk("Error: Physical size 0x%"PRIx64" for node=%s is greater than max width (%zu bytes) supported\n",
+                   dt_size, dev->name, sizeof(paddr_t));
+            return -ERANGE;
+        }
+
+        *size = dt_size;
+    }
+
+    return ret;
+}
+
+int dt_for_each_range(const struct dt_device_node *dev,
+                      int (*cb)(const struct dt_device_node *dev,
+                                uint64_t addr, uint64_t length,
+                                void *data),
+                      void *data)
+{
+    const struct dt_device_node *parent = NULL;
+    const struct dt_bus *bus, *pbus;
+    const __be32 *ranges;
+    __be32 addr[DT_MAX_ADDR_CELLS];
+    unsigned int rlen;
+    int na, ns, pna, pns, rone;
+
+    bus = dt_match_bus(dev);
+    if ( !bus )
+        return 0; /* device is not a bus */
+
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        return -EINVAL;
+
+    ranges = dt_get_property(dev, "ranges", &rlen);
+    if ( ranges == NULL )
+    {
+        printk(XENLOG_ERR "DT: no ranges; cannot enumerate %s\n",
+               dev->full_name);
+        return -EINVAL;
+    }
+    if ( rlen == 0 ) /* Nothing to do */
+        return 0;
+
+    bus->count_cells(dev, &na, &ns);
+    if ( !DT_CHECK_COUNTS(na, ns) )
+    {
+        printk(XENLOG_ERR "dt_parse: Bad cell count for device %s\n",
+                  dev->full_name);
+        return -EINVAL;
+    }
+
+    pbus = dt_match_bus(parent);
+    if ( pbus == NULL )
+    {
+        printk("DT: %s is not a valid bus\n", parent->full_name);
+        return -EINVAL;
+    }
+
+    pbus->count_cells(dev, &pna, &pns);
+    if ( !DT_CHECK_COUNTS(pna, pns) )
+    {
+        printk(XENLOG_ERR "dt_parse: Bad cell count for parent %s\n",
+               dev->full_name);
+        return -EINVAL;
+    }
+
+    /* Now walk through the ranges */
+    rlen /= 4;
+    rone = na + pna + ns;
+
+    dt_dprintk("%s: dev=%s, bus=%s, parent=%s, rlen=%d, rone=%d\n",
+               __func__,
+               dt_node_name(dev), bus->name,
+               dt_node_name(parent), rlen, rone);
+
+    for ( ; rlen >= rone; rlen -= rone, ranges += rone )
+    {
+        uint64_t a, s;
+        int ret;
+
+        memcpy(addr, ranges + na, 4 * pna);
+
+        a = __dt_translate_address(dev, addr, "ranges");
+        s = dt_read_number(ranges + na + pna, ns);
+
+        ret = cb(dev, a, s, data);
+        if ( ret )
+        {
+            dt_dprintk(" -> callback failed=%d\n", ret);
+            return ret;
+        }
+
+    }
+
+    return 0;
+}
+
+/**
+ * dt_find_node_by_phandle - Find a node given a phandle
+ * @handle: phandle of the node to find
+ *
+ * Returns a node pointer.
+ */
+struct dt_device_node *dt_find_node_by_phandle(dt_phandle handle)
+{
+    struct dt_device_node *np;
+
+    dt_for_each_device_node(dt_host, np)
+        if ( np->phandle == handle )
+            break;
+
+    return np;
+}
+
+/**
+ * dt_irq_find_parent - Given a device node, find its interrupt parent node
+ * @child: pointer to device node
+ *
+ * Returns a pointer to the interrupt parent node, or NULL if the interrupt
+ * parent could not be determined.
+ */
+static const struct dt_device_node *
+dt_irq_find_parent(const struct dt_device_node *child)
+{
+    const struct dt_device_node *p;
+    const __be32 *parp;
+
+    do
+    {
+        parp = dt_get_property(child, "interrupt-parent", NULL);
+        if ( parp == NULL )
+            p = dt_get_parent(child);
+        else
+            p = dt_find_node_by_phandle(be32_to_cpup(parp));
+        child = p;
+    } while ( p && dt_get_property(p, "#interrupt-cells", NULL) == NULL );
+
+    return p;
+}
+
+unsigned int dt_number_of_irq(const struct dt_device_node *device)
+{
+    const struct dt_device_node *p;
+    const __be32 *intspec, *tmp;
+    u32 intsize, intlen;
+    int intnum;
+
+    dt_dprintk("dt_irq_number: dev=%s\n", device->full_name);
+
+    /* Try the new-style interrupts-extended first */
+    intnum = dt_count_phandle_with_args(device, "interrupts-extended",
+                                        "#interrupt-cells");
+    if ( intnum >= 0 )
+    {
+        dt_dprintk(" using 'interrupts-extended' property\n");
+        dt_dprintk(" intnum=%d\n", intnum);
+        return intnum;
+    }
+
+    /* Get the interrupts property */
+    intspec = dt_get_property(device, "interrupts", &intlen);
+    if ( intspec == NULL )
+        return 0;
+    intlen /= sizeof(*intspec);
+
+    dt_dprintk(" using 'interrupts' property\n");
+    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+
+    /* Look for the interrupt parent. */
+    p = dt_irq_find_parent(device);
+    if ( p == NULL )
+        return 0;
+
+    /* Get size of interrupt specifier */
+    tmp = dt_get_property(p, "#interrupt-cells", NULL);
+    if ( tmp == NULL )
+        return 0;
+    intsize = be32_to_cpu(*tmp);
+
+    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
+
+    return (intlen / intsize);
+}
+
+unsigned int dt_number_of_address(const struct dt_device_node *dev)
+{
+    const __be32 *prop;
+    u32 psize;
+    const struct dt_device_node *parent;
+    const struct dt_bus *bus;
+    int onesize, na, ns;
+
+    /* Get parent & match bus type */
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        return 0;
+
+    bus = dt_match_bus(parent);
+    if ( !bus )
+        return 0;
+    bus->count_cells(dev, &na, &ns);
+
+    if ( !DT_CHECK_COUNTS(na, ns) )
+        return 0;
+
+    /* Get "reg" or "assigned-addresses" property */
+    prop = dt_get_property(dev, bus->addresses, &psize);
+    if ( prop == NULL )
+        return 0;
+
+    psize /= 4;
+    onesize = na + ns;
+
+    return (psize / onesize);
+}
+
+int dt_for_each_irq_map(const struct dt_device_node *dev,
+                        int (*cb)(const struct dt_device_node *dev,
+                                  const struct dt_irq *dt_irq,
+                                  void *data),
+                        void *data)
+{
+    const struct dt_device_node *ipar, *tnode, *old = NULL;
+    const __be32 *tmp, *imap;
+    u32 intsize = 1, addrsize, pintsize = 0, paddrsize = 0;
+    u32 imaplen;
+    int i, ret;
+
+    struct dt_raw_irq dt_raw_irq;
+    struct dt_irq dt_irq;
+
+    dt_dprintk("%s: par=%s cb=%p data=%p\n", __func__,
+               dev->full_name, cb, data);
+
+    ipar = dev;
+
+    /* First get the #interrupt-cells property of the current cursor
+     * that tells us how to interpret the passed-in intspec. If there
+     * is none, we are nice and just walk up the tree
+     */
+    do {
+        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
+        if ( tmp != NULL )
+        {
+            intsize = be32_to_cpu(*tmp);
+            break;
+        }
+        tnode = ipar;
+        ipar = dt_irq_find_parent(ipar);
+    } while ( ipar );
+    if ( ipar == NULL )
+    {
+        dt_dprintk(" -> no parent found !\n");
+        goto fail;
+    }
+
+    dt_dprintk("%s: ipar=%s, size=%d\n", __func__, ipar->full_name, intsize);
+
+    if ( intsize > DT_MAX_IRQ_SPEC )
+    {
+        dt_dprintk(" -> too many irq specifier cells\n");
+        goto fail;
+    }
+
+    /* Look for this #address-cells. We have to implement the old linux
+     * trick of looking for the parent here as some device-trees rely on it
+     */
+    old = ipar;
+    do {
+        tmp = dt_get_property(old, "#address-cells", NULL);
+        tnode = dt_get_parent(old);
+        old = tnode;
+    } while ( old && tmp == NULL );
+
+    old = NULL;
+    addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
+
+    dt_dprintk(" -> addrsize=%d\n", addrsize);
+
+    /* Now look for an interrupt-map */
+    imap = dt_get_property(dev, "interrupt-map", &imaplen);
+    /* No interrupt-map found. Ignore */
+    if ( imap == NULL )
+    {
+        dt_dprintk(" -> no map, ignoring\n");
+        return 0;
+    }
+    imaplen /= sizeof(u32);
+
+    /* Parse interrupt-map */
+    while ( imaplen > (addrsize + intsize + 1) )
+    {
+        /* skip child unit address and child interrupt specifier */
+        imap += addrsize + intsize;
+        imaplen -= addrsize + intsize;
+
+        /* Get the interrupt parent */
+        ipar = dt_find_node_by_phandle(be32_to_cpup(imap));
+        imap++;
+        --imaplen;
+
+        /* Check if not found */
+        if ( ipar == NULL )
+        {
+            dt_dprintk(" -> imap parent not found !\n");
+            goto fail;
+        }
+
+        dt_dprintk(" -> ipar %s\n", dt_node_name(ipar));
+
+        /* Get #interrupt-cells and #address-cells of new
+         * parent
+         */
+        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
+        if ( tmp == NULL )
+        {
+            dt_dprintk(" -> parent lacks #interrupt-cells!\n");
+            goto fail;
+        }
+        pintsize = be32_to_cpu(*tmp);
+        tmp = dt_get_property(ipar, "#address-cells", NULL);
+        paddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
+
+        dt_dprintk(" -> pintsize=%d, paddrsize=%d\n",
+                   pintsize, paddrsize);
+
+        if ( pintsize > DT_MAX_IRQ_SPEC )
+        {
+            dt_dprintk(" -> too many irq specifier cells in parent\n");
+            goto fail;
+        }
+
+        /* Check for malformed properties */
+        if ( imaplen < (paddrsize + pintsize) )
+            goto fail;
+
+        imap += paddrsize;
+        imaplen -= paddrsize;
+
+        dt_raw_irq.controller = ipar;
+        dt_raw_irq.size = pintsize;
+        for ( i = 0; i < pintsize; i++ )
+            dt_raw_irq.specifier[i] = dt_read_number(imap + i, 1);
+
+        if ( dt_raw_irq.controller != dt_interrupt_controller )
+        {
+            /*
+             * We don't map IRQs connected to secondary IRQ controllers as
+             * these IRQs have no meaning to us until they connect to the
+             * primary controller.
+             *
+             * Secondary IRQ controllers will at some point connect to
+             * the primary controller (possibly via other IRQ controllers).
+             * We map the IRQs at that last connection point.
+             */
+            imap += pintsize;
+            imaplen -= pintsize;
+            dt_dprintk(" -> Skipped IRQ for secondary IRQ controller\n");
+            continue;
+        }
+
+        ret = dt_irq_translate(&dt_raw_irq, &dt_irq);
+        if ( ret )
+        {
+            dt_dprintk(" -> failed to translate IRQ: %d\n", ret);
+            return ret;
+        }
+
+        ret = cb(dev, &dt_irq, data);
+        if ( ret )
+        {
+            dt_dprintk(" -> callback failed=%d\n", ret);
+            return ret;
+        }
+
+        imap += pintsize;
+        imaplen -= pintsize;
+
+        dt_dprintk(" -> imaplen=%d\n", imaplen);
+    }
+
+    return 0;
+
+fail:
+    return -EINVAL;
+}
+
+/**
+ * dt_irq_map_raw - Low level interrupt tree parsing
+ * @parent:     the device interrupt parent
+ * @intspec:    interrupt specifier ("interrupts" property of the device)
+ * @ointsize:   size of the passed in interrupt specifier
+ * @addr:       address specifier (start of "reg" property of the device)
+ * @oirq:       structure dt_raw_irq filled by this function
+ *
+ * Returns 0 on success and a negative number on error
+ *
+ * This function is a low-level interrupt tree walking function. It
+ * can be used to do a partial walk with synthesized reg and interrupts
+ * properties, for example when resolving PCI interrupts when no device
+ * node exist for the parent.
+ */
+static int dt_irq_map_raw(const struct dt_device_node *parent,
+                          const __be32 *intspec, u32 ointsize,
+                          const __be32 *addr,
+                          struct dt_raw_irq *oirq)
+{
+    const struct dt_device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+    const __be32 *tmp, *imap, *imask;
+    u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+    u32 imaplen;
+    int match, i;
+
+    dt_dprintk("dt_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+               parent->full_name, be32_to_cpup(intspec),
+               be32_to_cpup(intspec + 1), ointsize);
+
+    ipar = parent;
+
+    /* First get the #interrupt-cells property of the current cursor
+     * that tells us how to interpret the passed-in intspec. If there
+     * is none, we are nice and just walk up the tree
+     */
+    do {
+        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
+        if ( tmp != NULL )
+        {
+            intsize = be32_to_cpu(*tmp);
+            break;
+        }
+        tnode = ipar;
+        ipar = dt_irq_find_parent(ipar);
+    } while ( ipar );
+    if ( ipar == NULL )
+    {
+        dt_dprintk(" -> no parent found !\n");
+        goto fail;
+    }
+
+    dt_dprintk("dt_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
+
+    if ( ointsize != intsize )
+        return -EINVAL;
+
+    /* Look for this #address-cells. We have to implement the old linux
+     * trick of looking for the parent here as some device-trees rely on it
+     */
+    old = ipar;
+    do {
+        tmp = dt_get_property(old, "#address-cells", NULL);
+        tnode = dt_get_parent(old);
+        old = tnode;
+    } while ( old && tmp == NULL );
+
+    old = NULL;
+    addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
+
+    dt_dprintk(" -> addrsize=%d\n", addrsize);
+
+    /* Now start the actual "proper" walk of the interrupt tree */
+    while ( ipar != NULL )
+    {
+        /* Now check if cursor is an interrupt-controller and if it is
+         * then we are done
+         */
+        if ( dt_get_property(ipar, "interrupt-controller", NULL) != NULL )
+        {
+            dt_dprintk(" -> got it !\n");
+            if ( intsize > DT_MAX_IRQ_SPEC )
+            {
+                dt_dprintk(" -> intsize(%u) greater than DT_MAX_IRQ_SPEC(%u)\n",
+                           intsize, DT_MAX_IRQ_SPEC);
+                goto fail;
+            }
+            for ( i = 0; i < intsize; i++ )
+                oirq->specifier[i] = dt_read_number(intspec + i, 1);
+            oirq->size = intsize;
+            oirq->controller = ipar;
+            return 0;
+        }
+
+        /* Now look for an interrupt-map */
+        imap = dt_get_property(ipar, "interrupt-map", &imaplen);
+        /* No interrupt map, check for an interrupt parent */
+        if ( imap == NULL )
+        {
+            dt_dprintk(" -> no map, getting parent\n");
+            newpar = dt_irq_find_parent(ipar);
+            goto skiplevel;
+        }
+        imaplen /= sizeof(u32);
+
+        /* Look for a mask */
+        imask = dt_get_property(ipar, "interrupt-map-mask", NULL);
+
+        /* If we were passed no "reg" property and we attempt to parse
+         * an interrupt-map, then #address-cells must be 0.
+         * Fail if it's not.
+         */
+        if ( addr == NULL && addrsize != 0 )
+        {
+            dt_dprintk(" -> no reg passed in when needed !\n");
+            goto fail;
+        }
+
+        /* Parse interrupt-map */
+        match = 0;
+        while ( imaplen > (addrsize + intsize + 1) && !match )
+        {
+            /* Compare specifiers */
+            match = 1;
+            for ( i = 0; i < addrsize && match; ++i )
+            {
+                __be32 mask = imask ? imask[i] : cpu_to_be32(0xffffffffu);
+                match = ((addr[i] ^ imap[i]) & mask) == 0;
+            }
+            for ( ; i < (addrsize + intsize) && match; ++i )
+            {
+                __be32 mask = imask ? imask[i] : cpu_to_be32(0xffffffffu);
+                match = ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
+            }
+            imap += addrsize + intsize;
+            imaplen -= addrsize + intsize;
+
+            dt_dprintk(" -> match=%d (imaplen=%d)\n", match, imaplen);
+
+            /* Get the interrupt parent */
+            newpar = dt_find_node_by_phandle(be32_to_cpup(imap));
+            imap++;
+            --imaplen;
+
+            /* Check if not found */
+            if ( newpar == NULL )
+            {
+                dt_dprintk(" -> imap parent not found !\n");
+                goto fail;
+            }
+
+            /* Get #interrupt-cells and #address-cells of new
+             * parent
+             */
+            tmp = dt_get_property(newpar, "#interrupt-cells", NULL);
+            if ( tmp == NULL )
+            {
+                dt_dprintk(" -> parent lacks #interrupt-cells!\n");
+                goto fail;
+            }
+            newintsize = be32_to_cpu(*tmp);
+            tmp = dt_get_property(newpar, "#address-cells", NULL);
+            newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
+
+            dt_dprintk(" -> newintsize=%d, newaddrsize=%d\n",
+                       newintsize, newaddrsize);
+
+            /* Check for malformed properties */
+            if ( imaplen < (newaddrsize + newintsize) )
+                goto fail;
+
+            imap += newaddrsize + newintsize;
+            imaplen -= newaddrsize + newintsize;
+
+            dt_dprintk(" -> imaplen=%d\n", imaplen);
+        }
+        if ( !match )
+            goto fail;
+
+        old = newpar;
+        addrsize = newaddrsize;
+        intsize = newintsize;
+        intspec = imap - intsize;
+        addr = intspec - addrsize;
+
+    skiplevel:
+        /* Iterate again with new parent */
+        dt_dprintk(" -> new parent: %s\n", dt_node_full_name(newpar));
+        ipar = newpar;
+        newpar = NULL;
+    }
+fail:
+    return -EINVAL;
+}
+
+int dt_device_get_raw_irq(const struct dt_device_node *device,
+                          unsigned int index,
+                          struct dt_raw_irq *out_irq)
+{
+    const struct dt_device_node *p;
+    const __be32 *intspec, *tmp, *addr;
+    u32 intsize, intlen;
+    int res = -EINVAL;
+    struct dt_phandle_args args;
+    int i;
+
+    dt_dprintk("dt_device_get_raw_irq: dev=%s, index=%u\n",
+               device->full_name, index);
+
+    /* Get the reg property (if any) */
+    addr = dt_get_property(device, "reg", NULL);
+
+    /* Try the new-style interrupts-extended first */
+    res = dt_parse_phandle_with_args(device, "interrupts-extended",
+                                     "#interrupt-cells", index, &args);
+    if ( !res )
+    {
+        dt_dprintk(" using 'interrupts-extended' property\n");
+        dt_dprintk(" intspec=%d intsize=%d\n", args.args[0], args.args_count);
+
+        for ( i = 0; i < args.args_count; i++ )
+            args.args[i] = cpu_to_be32(args.args[i]);
+
+        return dt_irq_map_raw(args.np, args.args, args.args_count,
+                              addr, out_irq);
+    }
+
+    /* Get the interrupts property */
+    intspec = dt_get_property(device, "interrupts", &intlen);
+    if ( intspec == NULL )
+        return -EINVAL;
+    intlen /= sizeof(*intspec);
+
+    dt_dprintk(" using 'interrupts' property\n");
+    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+
+    /* Look for the interrupt parent. */
+    p = dt_irq_find_parent(device);
+    if ( p == NULL )
+        return -EINVAL;
+
+    /* Get size of interrupt specifier */
+    tmp = dt_get_property(p, "#interrupt-cells", NULL);
+    if ( tmp == NULL )
+        goto out;
+    intsize = be32_to_cpu(*tmp);
+
+    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
+
+    /* Check index */
+    if ( (index + 1) * intsize > intlen )
+        goto out;
+
+    /* Get new specifier and map it */
+    res = dt_irq_map_raw(p, intspec + index * intsize, intsize,
+                         addr, out_irq);
+    if ( res )
+        goto out;
+out:
+    return res;
+}
+
+int dt_irq_translate(const struct dt_raw_irq *raw,
+                     struct dt_irq *out_irq)
+{
+    ASSERT(dt_irq_xlate != NULL);
+    ASSERT(dt_interrupt_controller != NULL);
+
+    /*
+     * TODO: Retrieve the right irq_xlate. This is only works for the primary
+     * interrupt controller.
+     */
+    if ( raw->controller != dt_interrupt_controller )
+        return -EINVAL;
+
+    return dt_irq_xlate(raw->specifier, raw->size,
+                        &out_irq->irq, &out_irq->type);
+}
+
+int dt_device_get_irq(const struct dt_device_node *device, unsigned int index,
+                      struct dt_irq *out_irq)
+{
+    struct dt_raw_irq raw;
+    int res;
+
+    res = dt_device_get_raw_irq(device, index, &raw);
+
+    if ( res )
+        return res;
+
+    return dt_irq_translate(&raw, out_irq);
+}
+
+bool dt_device_is_available(const struct dt_device_node *device)
+{
+    const char *status;
+    u32 statlen;
+
+    status = dt_get_property(device, "status", &statlen);
+    if ( status == NULL )
+        return 1;
+
+    if ( statlen > 0 )
+    {
+        if ( !strcmp(status, "okay") || !strcmp(status, "ok") )
+            return 1;
+    }
+
+    return 0;
+}
+
+bool dt_device_for_passthrough(const struct dt_device_node *device)
+{
+    return (dt_find_property(device, "xen,passthrough", NULL) != NULL);
+
+}
+
+static int __dt_parse_phandle_with_args(const struct dt_device_node *np,
+                                        const char *list_name,
+                                        const char *cells_name,
+                                        int cell_count, int index,
+                                        struct dt_phandle_args *out_args)
+{
+    const __be32 *list, *list_end;
+    int rc = 0, cur_index = 0;
+    u32 size, count = 0;
+    struct dt_device_node *node = NULL;
+    dt_phandle phandle;
+
+    /* Retrieve the phandle list property */
+    list = dt_get_property(np, list_name, &size);
+    if ( !list )
+        return -ENOENT;
+    list_end = list + size / sizeof(*list);
+
+    /* Loop over the phandles until all the requested entry is found */
+    while ( list < list_end )
+    {
+        rc = -EINVAL;
+        count = 0;
+
+        /*
+         * If phandle is 0, then it is an empty entry with no
+         * arguments.  Skip forward to the next entry.
+         * */
+        phandle = be32_to_cpup(list++);
+        if ( phandle )
+        {
+            /*
+             * Find the provider node and parse the #*-cells
+             * property to determine the argument length.
+             *
+             * This is not needed if the cell count is hard-coded
+             * (i.e. cells_name not set, but cell_count is set),
+             * except when we're going to return the found node
+             * below.
+             */
+            if ( cells_name || cur_index == index )
+            {
+                node = dt_find_node_by_phandle(phandle);
+                if ( !node )
+                {
+                    printk(XENLOG_ERR "%s: could not find phandle\n",
+                           np->full_name);
+                    goto err;
+                }
+            }
+
+            if ( cells_name )
+            {
+                if ( !dt_property_read_u32(node, cells_name, &count) )
+                {
+                    printk("%s: could not get %s for %s\n",
+                           np->full_name, cells_name, node->full_name);
+                    goto err;
+                }
+            }
+            else
+                count = cell_count;
+
+            /*
+             * Make sure that the arguments actually fit in the
+             * remaining property data length
+             */
+            if ( list + count > list_end )
+            {
+                printk(XENLOG_ERR "%s: arguments longer than property\n",
+                       np->full_name);
+                goto err;
+            }
+        }
+
+        /*
+         * All of the error cases above bail out of the loop, so at
+         * this point, the parsing is successful. If the requested
+         * index matches, then fill the out_args structure and return,
+         * or return -ENOENT for an empty entry.
+         */
+        rc = -ENOENT;
+        if ( cur_index == index )
+        {
+            if (!phandle)
+                goto err;
+
+            if ( out_args )
+            {
+                int i;
+
+                WARN_ON(count > MAX_PHANDLE_ARGS);
+                if (count > MAX_PHANDLE_ARGS)
+                    count = MAX_PHANDLE_ARGS;
+                out_args->np = node;
+                out_args->args_count = count;
+                for ( i = 0; i < count; i++ )
+                    out_args->args[i] = be32_to_cpup(list++);
+            }
+
+            /* Found it! return success */
+            return 0;
+        }
+
+        node = NULL;
+        list += count;
+        cur_index++;
+    }
+
+    /*
+     * Returning result will be one of:
+     * -ENOENT : index is for empty phandle
+     * -EINVAL : parsing error on data
+     * [1..n]  : Number of phandle (count mode; when index = -1)
+     */
+    rc = index < 0 ? cur_index : -ENOENT;
+err:
+    return rc;
+}
+
+struct dt_device_node *dt_parse_phandle(const struct dt_device_node *np,
+                                        const char *phandle_name, int index)
+{
+    struct dt_phandle_args args;
+
+    if (index < 0)
+        return NULL;
+
+    if (__dt_parse_phandle_with_args(np, phandle_name, NULL, 0,
+                                     index, &args))
+        return NULL;
+
+    return args.np;
+}
+
+
+int dt_parse_phandle_with_args(const struct dt_device_node *np,
+                               const char *list_name,
+                               const char *cells_name, int index,
+                               struct dt_phandle_args *out_args)
+{
+    if ( index < 0 )
+        return -EINVAL;
+    return __dt_parse_phandle_with_args(np, list_name, cells_name, 0,
+                                        index, out_args);
+}
+
+int dt_count_phandle_with_args(const struct dt_device_node *np,
+                               const char *list_name,
+                               const char *cells_name)
+{
+    return __dt_parse_phandle_with_args(np, list_name, cells_name, 0, -1, NULL);
+}
+
+/**
+ * unflatten_dt_node - Alloc and populate a device_node from the flat tree
+ * @fdt: The parent device tree blob
+ * @mem: Memory chunk to use for allocating device nodes and properties
+ * @p: pointer to node in flat tree
+ * @dad: Parent struct device_node
+ * @allnextpp: pointer to ->allnext from last allocated device_node
+ * @fpsize: Size of the node path up at the current depth.
+ */
+static unsigned long unflatten_dt_node(const void *fdt,
+                                       unsigned long mem,
+                                       unsigned long *p,
+                                       struct dt_device_node *dad,
+                                       struct dt_device_node ***allnextpp,
+                                       unsigned long fpsize)
+{
+    struct dt_device_node *np;
+    struct dt_property *pp, **prev_pp = NULL;
+    char *pathp;
+    u32 tag;
+    unsigned int l, allocl;
+    int has_name = 0;
+    int new_format = 0;
+
+    tag = be32_to_cpup((__be32 *)(*p));
+    if ( tag != FDT_BEGIN_NODE )
+    {
+        printk(XENLOG_WARNING "Weird tag at start of node: %x\n", tag);
+        return mem;
+    }
+    *p += 4;
+    pathp = (char *)*p;
+    l = allocl = strlen(pathp) + 1;
+    *p = ROUNDUP(*p + l, 4);
+
+    /* version 0x10 has a more compact unit name here instead of the full
+     * path. we accumulate the full path size using "fpsize", we'll rebuild
+     * it later. We detect this because the first character of the name is
+     * not '/'.
+     */
+    if ( (*pathp) != '/' )
+    {
+        new_format = 1;
+        if ( fpsize == 0 )
+        {
+            /* root node: special case. fpsize accounts for path
+             * plus terminating zero. root node only has '/', so
+             * fpsize should be 2, but we want to avoid the first
+             * level nodes to have two '/' so we use fpsize 1 here
+             */
+            fpsize = 1;
+            allocl = 2;
+        }
+        else
+        {
+            /* account for '/' and path size minus terminal 0
+             * already in 'l'
+             */
+            fpsize += l;
+            allocl = fpsize;
+        }
+    }
+
+    np = unflatten_dt_alloc(&mem, sizeof(struct dt_device_node) + allocl,
+                            __alignof__(struct dt_device_node));
+    if ( allnextpp )
+    {
+        memset(np, 0, sizeof(*np));
+        np->full_name = ((char *)np) + sizeof(struct dt_device_node);
+        /* By default dom0 owns the device */
+        np->used_by = 0;
+        /* By default the device is not protected */
+        np->is_protected = false;
+        INIT_LIST_HEAD(&np->domain_list);
+
+        if ( new_format )
+        {
+            char *fn = np->full_name;
+            /* rebuild full path for new format */
+            if ( dad && dad->parent )
+            {
+                strlcpy(fn, dad->full_name, allocl);
+#ifdef DEBUG_DT
+                if ( (strlen(fn) + l + 1) != allocl )
+                {
+                    dt_dprintk("%s: p: %d, l: %d, a: %d\n",
+                               pathp, (int)strlen(fn),
+                               l, allocl);
+                }
+#endif
+                fn += strlen(fn);
+            }
+            *(fn++) = '/';
+            memcpy(fn, pathp, l);
+        }
+        else
+            memcpy(np->full_name, pathp, l);
+        prev_pp = &np->properties;
+        **allnextpp = np;
+        *allnextpp = &np->allnext;
+        if ( dad != NULL )
+        {
+            np->parent = dad;
+            /* we temporarily use the next field as `last_child'*/
+            if ( dad->next == NULL )
+                dad->child = np;
+            else
+                dad->next->sibling = np;
+            dad->next = np;
+        }
+    }
+    /* process properties */
+    while ( 1 )
+    {
+        u32 sz, noff;
+        const char *pname;
+
+        tag = be32_to_cpup((__be32 *)(*p));
+        if ( tag == FDT_NOP )
+        {
+            *p += 4;
+            continue;
+        }
+        if ( tag != FDT_PROP )
+            break;
+        *p += 4;
+        sz = be32_to_cpup((__be32 *)(*p));
+        noff = be32_to_cpup((__be32 *)((*p) + 4));
+        *p += 8;
+        if ( fdt_version(fdt) < 0x10 )
+            *p = ROUNDUP(*p, sz >= 8 ? 8 : 4);
+
+        pname = fdt_string(fdt, noff);
+        if ( pname == NULL )
+        {
+            dt_dprintk("Can't find property name in list!\n");
+            break;
+        }
+        if ( strcmp(pname, "name") == 0 )
+            has_name = 1;
+        l = strlen(pname) + 1;
+        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property),
+                                __alignof__(struct dt_property));
+        if ( allnextpp )
+        {
+            /* We accept flattened tree phandles either in
+             * ePAPR-style "phandle" properties, or the
+             * legacy "linux,phandle" properties.  If both
+             * appear and have different values, things
+             * will get weird.  Don't do that. */
+            if ( (strcmp(pname, "phandle") == 0) ||
+                 (strcmp(pname, "linux,phandle") == 0) )
+            {
+                if ( np->phandle == 0 )
+                    np->phandle = be32_to_cpup((__be32*)*p);
+            }
+            /* And we process the "ibm,phandle" property
+             * used in pSeries dynamic device tree
+             * stuff */
+            if ( strcmp(pname, "ibm,phandle") == 0 )
+                np->phandle = be32_to_cpup((__be32 *)*p);
+            pp->name = pname;
+            pp->length = sz;
+            pp->value = (void *)*p;
+            *prev_pp = pp;
+            prev_pp = &pp->next;
+        }
+        *p = ROUNDUP((*p) + sz, 4);
+    }
+    /* with version 0x10 we may not have the name property, recreate
+     * it here from the unit name if absent
+     */
+    if ( !has_name )
+    {
+        char *p1 = pathp, *ps = pathp, *pa = NULL;
+        int sz;
+
+        while ( *p1 )
+        {
+            if ( (*p1) == '@' )
+                pa = p1;
+            if ( (*p1) == '/' )
+                ps = p1 + 1;
+            p1++;
+        }
+        if ( pa < ps )
+            pa = p1;
+        sz = (pa - ps) + 1;
+        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property) + sz,
+                                __alignof__(struct dt_property));
+        if ( allnextpp )
+        {
+            pp->name = "name";
+            pp->length = sz;
+            pp->value = pp + 1;
+            /*
+             * The device tree creation code assume that the property
+             * "name" is not a fake.
+             * To avoid a big divergence with Linux code, only remove
+             * property link. In this case we will lose a bit of memory
+             */
+#if 0
+            *prev_pp = pp;
+            prev_pp = &pp->next;
+#endif
+            np->name = pp->value;
+            memcpy(pp->value, ps, sz - 1);
+            ((char *)pp->value)[sz - 1] = 0;
+            dt_dprintk("fixed up name for %s -> %s\n", pathp,
+                       (char *)pp->value);
+            /* Generic device initialization */
+            np->dev.type = DEV_DT;
+            np->dev.of_node = np;
+        }
+    }
+    if ( allnextpp )
+    {
+        *prev_pp = NULL;
+        np->name = (np->name) ? : dt_get_property(np, "name", NULL);
+        np->type = dt_get_property(np, "device_type", NULL);
+
+        if ( !np->name )
+            np->name = "<NULL>";
+        if ( !np->type )
+            np->type = "<NULL>";
+    }
+    while ( tag == FDT_BEGIN_NODE || tag == FDT_NOP )
+    {
+        if ( tag == FDT_NOP )
+            *p += 4;
+        else
+            mem = unflatten_dt_node(fdt, mem, p, np, allnextpp, fpsize);
+        tag = be32_to_cpup((__be32 *)(*p));
+    }
+    if ( tag != FDT_END_NODE )
+    {
+        printk(XENLOG_WARNING "Weird tag at end of node: %x\n", tag);
+        return mem;
+    }
+
+    *p += 4;
+    return mem;
+}
+
+int unflatten_device_tree(const void *fdt, struct dt_device_node **mynodes)
+{
+    unsigned long start, mem, size;
+    struct dt_device_node **allnextp = mynodes;
+
+    dt_dprintk(" -> unflatten_device_tree()\n");
+
+    dt_dprintk("Unflattening device tree:\n");
+    dt_dprintk("magic: %#08x\n", fdt_magic(fdt));
+    dt_dprintk("size: %#08x\n", fdt_totalsize(fdt));
+    dt_dprintk("version: %#08x\n", fdt_version(fdt));
+
+    /* First pass, scan for size */
+    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
+    size = unflatten_dt_node(fdt, 0, &start, NULL, NULL, 0);
+    if ( !size )
+        return -EINVAL;
+
+    size = (size | 3) + 1;
+
+    dt_dprintk("  size is %#lx allocating...\n", size);
+
+    /* Allocate memory for the expanded device tree */
+    mem = (unsigned long)_xmalloc (size + 4, __alignof__(struct dt_device_node));
+    if ( !mem )
+        return -ENOMEM;
+
+    ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeefU);
+
+    dt_dprintk("  unflattening %lx...\n", mem);
+
+    /* Second pass, do actual unflattening */
+    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
+    unflatten_dt_node(fdt, mem, &start, NULL, &allnextp, 0);
+    if ( be32_to_cpup((__be32 *)start) != FDT_END )
+    {
+        printk(XENLOG_ERR "Weird tag at end of tree: %08x\n",
+                  *((u32 *)start));
+        xfree((void *)mem);
+        return -EINVAL;
+    }
+
+    if ( be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeefU )
+    {
+        printk(XENLOG_ERR "End of tree marker overwritten: %08x\n",
+                  be32_to_cpu(((__be32 *)mem)[size / 4]));
+        xfree((void *)mem);
+        return -EINVAL;
+    }
+
+    *allnextp = NULL;
+
+    dt_dprintk(" <- unflatten_device_tree()\n");
+
+    return 0;
+}
+
+static void dt_alias_add(struct dt_alias_prop *ap,
+                         struct dt_device_node *np,
+                         int id, const char *stem, int stem_len)
+{
+    ap->np = np;
+    ap->id = id;
+    strlcpy(ap->stem, stem, stem_len + 1);
+    list_add_tail(&ap->link, &aliases_lookup);
+    dt_dprintk("adding DT alias:%s: stem=%s id=%d node=%s\n",
+               ap->alias, ap->stem, ap->id, dt_node_full_name(np));
+}
+
+/**
+ * dt_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties.  It returns the
+ * number of alias_prop found, or error code in error case.
+ */
+static void __init dt_alias_scan(void)
+{
+    const struct dt_property *pp;
+    const struct dt_device_node *aliases;
+
+    aliases = dt_find_node_by_path("/aliases");
+    if ( !aliases )
+        return;
+
+    dt_for_each_property_node( aliases, pp )
+    {
+        const char *start = pp->name;
+        const char *end = start + strlen(start);
+        struct dt_device_node *np;
+        struct dt_alias_prop *ap;
+        int id, len;
+
+        /* Skip those we do not want to proceed */
+        if ( !strcmp(pp->name, "name") ||
+             !strcmp(pp->name, "phandle") ||
+             !strcmp(pp->name, "linux,phandle") )
+            continue;
+
+        np = dt_find_node_by_path(pp->value);
+        if ( !np )
+            continue;
+
+        /* walk the alias backwards to extract the id and work out
+         * the 'stem' string */
+        while ( isdigit(*(end-1)) && end > start )
+            end--;
+        len = end - start;
+
+        id = simple_strtoll(end, NULL, 10);
+
+        /* Allocate an alias_prop with enough space for the stem */
+        ap = _xmalloc(sizeof(*ap) + len + 1, 4);
+        if ( !ap )
+            continue;
+        ap->alias = start;
+        dt_alias_add(ap, np, id, start, len);
+    }
+}
+
+struct dt_device_node * __init
+dt_find_interrupt_controller(const struct dt_device_match *matches)
+{
+    struct dt_device_node *np = NULL;
+
+    while ( (np = dt_find_matching_node(np, matches)) )
+    {
+        if ( !dt_find_property(np, "interrupt-controller", NULL) )
+            continue;
+
+        if ( dt_get_parent(np) )
+            break;
+    }
+
+    return np;
+}
+
+void __init dt_unflatten_host_device_tree(void)
+{
+    int error = unflatten_device_tree(device_tree_flattened, &dt_host);
+
+    if ( error )
+        panic("unflatten_device_tree failed with error %d\n", error);
+
+    dt_alias_scan();
+}
+
+int dt_get_pci_domain_nr(struct dt_device_node *node)
+{
+    u32 domain;
+    int error;
+
+    error = dt_property_read_u32(node, "linux,pci-domain", &domain);
+    if ( !error )
+        return -EINVAL;
+
+    return (u16)domain;
+}
+
+/*
+ * 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.c
deleted file mode 100644
index 8d1017a49d..0000000000
--- a/xen/common/device_tree.c
+++ /dev/null
@@ -1,2253 +0,0 @@
-/*
- * Device Tree
- *
- * Copyright (C) 2012 Citrix Systems, Inc.
- * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
- * benh@kernel.crashing.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <xen/types.h>
-#include <xen/init.h>
-#include <xen/guest_access.h>
-#include <xen/device_tree.h>
-#include <xen/kernel.h>
-#include <xen/lib.h>
-#include <xen/libfdt/libfdt.h>
-#include <xen/mm.h>
-#include <xen/stdarg.h>
-#include <xen/string.h>
-#include <xen/cpumask.h>
-#include <xen/ctype.h>
-#include <asm/setup.h>
-#include <xen/err.h>
-
-const void *device_tree_flattened;
-dt_irq_xlate_func dt_irq_xlate;
-/* Host device tree */
-struct dt_device_node *dt_host;
-/* Interrupt controller node*/
-const struct dt_device_node *dt_interrupt_controller;
-DEFINE_RWLOCK(dt_host_lock);
-
-/**
- * struct dt_alias_prop - Alias property in 'aliases' node
- * @link: List node to link the structure in aliases_lookup list
- * @alias: Alias property name
- * @np: Pointer to device_node that the alias stands for
- * @id: Index value from end of alias name
- * @stem: Alias string without the index
- *
- * The structure represents one alias property of 'aliases' node as
- * an entry in aliases_lookup list.
- */
-struct dt_alias_prop {
-    struct list_head link;
-    const char *alias;
-    struct dt_device_node *np;
-    int id;
-    char stem[0];
-};
-
-static LIST_HEAD(aliases_lookup);
-
-#ifdef CONFIG_DEVICE_TREE_DEBUG
-static void dt_dump_addr(const char *s, const __be32 *addr, int na)
-{
-    dt_dprintk("%s", s);
-    while ( na-- )
-        dt_dprintk(" %08x", be32_to_cpu(*(addr++)));
-    dt_dprintk("\n");
-}
-#else
-static void dt_dump_addr(const char *s, const __be32 *addr, int na) { }
-#endif
-
-#define DT_BAD_ADDR ((u64)-1)
-
-/* Max address size we deal with */
-#define DT_MAX_ADDR_CELLS 4
-#define DT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= DT_MAX_ADDR_CELLS)
-#define DT_CHECK_COUNTS(na, ns) (DT_CHECK_ADDR_COUNT(na) && (ns) > 0)
-
-/* Callbacks for bus specific translators */
-struct dt_bus
-{
-    const char *name;
-    const char *addresses;
-    bool (*match)(const struct dt_device_node *node);
-    void (*count_cells)(const struct dt_device_node *child,
-                        int *addrc, int *sizec);
-    u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
-    int (*translate)(__be32 *addr, u64 offset, int na);
-    unsigned int (*get_flags)(const __be32 *addr);
-};
-
-void dt_get_range(const __be32 **cellp, const struct dt_device_node *np,
-                  u64 *address, u64 *size)
-{
-    *address = dt_next_cell(dt_n_addr_cells(np), cellp);
-    *size = dt_next_cell(dt_n_size_cells(np), cellp);
-}
-
-void dt_set_cell(__be32 **cellp, int size, u64 val)
-{
-    int cells = size;
-
-    while ( size-- )
-    {
-        (*cellp)[size] = cpu_to_fdt32(val);
-        val >>= 32;
-    }
-
-    (*cellp) += cells;
-}
-
-void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
-                  u64 address, u64 size)
-{
-    dt_set_cell(cellp, dt_n_addr_cells(np), address);
-    dt_set_cell(cellp, dt_n_size_cells(np), size);
-}
-
-void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
-                        u64 address, u64 size)
-{
-    dt_set_cell(cellp, addrcells, address);
-    dt_set_cell(cellp, sizecells, size);
-}
-
-static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
-                                       unsigned long align)
-{
-    void *res;
-
-    *mem = ROUNDUP(*mem, align);
-    res = (void *)*mem;
-    *mem += size;
-
-    return res;
-}
-
-/* Find a property with a given name for a given node and return it. */
-const struct dt_property *dt_find_property(const struct dt_device_node *np,
-                                           const char *name, u32 *lenp)
-{
-    const struct dt_property *pp;
-
-    if ( !np )
-        return NULL;
-
-    for ( pp = np->properties; pp; pp = pp->next )
-    {
-        if ( dt_prop_cmp(pp->name, name) == 0 )
-        {
-            if ( lenp )
-                *lenp = pp->length;
-            break;
-        }
-    }
-
-    return pp;
-}
-
-const void *dt_get_property(const struct dt_device_node *np,
-                            const char *name, u32 *lenp)
-{
-    const struct dt_property *pp = dt_find_property(np, name, lenp);
-
-    return pp ? pp->value : NULL;
-}
-
-bool dt_property_read_u32(const struct dt_device_node *np,
-                          const char *name, u32 *out_value)
-{
-    u32 len;
-    const __be32 *val;
-
-    val = dt_get_property(np, name, &len);
-    if ( !val || len < sizeof(*out_value) )
-        return 0;
-
-    *out_value = be32_to_cpup(val);
-
-    return 1;
-}
-
-
-bool dt_property_read_u64(const struct dt_device_node *np,
-                          const char *name, u64 *out_value)
-{
-    u32 len;
-    const __be32 *val;
-
-    val = dt_get_property(np, name, &len);
-    if ( !val || len < sizeof(*out_value) )
-        return 0;
-
-    *out_value = dt_read_number(val, 2);
-
-    return 1;
-}
-int dt_property_read_string(const struct dt_device_node *np,
-                            const char *propname, const char **out_string)
-{
-    const struct dt_property *pp = dt_find_property(np, propname, NULL);
-
-    if ( !pp )
-        return -EINVAL;
-    if ( !pp->length )
-        return -ENODATA;
-    if ( strnlen(pp->value, pp->length) >= pp->length )
-        return -EILSEQ;
-
-    *out_string = pp->value;
-
-    return 0;
-}
-
-/**
- * dt_find_property_value_of_size
- *
- * @np:     device node from which the property value is to be read.
- * @propname:   name of the property to be searched.
- * @min:    minimum allowed length of property value
- * @max:    maximum allowed length of property value (0 means unlimited)
- * @len:    if !=NULL, actual length is written to here
- *
- * Search for a property in a device node and valid the requested size.
- *
- * Return: The property value on success, -EINVAL if the property does not
- * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
- * property data is too small or too large.
- */
-static void *dt_find_property_value_of_size(const struct dt_device_node *np,
-                                            const char *propname, u32 min,
-                                            u32 max, size_t *len)
-{
-    const struct dt_property *prop = dt_find_property(np, propname, NULL);
-
-    if ( !prop )
-        return ERR_PTR(-EINVAL);
-    if ( !prop->value )
-        return ERR_PTR(-ENODATA);
-    if ( prop->length < min )
-        return ERR_PTR(-EOVERFLOW);
-    if ( max && prop->length > max )
-        return ERR_PTR(-EOVERFLOW);
-
-    if ( len )
-        *len = prop->length;
-
-    return prop->value;
-}
-
-int dt_property_read_variable_u32_array(const struct dt_device_node *np,
-                                        const char *propname, u32 *out_values,
-                                        size_t sz_min, size_t sz_max)
-{
-    size_t sz, count;
-    const __be32 *val = dt_find_property_value_of_size(np, propname,
-                        (sz_min * sizeof(*out_values)),
-                        (sz_max * sizeof(*out_values)),
-                        &sz);
-
-    if ( IS_ERR(val) )
-        return PTR_ERR(val);
-
-    if ( !sz_max )
-        sz = sz_min;
-    else
-        sz /= sizeof(*out_values);
-
-    count = sz;
-    while ( count-- )
-        *out_values++ = be32_to_cpup(val++);
-
-    return sz;
-}
-
-int dt_property_match_string(const struct dt_device_node *np,
-                             const char *propname, const char *string)
-{
-    const struct dt_property *dtprop = dt_find_property(np, propname, NULL);
-    size_t l;
-    int i;
-    const char *p, *end;
-
-    if ( !dtprop )
-        return -EINVAL;
-    if ( !dtprop->value )
-        return -ENODATA;
-
-    p = dtprop->value;
-    end = p + dtprop->length;
-
-    for ( i = 0; p < end; i++, p += l )
-    {
-        l = strnlen(p, end - p) + 1;
-        if ( p + l > end )
-            return -EILSEQ;
-        if ( strcmp(string, p) == 0 )
-            return i; /* Found it; return index */
-    }
-    return -ENODATA;
-}
-
-bool dt_device_is_compatible(const struct dt_device_node *device,
-                             const char *compat)
-{
-    const char* cp;
-    u32 cplen, l;
-
-    cp = dt_get_property(device, "compatible", &cplen);
-    if ( cp == NULL )
-        return 0;
-    while ( cplen > 0 )
-    {
-        if ( dt_compat_cmp(cp, compat) == 0 )
-            return 1;
-        l = strlen(cp) + 1;
-        cp += l;
-        cplen -= l;
-    }
-
-    return 0;
-}
-
-bool dt_machine_is_compatible(const char *compat)
-{
-    const struct dt_device_node *root;
-    bool rc = false;
-
-    root = dt_find_node_by_path("/");
-    if ( root )
-    {
-        rc = dt_device_is_compatible(root, compat);
-    }
-    return rc;
-}
-
-struct dt_device_node *dt_find_node_by_name(struct dt_device_node *from,
-                                            const char *name)
-{
-    struct dt_device_node *np;
-    struct dt_device_node *dt;
-
-    dt = from ? from->allnext : dt_host;
-    dt_for_each_device_node(dt, np)
-        if ( np->name && (dt_node_cmp(np->name, name) == 0) )
-            break;
-
-    return np;
-}
-
-struct dt_device_node *dt_find_node_by_type(struct dt_device_node *from,
-                                            const char *type)
-{
-    struct dt_device_node *np;
-    struct dt_device_node *dt;
-
-    dt = from ? from->allnext : dt_host;
-    dt_for_each_device_node(dt, np)
-        if ( np->type && (dt_node_cmp(np->type, type) == 0) )
-            break;
-
-    return np;
-}
-
-struct dt_device_node *dt_find_node_by_path_from(struct dt_device_node *from,
-                                                 const char *path)
-{
-    struct dt_device_node *np;
-
-    dt_for_each_device_node(from, np)
-        if ( np->full_name && (dt_node_cmp(np->full_name, path) == 0) )
-            break;
-
-    return np;
-}
-
-int dt_find_node_by_gpath(XEN_GUEST_HANDLE(char) u_path, uint32_t u_plen,
-                          struct dt_device_node **node)
-{
-    char *path;
-
-    path = safe_copy_string_from_guest(u_path, u_plen, PAGE_SIZE);
-    if ( IS_ERR(path) )
-        return PTR_ERR(path);
-
-    *node = dt_find_node_by_path(path);
-
-    xfree(path);
-
-    return (*node == NULL) ? -ESRCH : 0;
-}
-
-struct dt_device_node *dt_find_node_by_alias(const char *alias)
-{
-    const struct dt_alias_prop *app;
-
-    list_for_each_entry( app, &aliases_lookup, link )
-    {
-        if ( !strcmp(app->alias, alias) )
-            return app->np;
-    }
-
-    return NULL;
-}
-
-const struct dt_device_match *
-dt_match_node(const struct dt_device_match *matches,
-              const struct dt_device_node *node)
-{
-    if ( !matches )
-        return NULL;
-
-    while ( matches->path || matches->type ||
-            matches->compatible || matches->not_available || matches->prop )
-    {
-        bool match = true;
-
-        if ( matches->path )
-            match &= dt_node_path_is_equal(node, matches->path);
-
-        if ( matches->type )
-            match &= dt_device_type_is_equal(node, matches->type);
-
-        if ( matches->compatible )
-            match &= dt_device_is_compatible(node, matches->compatible);
-
-        if ( matches->not_available )
-            match &= !dt_device_is_available(node);
-
-        if ( matches->prop )
-            match &= dt_find_property(node, matches->prop, NULL) != NULL;
-
-        if ( match )
-            return matches;
-        matches++;
-    }
-
-    return NULL;
-}
-
-const struct dt_device_node *dt_get_parent(const struct dt_device_node *node)
-{
-    if ( !node )
-        return NULL;
-
-    return node->parent;
-}
-
-struct dt_device_node *
-dt_find_compatible_node(struct dt_device_node *from,
-                        const char *type,
-                        const char *compatible)
-{
-    struct dt_device_node *np;
-    struct dt_device_node *dt;
-
-    dt = from ? from->allnext : dt_host;
-    dt_for_each_device_node(dt, np)
-    {
-        if ( type
-             && !(np->type && (dt_node_cmp(np->type, type) == 0)) )
-            continue;
-        if ( dt_device_is_compatible(np, compatible) )
-            break;
-    }
-
-    return np;
-}
-
-struct dt_device_node *
-dt_find_matching_node(struct dt_device_node *from,
-                      const struct dt_device_match *matches)
-{
-    struct dt_device_node *np;
-    struct dt_device_node *dt;
-
-    dt = from ? from->allnext : dt_host;
-    dt_for_each_device_node(dt, np)
-    {
-        if ( dt_match_node(matches, np) )
-            return np;
-    }
-
-    return NULL;
-}
-
-static int __dt_n_addr_cells(const struct dt_device_node *np, bool parent)
-{
-    const __be32 *ip;
-
-    do {
-        if ( np->parent && !parent )
-            np = np->parent;
-        parent = false;
-
-        ip = dt_get_property(np, "#address-cells", NULL);
-        if ( ip )
-            return be32_to_cpup(ip);
-    } while ( np->parent );
-    /* No #address-cells property for the root node */
-    return DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
-}
-
-static int __dt_n_size_cells(const struct dt_device_node *np, bool parent)
-{
-    const __be32 *ip;
-
-    do {
-        if ( np->parent && !parent )
-            np = np->parent;
-        parent = false;
-
-        ip = dt_get_property(np, "#size-cells", NULL);
-        if ( ip )
-            return be32_to_cpup(ip);
-    } while ( np->parent );
-    /* No #address-cells property for the root node */
-    return DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
-}
-
-int dt_n_addr_cells(const struct dt_device_node *np)
-{
-    return __dt_n_addr_cells(np, false);
-}
-
-int dt_n_size_cells(const struct dt_device_node *np)
-{
-    return __dt_n_size_cells(np, false);
-}
-
-int dt_child_n_addr_cells(const struct dt_device_node *parent)
-{
-    return __dt_n_addr_cells(parent, true);
-}
-
-int dt_child_n_size_cells(const struct dt_device_node *parent)
-{
-    return __dt_n_size_cells(parent, true);
-}
-
-/*
- * These are defined in Linux where much of this code comes from, but
- * are currently unused outside this file in the context of Xen.
- */
-#define IORESOURCE_BITS         0x000000ff      /* Bus-specific bits */
-
-#define IORESOURCE_TYPE_BITS    0x00001f00      /* Resource type */
-#define IORESOURCE_IO           0x00000100      /* PCI/ISA I/O ports */
-#define IORESOURCE_MEM          0x00000200
-#define IORESOURCE_REG          0x00000300      /* Register offsets */
-#define IORESOURCE_IRQ          0x00000400
-#define IORESOURCE_DMA          0x00000800
-#define IORESOURCE_BUS          0x00001000
-
-#define IORESOURCE_PREFETCH     0x00002000      /* No side effects */
-#define IORESOURCE_READONLY     0x00004000
-#define IORESOURCE_CACHEABLE    0x00008000
-#define IORESOURCE_RANGELENGTH  0x00010000
-#define IORESOURCE_SHADOWABLE   0x00020000
-
-/*
- * Default translator (generic bus)
- */
-static bool dt_bus_default_match(const struct dt_device_node *node)
-{
-    /* Root node doesn't have "ranges" property */
-    if ( node->parent == NULL )
-        return 1;
-
-    /* The default bus is only used when the "ranges" property exists.
-     * Otherwise we can't translate the address
-     */
-    return (dt_get_property(node, "ranges", NULL) != NULL);
-}
-
-static void dt_bus_default_count_cells(const struct dt_device_node *dev,
-                                int *addrc, int *sizec)
-{
-    if ( addrc )
-        *addrc = dt_n_addr_cells(dev);
-    if ( sizec )
-        *sizec = dt_n_size_cells(dev);
-}
-
-static u64 dt_bus_default_map(__be32 *addr, const __be32 *range,
-                              int na, int ns, int pna)
-{
-    u64 cp, s, da;
-
-    cp = dt_read_number(range, na);
-    s = dt_read_number(range + na + pna, ns);
-    da = dt_read_number(addr, na);
-
-    dt_dprintk("DT: default map, cp=%llx, s=%llx, da=%llx\n",
-               (unsigned long long)cp, (unsigned long long)s,
-               (unsigned long long)da);
-
-    /*
-     * If the number of address cells is larger than 2 we assume the
-     * mapping doesn't specify a physical address. Rather, the address
-     * specifies an identifier that must match exactly.
-     */
-    if ( na > 2 && memcmp(range, addr, na * 4) != 0 )
-        return DT_BAD_ADDR;
-
-    if ( da < cp || da >= (cp + s) )
-        return DT_BAD_ADDR;
-    return da - cp;
-}
-
-static int dt_bus_default_translate(__be32 *addr, u64 offset, int na)
-{
-    u64 a = dt_read_number(addr, na);
-
-    memset(addr, 0, na * 4);
-    a += offset;
-    if ( na > 1 )
-        addr[na - 2] = cpu_to_be32(a >> 32);
-    addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
-
-    return 0;
-}
-static unsigned int dt_bus_default_get_flags(const __be32 *addr)
-{
-    return IORESOURCE_MEM;
-}
-
-/*
- * PCI bus specific translator
- */
-
-static bool dt_node_is_pci(const struct dt_device_node *np)
-{
-    bool is_pci = !strcmp(np->name, "pcie") || !strcmp(np->name, "pci");
-
-    if ( is_pci )
-        printk(XENLOG_WARNING "%s: Missing device_type\n", np->full_name);
-
-    return is_pci;
-}
-
-static bool dt_bus_pci_match(const struct dt_device_node *np)
-{
-    /*
-     * "pciex" is PCI Express "vci" is for the /chaos bridge on 1st-gen PCI
-     * powermacs "ht" is hypertransport
-     *
-     * If none of the device_type match, and that the node name is
-     * "pcie" or "pci", accept the device as PCI (with a warning).
-     */
-    return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") ||
-        !strcmp(np->type, "vci") || !strcmp(np->type, "ht") ||
-        dt_node_is_pci(np);
-}
-
-static void dt_bus_pci_count_cells(const struct dt_device_node *np,
-				   int *addrc, int *sizec)
-{
-    if (addrc)
-        *addrc = 3;
-    if (sizec)
-        *sizec = 2;
-}
-
-static unsigned int dt_bus_pci_get_flags(const __be32 *addr)
-{
-    unsigned int flags = 0;
-    u32 w = be32_to_cpup(addr);
-
-    switch((w >> 24) & 0x03) {
-    case 0x01:
-        flags |= IORESOURCE_IO;
-        break;
-    case 0x02: /* 32 bits */
-    case 0x03: /* 64 bits */
-        flags |= IORESOURCE_MEM;
-        break;
-    }
-    if (w & 0x40000000)
-        flags |= IORESOURCE_PREFETCH;
-    return flags;
-}
-
-static u64 dt_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
-		int pna)
-{
-    u64 cp, s, da;
-    unsigned int af, rf;
-
-    af = dt_bus_pci_get_flags(addr);
-    rf = dt_bus_pci_get_flags(range);
-
-    /* Check address type match */
-    if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
-        return DT_BAD_ADDR;
-
-    /* Read address values, skipping high cell */
-    cp = dt_read_number(range + 1, na - 1);
-    s  = dt_read_number(range + na + pna, ns);
-    da = dt_read_number(addr + 1, na - 1);
-
-    dt_dprintk("DT: PCI map, cp=%llx, s=%llx, da=%llx\n",
-               (unsigned long long)cp, (unsigned long long)s,
-               (unsigned long long)da);
-
-    if (da < cp || da >= (cp + s))
-        return DT_BAD_ADDR;
-    return da - cp;
-}
-
-static int dt_bus_pci_translate(__be32 *addr, u64 offset, int na)
-{
-    return dt_bus_default_translate(addr + 1, offset, na - 1);
-}
-
-/*
- * Array of bus specific translators
- */
-static const struct dt_bus dt_busses[] =
-{
-    /* PCI */
-    {
-        .name = "pci",
-        .addresses = "assigned-addresses",
-        .match = dt_bus_pci_match,
-        .count_cells = dt_bus_pci_count_cells,
-        .map = dt_bus_pci_map,
-        .translate = dt_bus_pci_translate,
-        .get_flags = dt_bus_pci_get_flags,
-    },
-    /* Default */
-    {
-        .name = "default",
-        .addresses = "reg",
-        .match = dt_bus_default_match,
-        .count_cells = dt_bus_default_count_cells,
-        .map = dt_bus_default_map,
-        .translate = dt_bus_default_translate,
-        .get_flags = dt_bus_default_get_flags,
-    },
-};
-
-static const struct dt_bus *dt_match_bus(const struct dt_device_node *np)
-{
-    int i;
-
-    for ( i = 0; i < ARRAY_SIZE(dt_busses); i++ )
-        if ( !dt_busses[i].match || dt_busses[i].match(np) )
-            return &dt_busses[i];
-
-    return NULL;
-}
-
-static const __be32 *dt_get_address(const struct dt_device_node *dev,
-                                    unsigned int index, u64 *size,
-                                    unsigned int *flags)
-{
-    const __be32 *prop;
-    u32 psize;
-    const struct dt_device_node *parent;
-    const struct dt_bus *bus;
-    int onesize, i, na, ns;
-
-    /* Get parent & match bus type */
-    parent = dt_get_parent(dev);
-    if ( parent == NULL )
-        return NULL;
-
-    bus = dt_match_bus(parent);
-    if ( !bus )
-        return NULL;
-    bus->count_cells(dev, &na, &ns);
-
-    if ( !DT_CHECK_ADDR_COUNT(na) )
-        return NULL;
-
-    /* Get "reg" or "assigned-addresses" property */
-    prop = dt_get_property(dev, bus->addresses, &psize);
-    if ( prop == NULL )
-        return NULL;
-    psize /= 4;
-
-    onesize = na + ns;
-    for ( i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++ )
-    {
-        if ( i == index )
-        {
-            if ( size )
-                *size = dt_read_number(prop + na, ns);
-            if ( flags )
-                *flags = bus->get_flags(prop);
-            return prop;
-        }
-    }
-    return NULL;
-}
-
-static int dt_translate_one(const struct dt_device_node *parent,
-                            const struct dt_bus *bus,
-                            const struct dt_bus *pbus,
-                            __be32 *addr, int na, int ns,
-                            int pna, const char *rprop)
-{
-    const __be32 *ranges;
-    unsigned int rlen;
-    int rone;
-    u64 offset = DT_BAD_ADDR;
-
-    ranges = dt_get_property(parent, rprop, &rlen);
-    if ( ranges == NULL )
-    {
-        printk(XENLOG_ERR "DT: no ranges; cannot translate\n");
-        return 1;
-    }
-    if ( rlen == 0 )
-    {
-        offset = dt_read_number(addr, na);
-        memset(addr, 0, pna * 4);
-        dt_dprintk("DT: empty ranges; 1:1 translation\n");
-        goto finish;
-    }
-
-    dt_dprintk("DT: walking ranges...\n");
-
-    /* Now walk through the ranges */
-    rlen /= 4;
-    rone = na + pna + ns;
-    for ( ; rlen >= rone; rlen -= rone, ranges += rone )
-    {
-        offset = bus->map(addr, ranges, na, ns, pna);
-        if ( offset != DT_BAD_ADDR )
-            break;
-    }
-    if ( offset == DT_BAD_ADDR )
-    {
-        dt_dprintk("DT: not found !\n");
-        return 1;
-    }
-    memcpy(addr, ranges + na, 4 * pna);
-
-finish:
-    dt_dump_addr("DT: parent translation for:", addr, pna);
-    dt_dprintk("DT: with offset: %llx\n", (unsigned long long)offset);
-
-    /* Translate it into parent bus space */
-    return pbus->translate(addr, offset, pna);
-}
-
-/*
- * Translate an address from the device-tree into a CPU physical address,
- * this walks up the tree and applies the various bus mappings on the
- * way.
- *
- * Note: We consider that crossing any level with #size-cells == 0 to mean
- * that translation is impossible (that is we are not dealing with a value
- * that can be mapped to a cpu physical address). This is not really specified
- * that way, but this is traditionally the way IBM at least do things
- */
-static u64 __dt_translate_address(const struct dt_device_node *dev,
-                                  const __be32 *in_addr, const char *rprop)
-{
-    const struct dt_device_node *parent = NULL;
-    const struct dt_bus *bus, *pbus;
-    __be32 addr[DT_MAX_ADDR_CELLS];
-    int na, ns, pna, pns;
-    u64 result = DT_BAD_ADDR;
-
-    dt_dprintk("DT: ** translation for device %s **\n", dev->full_name);
-
-    /* Get parent & match bus type */
-    parent = dt_get_parent(dev);
-    if ( parent == NULL )
-        goto bail;
-    bus = dt_match_bus(parent);
-    if ( !bus )
-        goto bail;
-
-    /* Count address cells & copy address locally */
-    bus->count_cells(dev, &na, &ns);
-    if ( !DT_CHECK_COUNTS(na, ns) )
-    {
-        printk(XENLOG_ERR "dt_parse: Bad cell count for device %s\n",
-                  dev->full_name);
-        goto bail;
-    }
-    memcpy(addr, in_addr, na * 4);
-
-    dt_dprintk("DT: bus is %s (na=%d, ns=%d) on %s\n",
-               bus->name, na, ns, parent->full_name);
-    dt_dump_addr("DT: translating address:", addr, na);
-
-    /* Translate */
-    for ( ;; )
-    {
-        /* Switch to parent bus */
-        dev = parent;
-        parent = dt_get_parent(dev);
-
-        /* If root, we have finished */
-        if ( parent == NULL )
-        {
-            dt_dprintk("DT: reached root node\n");
-            result = dt_read_number(addr, na);
-            break;
-        }
-
-        /* Get new parent bus and counts */
-        pbus = dt_match_bus(parent);
-        if ( pbus == NULL )
-        {
-            printk("DT: %s is not a valid bus\n", parent->full_name);
-            break;
-        }
-        pbus->count_cells(dev, &pna, &pns);
-        if ( !DT_CHECK_COUNTS(pna, pns) )
-        {
-            printk(XENLOG_ERR "dt_parse: Bad cell count for parent %s\n",
-                   dev->full_name);
-            break;
-        }
-
-        dt_dprintk("DT: parent bus is %s (na=%d, ns=%d) on %s\n",
-                   pbus->name, pna, pns, parent->full_name);
-
-        /* Apply bus translation */
-        if ( dt_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop) )
-            break;
-
-        /* Complete the move up one level */
-        na = pna;
-        ns = pns;
-        bus = pbus;
-
-        dt_dump_addr("DT: one level translation:", addr, na);
-    }
-
-bail:
-    return result;
-}
-
-/* dt_device_address - Translate device tree address and return it */
-int dt_device_get_address(const struct dt_device_node *dev, unsigned int index,
-                          u64 *addr, u64 *size)
-{
-    const __be32 *addrp;
-    unsigned int flags;
-
-    addrp = dt_get_address(dev, index, size, &flags);
-    if ( addrp == NULL )
-        return -EINVAL;
-
-    if ( !addr )
-        return -EINVAL;
-
-    *addr = __dt_translate_address(dev, addrp, "ranges");
-
-    if ( *addr == DT_BAD_ADDR )
-        return -EINVAL;
-
-    return 0;
-}
-
-int dt_device_get_paddr(const struct dt_device_node *dev, unsigned int index,
-                        paddr_t *addr, paddr_t *size)
-{
-    uint64_t dt_addr, dt_size;
-    int ret;
-
-    ret = dt_device_get_address(dev, index, &dt_addr, &dt_size);
-    if ( ret )
-        return ret;
-
-    if ( !addr )
-        return -EINVAL;
-
-    if ( dt_addr != (paddr_t)dt_addr )
-    {
-        printk("Error: Physical address 0x%"PRIx64" for node=%s is greater than max width (%zu bytes) supported\n",
-               dt_addr, dev->name, sizeof(paddr_t));
-        return -ERANGE;
-    }
-
-    *addr = dt_addr;
-
-    if ( size )
-    {
-        if ( dt_size != (paddr_t)dt_size )
-        {
-            printk("Error: Physical size 0x%"PRIx64" for node=%s is greater than max width (%zu bytes) supported\n",
-                   dt_size, dev->name, sizeof(paddr_t));
-            return -ERANGE;
-        }
-
-        *size = dt_size;
-    }
-
-    return ret;
-}
-
-int dt_for_each_range(const struct dt_device_node *dev,
-                      int (*cb)(const struct dt_device_node *dev,
-                                uint64_t addr, uint64_t length,
-                                void *data),
-                      void *data)
-{
-    const struct dt_device_node *parent = NULL;
-    const struct dt_bus *bus, *pbus;
-    const __be32 *ranges;
-    __be32 addr[DT_MAX_ADDR_CELLS];
-    unsigned int rlen;
-    int na, ns, pna, pns, rone;
-
-    bus = dt_match_bus(dev);
-    if ( !bus )
-        return 0; /* device is not a bus */
-
-    parent = dt_get_parent(dev);
-    if ( parent == NULL )
-        return -EINVAL;
-
-    ranges = dt_get_property(dev, "ranges", &rlen);
-    if ( ranges == NULL )
-    {
-        printk(XENLOG_ERR "DT: no ranges; cannot enumerate %s\n",
-               dev->full_name);
-        return -EINVAL;
-    }
-    if ( rlen == 0 ) /* Nothing to do */
-        return 0;
-
-    bus->count_cells(dev, &na, &ns);
-    if ( !DT_CHECK_COUNTS(na, ns) )
-    {
-        printk(XENLOG_ERR "dt_parse: Bad cell count for device %s\n",
-                  dev->full_name);
-        return -EINVAL;
-    }
-
-    pbus = dt_match_bus(parent);
-    if ( pbus == NULL )
-    {
-        printk("DT: %s is not a valid bus\n", parent->full_name);
-        return -EINVAL;
-    }
-
-    pbus->count_cells(dev, &pna, &pns);
-    if ( !DT_CHECK_COUNTS(pna, pns) )
-    {
-        printk(XENLOG_ERR "dt_parse: Bad cell count for parent %s\n",
-               dev->full_name);
-        return -EINVAL;
-    }
-
-    /* Now walk through the ranges */
-    rlen /= 4;
-    rone = na + pna + ns;
-
-    dt_dprintk("%s: dev=%s, bus=%s, parent=%s, rlen=%d, rone=%d\n",
-               __func__,
-               dt_node_name(dev), bus->name,
-               dt_node_name(parent), rlen, rone);
-
-    for ( ; rlen >= rone; rlen -= rone, ranges += rone )
-    {
-        uint64_t a, s;
-        int ret;
-
-        memcpy(addr, ranges + na, 4 * pna);
-
-        a = __dt_translate_address(dev, addr, "ranges");
-        s = dt_read_number(ranges + na + pna, ns);
-
-        ret = cb(dev, a, s, data);
-        if ( ret )
-        {
-            dt_dprintk(" -> callback failed=%d\n", ret);
-            return ret;
-        }
-
-    }
-
-    return 0;
-}
-
-/**
- * dt_find_node_by_phandle - Find a node given a phandle
- * @handle: phandle of the node to find
- *
- * Returns a node pointer.
- */
-struct dt_device_node *dt_find_node_by_phandle(dt_phandle handle)
-{
-    struct dt_device_node *np;
-
-    dt_for_each_device_node(dt_host, np)
-        if ( np->phandle == handle )
-            break;
-
-    return np;
-}
-
-/**
- * dt_irq_find_parent - Given a device node, find its interrupt parent node
- * @child: pointer to device node
- *
- * Returns a pointer to the interrupt parent node, or NULL if the interrupt
- * parent could not be determined.
- */
-static const struct dt_device_node *
-dt_irq_find_parent(const struct dt_device_node *child)
-{
-    const struct dt_device_node *p;
-    const __be32 *parp;
-
-    do
-    {
-        parp = dt_get_property(child, "interrupt-parent", NULL);
-        if ( parp == NULL )
-            p = dt_get_parent(child);
-        else
-            p = dt_find_node_by_phandle(be32_to_cpup(parp));
-        child = p;
-    } while ( p && dt_get_property(p, "#interrupt-cells", NULL) == NULL );
-
-    return p;
-}
-
-unsigned int dt_number_of_irq(const struct dt_device_node *device)
-{
-    const struct dt_device_node *p;
-    const __be32 *intspec, *tmp;
-    u32 intsize, intlen;
-    int intnum;
-
-    dt_dprintk("dt_irq_number: dev=%s\n", device->full_name);
-
-    /* Try the new-style interrupts-extended first */
-    intnum = dt_count_phandle_with_args(device, "interrupts-extended",
-                                        "#interrupt-cells");
-    if ( intnum >= 0 )
-    {
-        dt_dprintk(" using 'interrupts-extended' property\n");
-        dt_dprintk(" intnum=%d\n", intnum);
-        return intnum;
-    }
-
-    /* Get the interrupts property */
-    intspec = dt_get_property(device, "interrupts", &intlen);
-    if ( intspec == NULL )
-        return 0;
-    intlen /= sizeof(*intspec);
-
-    dt_dprintk(" using 'interrupts' property\n");
-    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
-
-    /* Look for the interrupt parent. */
-    p = dt_irq_find_parent(device);
-    if ( p == NULL )
-        return 0;
-
-    /* Get size of interrupt specifier */
-    tmp = dt_get_property(p, "#interrupt-cells", NULL);
-    if ( tmp == NULL )
-        return 0;
-    intsize = be32_to_cpu(*tmp);
-
-    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
-
-    return (intlen / intsize);
-}
-
-unsigned int dt_number_of_address(const struct dt_device_node *dev)
-{
-    const __be32 *prop;
-    u32 psize;
-    const struct dt_device_node *parent;
-    const struct dt_bus *bus;
-    int onesize, na, ns;
-
-    /* Get parent & match bus type */
-    parent = dt_get_parent(dev);
-    if ( parent == NULL )
-        return 0;
-
-    bus = dt_match_bus(parent);
-    if ( !bus )
-        return 0;
-    bus->count_cells(dev, &na, &ns);
-
-    if ( !DT_CHECK_COUNTS(na, ns) )
-        return 0;
-
-    /* Get "reg" or "assigned-addresses" property */
-    prop = dt_get_property(dev, bus->addresses, &psize);
-    if ( prop == NULL )
-        return 0;
-
-    psize /= 4;
-    onesize = na + ns;
-
-    return (psize / onesize);
-}
-
-int dt_for_each_irq_map(const struct dt_device_node *dev,
-                        int (*cb)(const struct dt_device_node *dev,
-                                  const struct dt_irq *dt_irq,
-                                  void *data),
-                        void *data)
-{
-    const struct dt_device_node *ipar, *tnode, *old = NULL;
-    const __be32 *tmp, *imap;
-    u32 intsize = 1, addrsize, pintsize = 0, paddrsize = 0;
-    u32 imaplen;
-    int i, ret;
-
-    struct dt_raw_irq dt_raw_irq;
-    struct dt_irq dt_irq;
-
-    dt_dprintk("%s: par=%s cb=%p data=%p\n", __func__,
-               dev->full_name, cb, data);
-
-    ipar = dev;
-
-    /* First get the #interrupt-cells property of the current cursor
-     * that tells us how to interpret the passed-in intspec. If there
-     * is none, we are nice and just walk up the tree
-     */
-    do {
-        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
-        if ( tmp != NULL )
-        {
-            intsize = be32_to_cpu(*tmp);
-            break;
-        }
-        tnode = ipar;
-        ipar = dt_irq_find_parent(ipar);
-    } while ( ipar );
-    if ( ipar == NULL )
-    {
-        dt_dprintk(" -> no parent found !\n");
-        goto fail;
-    }
-
-    dt_dprintk("%s: ipar=%s, size=%d\n", __func__, ipar->full_name, intsize);
-
-    if ( intsize > DT_MAX_IRQ_SPEC )
-    {
-        dt_dprintk(" -> too many irq specifier cells\n");
-        goto fail;
-    }
-
-    /* Look for this #address-cells. We have to implement the old linux
-     * trick of looking for the parent here as some device-trees rely on it
-     */
-    old = ipar;
-    do {
-        tmp = dt_get_property(old, "#address-cells", NULL);
-        tnode = dt_get_parent(old);
-        old = tnode;
-    } while ( old && tmp == NULL );
-
-    old = NULL;
-    addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
-
-    dt_dprintk(" -> addrsize=%d\n", addrsize);
-
-    /* Now look for an interrupt-map */
-    imap = dt_get_property(dev, "interrupt-map", &imaplen);
-    /* No interrupt-map found. Ignore */
-    if ( imap == NULL )
-    {
-        dt_dprintk(" -> no map, ignoring\n");
-        return 0;
-    }
-    imaplen /= sizeof(u32);
-
-    /* Parse interrupt-map */
-    while ( imaplen > (addrsize + intsize + 1) )
-    {
-        /* skip child unit address and child interrupt specifier */
-        imap += addrsize + intsize;
-        imaplen -= addrsize + intsize;
-
-        /* Get the interrupt parent */
-        ipar = dt_find_node_by_phandle(be32_to_cpup(imap));
-        imap++;
-        --imaplen;
-
-        /* Check if not found */
-        if ( ipar == NULL )
-        {
-            dt_dprintk(" -> imap parent not found !\n");
-            goto fail;
-        }
-
-        dt_dprintk(" -> ipar %s\n", dt_node_name(ipar));
-
-        /* Get #interrupt-cells and #address-cells of new
-         * parent
-         */
-        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
-        if ( tmp == NULL )
-        {
-            dt_dprintk(" -> parent lacks #interrupt-cells!\n");
-            goto fail;
-        }
-        pintsize = be32_to_cpu(*tmp);
-        tmp = dt_get_property(ipar, "#address-cells", NULL);
-        paddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
-
-        dt_dprintk(" -> pintsize=%d, paddrsize=%d\n",
-                   pintsize, paddrsize);
-
-        if ( pintsize > DT_MAX_IRQ_SPEC )
-        {
-            dt_dprintk(" -> too many irq specifier cells in parent\n");
-            goto fail;
-        }
-
-        /* Check for malformed properties */
-        if ( imaplen < (paddrsize + pintsize) )
-            goto fail;
-
-        imap += paddrsize;
-        imaplen -= paddrsize;
-
-        dt_raw_irq.controller = ipar;
-        dt_raw_irq.size = pintsize;
-        for ( i = 0; i < pintsize; i++ )
-            dt_raw_irq.specifier[i] = dt_read_number(imap + i, 1);
-
-        if ( dt_raw_irq.controller != dt_interrupt_controller )
-        {
-            /*
-             * We don't map IRQs connected to secondary IRQ controllers as
-             * these IRQs have no meaning to us until they connect to the
-             * primary controller.
-             *
-             * Secondary IRQ controllers will at some point connect to
-             * the primary controller (possibly via other IRQ controllers).
-             * We map the IRQs at that last connection point.
-             */
-            imap += pintsize;
-            imaplen -= pintsize;
-            dt_dprintk(" -> Skipped IRQ for secondary IRQ controller\n");
-            continue;
-        }
-
-        ret = dt_irq_translate(&dt_raw_irq, &dt_irq);
-        if ( ret )
-        {
-            dt_dprintk(" -> failed to translate IRQ: %d\n", ret);
-            return ret;
-        }
-
-        ret = cb(dev, &dt_irq, data);
-        if ( ret )
-        {
-            dt_dprintk(" -> callback failed=%d\n", ret);
-            return ret;
-        }
-
-        imap += pintsize;
-        imaplen -= pintsize;
-
-        dt_dprintk(" -> imaplen=%d\n", imaplen);
-    }
-
-    return 0;
-
-fail:
-    return -EINVAL;
-}
-
-/**
- * dt_irq_map_raw - Low level interrupt tree parsing
- * @parent:     the device interrupt parent
- * @intspec:    interrupt specifier ("interrupts" property of the device)
- * @ointsize:   size of the passed in interrupt specifier
- * @addr:       address specifier (start of "reg" property of the device)
- * @oirq:       structure dt_raw_irq filled by this function
- *
- * Returns 0 on success and a negative number on error
- *
- * This function is a low-level interrupt tree walking function. It
- * can be used to do a partial walk with synthesized reg and interrupts
- * properties, for example when resolving PCI interrupts when no device
- * node exist for the parent.
- */
-static int dt_irq_map_raw(const struct dt_device_node *parent,
-                          const __be32 *intspec, u32 ointsize,
-                          const __be32 *addr,
-                          struct dt_raw_irq *oirq)
-{
-    const struct dt_device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
-    const __be32 *tmp, *imap, *imask;
-    u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
-    u32 imaplen;
-    int match, i;
-
-    dt_dprintk("dt_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
-               parent->full_name, be32_to_cpup(intspec),
-               be32_to_cpup(intspec + 1), ointsize);
-
-    ipar = parent;
-
-    /* First get the #interrupt-cells property of the current cursor
-     * that tells us how to interpret the passed-in intspec. If there
-     * is none, we are nice and just walk up the tree
-     */
-    do {
-        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
-        if ( tmp != NULL )
-        {
-            intsize = be32_to_cpu(*tmp);
-            break;
-        }
-        tnode = ipar;
-        ipar = dt_irq_find_parent(ipar);
-    } while ( ipar );
-    if ( ipar == NULL )
-    {
-        dt_dprintk(" -> no parent found !\n");
-        goto fail;
-    }
-
-    dt_dprintk("dt_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
-
-    if ( ointsize != intsize )
-        return -EINVAL;
-
-    /* Look for this #address-cells. We have to implement the old linux
-     * trick of looking for the parent here as some device-trees rely on it
-     */
-    old = ipar;
-    do {
-        tmp = dt_get_property(old, "#address-cells", NULL);
-        tnode = dt_get_parent(old);
-        old = tnode;
-    } while ( old && tmp == NULL );
-
-    old = NULL;
-    addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
-
-    dt_dprintk(" -> addrsize=%d\n", addrsize);
-
-    /* Now start the actual "proper" walk of the interrupt tree */
-    while ( ipar != NULL )
-    {
-        /* Now check if cursor is an interrupt-controller and if it is
-         * then we are done
-         */
-        if ( dt_get_property(ipar, "interrupt-controller", NULL) != NULL )
-        {
-            dt_dprintk(" -> got it !\n");
-            if ( intsize > DT_MAX_IRQ_SPEC )
-            {
-                dt_dprintk(" -> intsize(%u) greater than DT_MAX_IRQ_SPEC(%u)\n",
-                           intsize, DT_MAX_IRQ_SPEC);
-                goto fail;
-            }
-            for ( i = 0; i < intsize; i++ )
-                oirq->specifier[i] = dt_read_number(intspec + i, 1);
-            oirq->size = intsize;
-            oirq->controller = ipar;
-            return 0;
-        }
-
-        /* Now look for an interrupt-map */
-        imap = dt_get_property(ipar, "interrupt-map", &imaplen);
-        /* No interrupt map, check for an interrupt parent */
-        if ( imap == NULL )
-        {
-            dt_dprintk(" -> no map, getting parent\n");
-            newpar = dt_irq_find_parent(ipar);
-            goto skiplevel;
-        }
-        imaplen /= sizeof(u32);
-
-        /* Look for a mask */
-        imask = dt_get_property(ipar, "interrupt-map-mask", NULL);
-
-        /* If we were passed no "reg" property and we attempt to parse
-         * an interrupt-map, then #address-cells must be 0.
-         * Fail if it's not.
-         */
-        if ( addr == NULL && addrsize != 0 )
-        {
-            dt_dprintk(" -> no reg passed in when needed !\n");
-            goto fail;
-        }
-
-        /* Parse interrupt-map */
-        match = 0;
-        while ( imaplen > (addrsize + intsize + 1) && !match )
-        {
-            /* Compare specifiers */
-            match = 1;
-            for ( i = 0; i < addrsize && match; ++i )
-            {
-                __be32 mask = imask ? imask[i] : cpu_to_be32(0xffffffffu);
-                match = ((addr[i] ^ imap[i]) & mask) == 0;
-            }
-            for ( ; i < (addrsize + intsize) && match; ++i )
-            {
-                __be32 mask = imask ? imask[i] : cpu_to_be32(0xffffffffu);
-                match = ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
-            }
-            imap += addrsize + intsize;
-            imaplen -= addrsize + intsize;
-
-            dt_dprintk(" -> match=%d (imaplen=%d)\n", match, imaplen);
-
-            /* Get the interrupt parent */
-            newpar = dt_find_node_by_phandle(be32_to_cpup(imap));
-            imap++;
-            --imaplen;
-
-            /* Check if not found */
-            if ( newpar == NULL )
-            {
-                dt_dprintk(" -> imap parent not found !\n");
-                goto fail;
-            }
-
-            /* Get #interrupt-cells and #address-cells of new
-             * parent
-             */
-            tmp = dt_get_property(newpar, "#interrupt-cells", NULL);
-            if ( tmp == NULL )
-            {
-                dt_dprintk(" -> parent lacks #interrupt-cells!\n");
-                goto fail;
-            }
-            newintsize = be32_to_cpu(*tmp);
-            tmp = dt_get_property(newpar, "#address-cells", NULL);
-            newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
-
-            dt_dprintk(" -> newintsize=%d, newaddrsize=%d\n",
-                       newintsize, newaddrsize);
-
-            /* Check for malformed properties */
-            if ( imaplen < (newaddrsize + newintsize) )
-                goto fail;
-
-            imap += newaddrsize + newintsize;
-            imaplen -= newaddrsize + newintsize;
-
-            dt_dprintk(" -> imaplen=%d\n", imaplen);
-        }
-        if ( !match )
-            goto fail;
-
-        old = newpar;
-        addrsize = newaddrsize;
-        intsize = newintsize;
-        intspec = imap - intsize;
-        addr = intspec - addrsize;
-
-    skiplevel:
-        /* Iterate again with new parent */
-        dt_dprintk(" -> new parent: %s\n", dt_node_full_name(newpar));
-        ipar = newpar;
-        newpar = NULL;
-    }
-fail:
-    return -EINVAL;
-}
-
-int dt_device_get_raw_irq(const struct dt_device_node *device,
-                          unsigned int index,
-                          struct dt_raw_irq *out_irq)
-{
-    const struct dt_device_node *p;
-    const __be32 *intspec, *tmp, *addr;
-    u32 intsize, intlen;
-    int res = -EINVAL;
-    struct dt_phandle_args args;
-    int i;
-
-    dt_dprintk("dt_device_get_raw_irq: dev=%s, index=%u\n",
-               device->full_name, index);
-
-    /* Get the reg property (if any) */
-    addr = dt_get_property(device, "reg", NULL);
-
-    /* Try the new-style interrupts-extended first */
-    res = dt_parse_phandle_with_args(device, "interrupts-extended",
-                                     "#interrupt-cells", index, &args);
-    if ( !res )
-    {
-        dt_dprintk(" using 'interrupts-extended' property\n");
-        dt_dprintk(" intspec=%d intsize=%d\n", args.args[0], args.args_count);
-
-        for ( i = 0; i < args.args_count; i++ )
-            args.args[i] = cpu_to_be32(args.args[i]);
-
-        return dt_irq_map_raw(args.np, args.args, args.args_count,
-                              addr, out_irq);
-    }
-
-    /* Get the interrupts property */
-    intspec = dt_get_property(device, "interrupts", &intlen);
-    if ( intspec == NULL )
-        return -EINVAL;
-    intlen /= sizeof(*intspec);
-
-    dt_dprintk(" using 'interrupts' property\n");
-    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
-
-    /* Look for the interrupt parent. */
-    p = dt_irq_find_parent(device);
-    if ( p == NULL )
-        return -EINVAL;
-
-    /* Get size of interrupt specifier */
-    tmp = dt_get_property(p, "#interrupt-cells", NULL);
-    if ( tmp == NULL )
-        goto out;
-    intsize = be32_to_cpu(*tmp);
-
-    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
-
-    /* Check index */
-    if ( (index + 1) * intsize > intlen )
-        goto out;
-
-    /* Get new specifier and map it */
-    res = dt_irq_map_raw(p, intspec + index * intsize, intsize,
-                         addr, out_irq);
-    if ( res )
-        goto out;
-out:
-    return res;
-}
-
-int dt_irq_translate(const struct dt_raw_irq *raw,
-                     struct dt_irq *out_irq)
-{
-    ASSERT(dt_irq_xlate != NULL);
-    ASSERT(dt_interrupt_controller != NULL);
-
-    /*
-     * TODO: Retrieve the right irq_xlate. This is only works for the primary
-     * interrupt controller.
-     */
-    if ( raw->controller != dt_interrupt_controller )
-        return -EINVAL;
-
-    return dt_irq_xlate(raw->specifier, raw->size,
-                        &out_irq->irq, &out_irq->type);
-}
-
-int dt_device_get_irq(const struct dt_device_node *device, unsigned int index,
-                      struct dt_irq *out_irq)
-{
-    struct dt_raw_irq raw;
-    int res;
-
-    res = dt_device_get_raw_irq(device, index, &raw);
-
-    if ( res )
-        return res;
-
-    return dt_irq_translate(&raw, out_irq);
-}
-
-bool dt_device_is_available(const struct dt_device_node *device)
-{
-    const char *status;
-    u32 statlen;
-
-    status = dt_get_property(device, "status", &statlen);
-    if ( status == NULL )
-        return 1;
-
-    if ( statlen > 0 )
-    {
-        if ( !strcmp(status, "okay") || !strcmp(status, "ok") )
-            return 1;
-    }
-
-    return 0;
-}
-
-bool dt_device_for_passthrough(const struct dt_device_node *device)
-{
-    return (dt_find_property(device, "xen,passthrough", NULL) != NULL);
-
-}
-
-static int __dt_parse_phandle_with_args(const struct dt_device_node *np,
-                                        const char *list_name,
-                                        const char *cells_name,
-                                        int cell_count, int index,
-                                        struct dt_phandle_args *out_args)
-{
-    const __be32 *list, *list_end;
-    int rc = 0, cur_index = 0;
-    u32 size, count = 0;
-    struct dt_device_node *node = NULL;
-    dt_phandle phandle;
-
-    /* Retrieve the phandle list property */
-    list = dt_get_property(np, list_name, &size);
-    if ( !list )
-        return -ENOENT;
-    list_end = list + size / sizeof(*list);
-
-    /* Loop over the phandles until all the requested entry is found */
-    while ( list < list_end )
-    {
-        rc = -EINVAL;
-        count = 0;
-
-        /*
-         * If phandle is 0, then it is an empty entry with no
-         * arguments.  Skip forward to the next entry.
-         * */
-        phandle = be32_to_cpup(list++);
-        if ( phandle )
-        {
-            /*
-             * Find the provider node and parse the #*-cells
-             * property to determine the argument length.
-             *
-             * This is not needed if the cell count is hard-coded
-             * (i.e. cells_name not set, but cell_count is set),
-             * except when we're going to return the found node
-             * below.
-             */
-            if ( cells_name || cur_index == index )
-            {
-                node = dt_find_node_by_phandle(phandle);
-                if ( !node )
-                {
-                    printk(XENLOG_ERR "%s: could not find phandle\n",
-                           np->full_name);
-                    goto err;
-                }
-            }
-
-            if ( cells_name )
-            {
-                if ( !dt_property_read_u32(node, cells_name, &count) )
-                {
-                    printk("%s: could not get %s for %s\n",
-                           np->full_name, cells_name, node->full_name);
-                    goto err;
-                }
-            }
-            else
-                count = cell_count;
-
-            /*
-             * Make sure that the arguments actually fit in the
-             * remaining property data length
-             */
-            if ( list + count > list_end )
-            {
-                printk(XENLOG_ERR "%s: arguments longer than property\n",
-                       np->full_name);
-                goto err;
-            }
-        }
-
-        /*
-         * All of the error cases above bail out of the loop, so at
-         * this point, the parsing is successful. If the requested
-         * index matches, then fill the out_args structure and return,
-         * or return -ENOENT for an empty entry.
-         */
-        rc = -ENOENT;
-        if ( cur_index == index )
-        {
-            if (!phandle)
-                goto err;
-
-            if ( out_args )
-            {
-                int i;
-
-                WARN_ON(count > MAX_PHANDLE_ARGS);
-                if (count > MAX_PHANDLE_ARGS)
-                    count = MAX_PHANDLE_ARGS;
-                out_args->np = node;
-                out_args->args_count = count;
-                for ( i = 0; i < count; i++ )
-                    out_args->args[i] = be32_to_cpup(list++);
-            }
-
-            /* Found it! return success */
-            return 0;
-        }
-
-        node = NULL;
-        list += count;
-        cur_index++;
-    }
-
-    /*
-     * Returning result will be one of:
-     * -ENOENT : index is for empty phandle
-     * -EINVAL : parsing error on data
-     * [1..n]  : Number of phandle (count mode; when index = -1)
-     */
-    rc = index < 0 ? cur_index : -ENOENT;
-err:
-    return rc;
-}
-
-struct dt_device_node *dt_parse_phandle(const struct dt_device_node *np,
-                                        const char *phandle_name, int index)
-{
-    struct dt_phandle_args args;
-
-    if (index < 0)
-        return NULL;
-
-    if (__dt_parse_phandle_with_args(np, phandle_name, NULL, 0,
-                                     index, &args))
-        return NULL;
-
-    return args.np;
-}
-
-
-int dt_parse_phandle_with_args(const struct dt_device_node *np,
-                               const char *list_name,
-                               const char *cells_name, int index,
-                               struct dt_phandle_args *out_args)
-{
-    if ( index < 0 )
-        return -EINVAL;
-    return __dt_parse_phandle_with_args(np, list_name, cells_name, 0,
-                                        index, out_args);
-}
-
-int dt_count_phandle_with_args(const struct dt_device_node *np,
-                               const char *list_name,
-                               const char *cells_name)
-{
-    return __dt_parse_phandle_with_args(np, list_name, cells_name, 0, -1, NULL);
-}
-
-/**
- * unflatten_dt_node - Alloc and populate a device_node from the flat tree
- * @fdt: The parent device tree blob
- * @mem: Memory chunk to use for allocating device nodes and properties
- * @p: pointer to node in flat tree
- * @dad: Parent struct device_node
- * @allnextpp: pointer to ->allnext from last allocated device_node
- * @fpsize: Size of the node path up at the current depth.
- */
-static unsigned long unflatten_dt_node(const void *fdt,
-                                       unsigned long mem,
-                                       unsigned long *p,
-                                       struct dt_device_node *dad,
-                                       struct dt_device_node ***allnextpp,
-                                       unsigned long fpsize)
-{
-    struct dt_device_node *np;
-    struct dt_property *pp, **prev_pp = NULL;
-    char *pathp;
-    u32 tag;
-    unsigned int l, allocl;
-    int has_name = 0;
-    int new_format = 0;
-
-    tag = be32_to_cpup((__be32 *)(*p));
-    if ( tag != FDT_BEGIN_NODE )
-    {
-        printk(XENLOG_WARNING "Weird tag at start of node: %x\n", tag);
-        return mem;
-    }
-    *p += 4;
-    pathp = (char *)*p;
-    l = allocl = strlen(pathp) + 1;
-    *p = ROUNDUP(*p + l, 4);
-
-    /* version 0x10 has a more compact unit name here instead of the full
-     * path. we accumulate the full path size using "fpsize", we'll rebuild
-     * it later. We detect this because the first character of the name is
-     * not '/'.
-     */
-    if ( (*pathp) != '/' )
-    {
-        new_format = 1;
-        if ( fpsize == 0 )
-        {
-            /* root node: special case. fpsize accounts for path
-             * plus terminating zero. root node only has '/', so
-             * fpsize should be 2, but we want to avoid the first
-             * level nodes to have two '/' so we use fpsize 1 here
-             */
-            fpsize = 1;
-            allocl = 2;
-        }
-        else
-        {
-            /* account for '/' and path size minus terminal 0
-             * already in 'l'
-             */
-            fpsize += l;
-            allocl = fpsize;
-        }
-    }
-
-    np = unflatten_dt_alloc(&mem, sizeof(struct dt_device_node) + allocl,
-                            __alignof__(struct dt_device_node));
-    if ( allnextpp )
-    {
-        memset(np, 0, sizeof(*np));
-        np->full_name = ((char *)np) + sizeof(struct dt_device_node);
-        /* By default dom0 owns the device */
-        np->used_by = 0;
-        /* By default the device is not protected */
-        np->is_protected = false;
-        INIT_LIST_HEAD(&np->domain_list);
-
-        if ( new_format )
-        {
-            char *fn = np->full_name;
-            /* rebuild full path for new format */
-            if ( dad && dad->parent )
-            {
-                strlcpy(fn, dad->full_name, allocl);
-#ifdef DEBUG_DT
-                if ( (strlen(fn) + l + 1) != allocl )
-                {
-                    dt_dprintk("%s: p: %d, l: %d, a: %d\n",
-                               pathp, (int)strlen(fn),
-                               l, allocl);
-                }
-#endif
-                fn += strlen(fn);
-            }
-            *(fn++) = '/';
-            memcpy(fn, pathp, l);
-        }
-        else
-            memcpy(np->full_name, pathp, l);
-        prev_pp = &np->properties;
-        **allnextpp = np;
-        *allnextpp = &np->allnext;
-        if ( dad != NULL )
-        {
-            np->parent = dad;
-            /* we temporarily use the next field as `last_child'*/
-            if ( dad->next == NULL )
-                dad->child = np;
-            else
-                dad->next->sibling = np;
-            dad->next = np;
-        }
-    }
-    /* process properties */
-    while ( 1 )
-    {
-        u32 sz, noff;
-        const char *pname;
-
-        tag = be32_to_cpup((__be32 *)(*p));
-        if ( tag == FDT_NOP )
-        {
-            *p += 4;
-            continue;
-        }
-        if ( tag != FDT_PROP )
-            break;
-        *p += 4;
-        sz = be32_to_cpup((__be32 *)(*p));
-        noff = be32_to_cpup((__be32 *)((*p) + 4));
-        *p += 8;
-        if ( fdt_version(fdt) < 0x10 )
-            *p = ROUNDUP(*p, sz >= 8 ? 8 : 4);
-
-        pname = fdt_string(fdt, noff);
-        if ( pname == NULL )
-        {
-            dt_dprintk("Can't find property name in list!\n");
-            break;
-        }
-        if ( strcmp(pname, "name") == 0 )
-            has_name = 1;
-        l = strlen(pname) + 1;
-        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property),
-                                __alignof__(struct dt_property));
-        if ( allnextpp )
-        {
-            /* We accept flattened tree phandles either in
-             * ePAPR-style "phandle" properties, or the
-             * legacy "linux,phandle" properties.  If both
-             * appear and have different values, things
-             * will get weird.  Don't do that. */
-            if ( (strcmp(pname, "phandle") == 0) ||
-                 (strcmp(pname, "linux,phandle") == 0) )
-            {
-                if ( np->phandle == 0 )
-                    np->phandle = be32_to_cpup((__be32*)*p);
-            }
-            /* And we process the "ibm,phandle" property
-             * used in pSeries dynamic device tree
-             * stuff */
-            if ( strcmp(pname, "ibm,phandle") == 0 )
-                np->phandle = be32_to_cpup((__be32 *)*p);
-            pp->name = pname;
-            pp->length = sz;
-            pp->value = (void *)*p;
-            *prev_pp = pp;
-            prev_pp = &pp->next;
-        }
-        *p = ROUNDUP((*p) + sz, 4);
-    }
-    /* with version 0x10 we may not have the name property, recreate
-     * it here from the unit name if absent
-     */
-    if ( !has_name )
-    {
-        char *p1 = pathp, *ps = pathp, *pa = NULL;
-        int sz;
-
-        while ( *p1 )
-        {
-            if ( (*p1) == '@' )
-                pa = p1;
-            if ( (*p1) == '/' )
-                ps = p1 + 1;
-            p1++;
-        }
-        if ( pa < ps )
-            pa = p1;
-        sz = (pa - ps) + 1;
-        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property) + sz,
-                                __alignof__(struct dt_property));
-        if ( allnextpp )
-        {
-            pp->name = "name";
-            pp->length = sz;
-            pp->value = pp + 1;
-            /*
-             * The device tree creation code assume that the property
-             * "name" is not a fake.
-             * To avoid a big divergence with Linux code, only remove
-             * property link. In this case we will lose a bit of memory
-             */
-#if 0
-            *prev_pp = pp;
-            prev_pp = &pp->next;
-#endif
-            np->name = pp->value;
-            memcpy(pp->value, ps, sz - 1);
-            ((char *)pp->value)[sz - 1] = 0;
-            dt_dprintk("fixed up name for %s -> %s\n", pathp,
-                       (char *)pp->value);
-            /* Generic device initialization */
-            np->dev.type = DEV_DT;
-            np->dev.of_node = np;
-        }
-    }
-    if ( allnextpp )
-    {
-        *prev_pp = NULL;
-        np->name = (np->name) ? : dt_get_property(np, "name", NULL);
-        np->type = dt_get_property(np, "device_type", NULL);
-
-        if ( !np->name )
-            np->name = "<NULL>";
-        if ( !np->type )
-            np->type = "<NULL>";
-    }
-    while ( tag == FDT_BEGIN_NODE || tag == FDT_NOP )
-    {
-        if ( tag == FDT_NOP )
-            *p += 4;
-        else
-            mem = unflatten_dt_node(fdt, mem, p, np, allnextpp, fpsize);
-        tag = be32_to_cpup((__be32 *)(*p));
-    }
-    if ( tag != FDT_END_NODE )
-    {
-        printk(XENLOG_WARNING "Weird tag at end of node: %x\n", tag);
-        return mem;
-    }
-
-    *p += 4;
-    return mem;
-}
-
-int unflatten_device_tree(const void *fdt, struct dt_device_node **mynodes)
-{
-    unsigned long start, mem, size;
-    struct dt_device_node **allnextp = mynodes;
-
-    dt_dprintk(" -> unflatten_device_tree()\n");
-
-    dt_dprintk("Unflattening device tree:\n");
-    dt_dprintk("magic: %#08x\n", fdt_magic(fdt));
-    dt_dprintk("size: %#08x\n", fdt_totalsize(fdt));
-    dt_dprintk("version: %#08x\n", fdt_version(fdt));
-
-    /* First pass, scan for size */
-    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
-    size = unflatten_dt_node(fdt, 0, &start, NULL, NULL, 0);
-    if ( !size )
-        return -EINVAL;
-
-    size = (size | 3) + 1;
-
-    dt_dprintk("  size is %#lx allocating...\n", size);
-
-    /* Allocate memory for the expanded device tree */
-    mem = (unsigned long)_xmalloc (size + 4, __alignof__(struct dt_device_node));
-    if ( !mem )
-        return -ENOMEM;
-
-    ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeefU);
-
-    dt_dprintk("  unflattening %lx...\n", mem);
-
-    /* Second pass, do actual unflattening */
-    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
-    unflatten_dt_node(fdt, mem, &start, NULL, &allnextp, 0);
-    if ( be32_to_cpup((__be32 *)start) != FDT_END )
-    {
-        printk(XENLOG_ERR "Weird tag at end of tree: %08x\n",
-                  *((u32 *)start));
-        xfree((void *)mem);
-        return -EINVAL;
-    }
-
-    if ( be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeefU )
-    {
-        printk(XENLOG_ERR "End of tree marker overwritten: %08x\n",
-                  be32_to_cpu(((__be32 *)mem)[size / 4]));
-        xfree((void *)mem);
-        return -EINVAL;
-    }
-
-    *allnextp = NULL;
-
-    dt_dprintk(" <- unflatten_device_tree()\n");
-
-    return 0;
-}
-
-static void dt_alias_add(struct dt_alias_prop *ap,
-                         struct dt_device_node *np,
-                         int id, const char *stem, int stem_len)
-{
-    ap->np = np;
-    ap->id = id;
-    strlcpy(ap->stem, stem, stem_len + 1);
-    list_add_tail(&ap->link, &aliases_lookup);
-    dt_dprintk("adding DT alias:%s: stem=%s id=%d node=%s\n",
-               ap->alias, ap->stem, ap->id, dt_node_full_name(np));
-}
-
-/**
- * dt_alias_scan - Scan all properties of 'aliases' node
- *
- * The function scans all the properties of 'aliases' node and populate
- * the the global lookup table with the properties.  It returns the
- * number of alias_prop found, or error code in error case.
- */
-static void __init dt_alias_scan(void)
-{
-    const struct dt_property *pp;
-    const struct dt_device_node *aliases;
-
-    aliases = dt_find_node_by_path("/aliases");
-    if ( !aliases )
-        return;
-
-    dt_for_each_property_node( aliases, pp )
-    {
-        const char *start = pp->name;
-        const char *end = start + strlen(start);
-        struct dt_device_node *np;
-        struct dt_alias_prop *ap;
-        int id, len;
-
-        /* Skip those we do not want to proceed */
-        if ( !strcmp(pp->name, "name") ||
-             !strcmp(pp->name, "phandle") ||
-             !strcmp(pp->name, "linux,phandle") )
-            continue;
-
-        np = dt_find_node_by_path(pp->value);
-        if ( !np )
-            continue;
-
-        /* walk the alias backwards to extract the id and work out
-         * the 'stem' string */
-        while ( isdigit(*(end-1)) && end > start )
-            end--;
-        len = end - start;
-
-        id = simple_strtoll(end, NULL, 10);
-
-        /* Allocate an alias_prop with enough space for the stem */
-        ap = _xmalloc(sizeof(*ap) + len + 1, 4);
-        if ( !ap )
-            continue;
-        ap->alias = start;
-        dt_alias_add(ap, np, id, start, len);
-    }
-}
-
-struct dt_device_node * __init
-dt_find_interrupt_controller(const struct dt_device_match *matches)
-{
-    struct dt_device_node *np = NULL;
-
-    while ( (np = dt_find_matching_node(np, matches)) )
-    {
-        if ( !dt_find_property(np, "interrupt-controller", NULL) )
-            continue;
-
-        if ( dt_get_parent(np) )
-            break;
-    }
-
-    return np;
-}
-
-void __init dt_unflatten_host_device_tree(void)
-{
-    int error = unflatten_device_tree(device_tree_flattened, &dt_host);
-
-    if ( error )
-        panic("unflatten_device_tree failed with error %d\n", error);
-
-    dt_alias_scan();
-}
-
-int dt_get_pci_domain_nr(struct dt_device_node *node)
-{
-    u32 domain;
-    int error;
-
-    error = dt_property_read_u32(node, "linux,pci-domain", &domain);
-    if ( !error )
-        return -EINVAL;
-
-    return (u16)domain;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c to common
  2024-08-05 11:33 [PATCH v1 0/2] Common device tree stuff Oleksii Kurochko
  2024-08-05 11:33 ` [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common Oleksii Kurochko
@ 2024-08-05 11:33 ` Oleksii Kurochko
  2024-08-05 19:01   ` Julien Grall
  1 sibling, 1 reply; 7+ messages in thread
From: Oleksii Kurochko @ 2024-08-05 11:33 UTC (permalink / raw)
  To: xen-devel
  Cc: Shawn Anastasio, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
	Daniel P. Smith, Oleksii Kurochko

From: Shawn Anastasio <sanastasio@raptorengineering.com>

Move Arm's bootfdt.c to xen/common so that it can be used by other
device tree architectures like PPC and RISCV.

Remove stubs for process_shm_node() and early_print_info_shmem()
from $xen/arch/arm/include/asm/static-shmem.h.
These stubs are removed to avoid introducing them for architectures
that do not support CONFIG_STATIC_SHM.
The process_shm_node() stub is now implemented in common code to
maintain the current behavior of early_scan_code() on ARM.
The early_print_info_shmem() stub is only used in early_print_info(),
so it's now guarded with #ifdef CONFIG_STATIC_SHM ... #endif.

Suggested-by: Julien Grall <julien@xen.org>
Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V8:
 - Fix the change log for this patch ( accidentally the change log of the previous
   patch was copied to this ).
 - Drop the stub of process_shm_node() and early_print_info_shmem() in
   xen/arch/arm/include/asm/static-shmem.h as it is moved to common code to not
   re-introduce the same stub for each architecture which doesn't support
   CONFIG_STATIC_SHM now.
 - Drop Acked-by: Julien Grall <julien@xen.org> as after the Ack additional changes were
   done so an additional review is needed.
---
Changes in V7:
 - Nothing changed. Only rebase.
---
Changes in V6:
 - update the version of the patch to v6.
---
Changes in v5:
 - add guard #ifdef CONFIG_STATIC_SHM around inclusion of <asm/static-shmem.h>
   in common/device-tree/bootfdt.c.
 - add stub for process_shm_node() in case CONFIG_STATIC_SHM isn't enabled.
 - add guard around #ifdef CONFIG_STATIC_SHM aroud early_print_info_shmem() in
   early_print_info().
---
Changes in v4:
  - move function prototypes to patch 2's xen/include/bootfdt.h
  - clean up #includes
---
 xen/arch/arm/Makefile                   |   1 -
 xen/arch/arm/bootfdt.c                  | 622 -----------------------
 xen/arch/arm/include/asm/setup.h        |  13 -
 xen/arch/arm/include/asm/static-shmem.h |   9 -
 xen/common/device-tree/Makefile         |   1 +
 xen/common/device-tree/bootfdt.c        | 635 ++++++++++++++++++++++++
 xen/include/xen/bootfdt.h               |  14 +
 7 files changed, 650 insertions(+), 645 deletions(-)
 delete mode 100644 xen/arch/arm/bootfdt.c
 create mode 100644 xen/common/device-tree/bootfdt.c

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 45dc29ea53..da9c979dc4 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_TEE) += tee/
 obj-$(CONFIG_HAS_VPCI) += vpci.o
 
 obj-$(CONFIG_HAS_ALTERNATIVE) += alternative.o
-obj-y += bootfdt.init.o
 obj-y += cpuerrata.o
 obj-y += cpufeature.o
 obj-y += decode.o
diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
deleted file mode 100644
index 6e060111d9..0000000000
--- a/xen/arch/arm/bootfdt.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Early Device Tree
- *
- * Copyright (C) 2012-2014 Citrix Systems, Inc.
- */
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/kernel.h>
-#include <xen/init.h>
-#include <xen/efi.h>
-#include <xen/device_tree.h>
-#include <xen/lib.h>
-#include <xen/libfdt/libfdt-xen.h>
-#include <xen/sort.h>
-#include <xsm/xsm.h>
-#include <asm/setup.h>
-#include <asm/static-shmem.h>
-
-static void __init __maybe_unused build_assertions(void)
-{
-    /*
-     * Check that no padding is between struct membanks "bank" flexible array
-     * member and struct meminfo "bank" member
-     */
-    BUILD_BUG_ON((offsetof(struct membanks, bank) !=
-                 offsetof(struct meminfo, bank)));
-    /* Ensure "struct membanks" is 8-byte aligned */
-    BUILD_BUG_ON(alignof(struct membanks) != 8);
-}
-
-static bool __init device_tree_node_is_available(const void *fdt, int node)
-{
-    const char *status;
-    int len;
-
-    status = fdt_getprop(fdt, node, "status", &len);
-    if ( !status )
-        return true;
-
-    if ( len > 0 )
-    {
-        if ( !strcmp(status, "ok") || !strcmp(status, "okay") )
-            return true;
-    }
-
-    return false;
-}
-
-static bool __init device_tree_node_matches(const void *fdt, int node,
-                                            const char *match)
-{
-    const char *name;
-    size_t match_len;
-
-    name = fdt_get_name(fdt, node, NULL);
-    match_len = strlen(match);
-
-    /* Match both "match" and "match@..." patterns but not
-       "match-foo". */
-    return strncmp(name, match, match_len) == 0
-        && (name[match_len] == '@' || name[match_len] == '\0');
-}
-
-static bool __init device_tree_node_compatible(const void *fdt, int node,
-                                               const char *match)
-{
-    int len, l;
-    const void *prop;
-
-    prop = fdt_getprop(fdt, node, "compatible", &len);
-    if ( prop == NULL )
-        return false;
-
-    while ( len > 0 ) {
-        if ( !dt_compat_cmp(prop, match) )
-            return true;
-        l = strlen(prop) + 1;
-        prop += l;
-        len -= l;
-    }
-
-    return false;
-}
-
-void __init device_tree_get_reg(const __be32 **cell, uint32_t address_cells,
-                                uint32_t size_cells, paddr_t *start,
-                                paddr_t *size)
-{
-    uint64_t dt_start, dt_size;
-
-    /*
-     * dt_next_cell will return uint64_t whereas paddr_t may not be 64-bit.
-     * Thus, there is an implicit cast from uint64_t to paddr_t.
-     */
-    dt_start = dt_next_cell(address_cells, cell);
-    dt_size = dt_next_cell(size_cells, cell);
-
-    if ( dt_start != (paddr_t)dt_start )
-    {
-        printk("Physical address greater than max width supported\n");
-        WARN();
-    }
-
-    if ( dt_size != (paddr_t)dt_size )
-    {
-        printk("Physical size greater than max width supported\n");
-        WARN();
-    }
-
-    /*
-     * Xen will truncate the address/size if it is greater than the maximum
-     * supported width and it will give an appropriate warning.
-     */
-    *start = dt_start;
-    *size = dt_size;
-}
-
-static int __init device_tree_get_meminfo(const void *fdt, int node,
-                                          const char *prop_name,
-                                          u32 address_cells, u32 size_cells,
-                                          struct membanks *mem,
-                                          enum membank_type type)
-{
-    const struct fdt_property *prop;
-    unsigned int i, banks;
-    const __be32 *cell;
-    u32 reg_cells = address_cells + size_cells;
-    paddr_t start, size;
-
-    if ( !device_tree_node_is_available(fdt, node) )
-        return 0;
-
-    if ( address_cells < 1 || size_cells < 1 )
-    {
-        printk("fdt: property `%s': invalid #address-cells or #size-cells",
-               prop_name);
-        return -EINVAL;
-    }
-
-    prop = fdt_get_property(fdt, node, prop_name, NULL);
-    if ( !prop )
-        return -ENOENT;
-
-    cell = (const __be32 *)prop->data;
-    banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));
-
-    for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ )
-    {
-        device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
-        if ( mem == bootinfo_get_reserved_mem() &&
-             check_reserved_regions_overlap(start, size) )
-            return -EINVAL;
-        /* Some DT may describe empty bank, ignore them */
-        if ( !size )
-            continue;
-        mem->bank[mem->nr_banks].start = start;
-        mem->bank[mem->nr_banks].size = size;
-        mem->bank[mem->nr_banks].type = type;
-        mem->nr_banks++;
-    }
-
-    if ( i < banks )
-    {
-        printk("Warning: Max number of supported memory regions reached.\n");
-        return -ENOSPC;
-    }
-
-    return 0;
-}
-
-u32 __init device_tree_get_u32(const void *fdt, int node,
-                               const char *prop_name, u32 dflt)
-{
-    const struct fdt_property *prop;
-
-    prop = fdt_get_property(fdt, node, prop_name, NULL);
-    if ( !prop || prop->len < sizeof(u32) )
-        return dflt;
-
-    return fdt32_to_cpu(*(uint32_t*)prop->data);
-}
-
-/**
- * device_tree_for_each_node - iterate over all device tree sub-nodes
- * @fdt: flat device tree.
- * @node: parent node to start the search from
- * @func: function to call for each sub-node.
- * @data: data to pass to @func.
- *
- * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
- *
- * Returns 0 if all nodes were iterated over successfully.  If @func
- * returns a value different from 0, that value is returned immediately.
- */
-int __init device_tree_for_each_node(const void *fdt, int node,
-                                     device_tree_node_func func,
-                                     void *data)
-{
-    /*
-     * We only care about relative depth increments, assume depth of
-     * node is 0 for simplicity.
-     */
-    int depth = 0;
-    const int first_node = node;
-    u32 address_cells[DEVICE_TREE_MAX_DEPTH];
-    u32 size_cells[DEVICE_TREE_MAX_DEPTH];
-    int ret;
-
-    do {
-        const char *name = fdt_get_name(fdt, node, NULL);
-        u32 as, ss;
-
-        if ( depth >= DEVICE_TREE_MAX_DEPTH )
-        {
-            printk("Warning: device tree node `%s' is nested too deep\n",
-                   name);
-            continue;
-        }
-
-        as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
-        ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
-
-        address_cells[depth] = device_tree_get_u32(fdt, node,
-                                                   "#address-cells", as);
-        size_cells[depth] = device_tree_get_u32(fdt, node,
-                                                "#size-cells", ss);
-
-        /* skip the first node */
-        if ( node != first_node )
-        {
-            ret = func(fdt, node, name, depth, as, ss, data);
-            if ( ret != 0 )
-                return ret;
-        }
-
-        node = fdt_next_node(fdt, node, &depth);
-    } while ( node >= 0 && depth > 0 );
-
-    return 0;
-}
-
-static int __init process_memory_node(const void *fdt, int node,
-                                      const char *name, int depth,
-                                      u32 address_cells, u32 size_cells,
-                                      struct membanks *mem)
-{
-    return device_tree_get_meminfo(fdt, node, "reg", address_cells, size_cells,
-                                   mem, MEMBANK_DEFAULT);
-}
-
-static int __init process_reserved_memory_node(const void *fdt, int node,
-                                               const char *name, int depth,
-                                               u32 address_cells,
-                                               u32 size_cells,
-                                               void *data)
-{
-    int rc = process_memory_node(fdt, node, name, depth, address_cells,
-                                 size_cells, data);
-
-    if ( rc == -ENOSPC )
-        panic("Max number of supported reserved-memory regions reached.\n");
-    else if ( rc != -ENOENT )
-        return rc;
-    return 0;
-}
-
-static int __init process_reserved_memory(const void *fdt, int node,
-                                          const char *name, int depth,
-                                          u32 address_cells, u32 size_cells)
-{
-    return device_tree_for_each_node(fdt, node,
-                                     process_reserved_memory_node,
-                                     bootinfo_get_reserved_mem());
-}
-
-static void __init process_multiboot_node(const void *fdt, int node,
-                                          const char *name,
-                                          u32 address_cells, u32 size_cells)
-{
-    static int __initdata kind_guess = 0;
-    const struct fdt_property *prop;
-    const __be32 *cell;
-    bootmodule_kind kind;
-    paddr_t start, size;
-    int len;
-    /* sizeof("/chosen/") + DT_MAX_NAME + '/' + DT_MAX_NAME + '/0' => 92 */
-    char path[92];
-    int parent_node, ret;
-    bool domU;
-
-    parent_node = fdt_parent_offset(fdt, node);
-    ASSERT(parent_node >= 0);
-
-    /* Check that the node is under "/chosen" (first 7 chars of path) */
-    ret = fdt_get_path(fdt, node, path, sizeof (path));
-    if ( ret != 0 || strncmp(path, "/chosen", 7) )
-        return;
-
-    prop = fdt_get_property(fdt, node, "reg", &len);
-    if ( !prop )
-        panic("node %s missing `reg' property\n", name);
-
-    if ( len < dt_cells_to_size(address_cells + size_cells) )
-        panic("fdt: node `%s': `reg` property length is too short\n",
-                    name);
-
-    cell = (const __be32 *)prop->data;
-    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
-
-    if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 ||
-         fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 )
-        kind = BOOTMOD_KERNEL;
-    else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 ||
-              fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 )
-        kind = BOOTMOD_RAMDISK;
-    else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 )
-        kind = BOOTMOD_XSM;
-    else if ( fdt_node_check_compatible(fdt, node, "multiboot,device-tree") == 0 )
-        kind = BOOTMOD_GUEST_DTB;
-    else
-        kind = BOOTMOD_UNKNOWN;
-
-    /**
-     * Guess the kind of these first two unknowns respectively:
-     * (1) The first unknown must be kernel.
-     * (2) Detect the XSM Magic from the 2nd unknown:
-     *     a. If it's XSM, set the kind as XSM, and that also means we
-     *     won't load ramdisk;
-     *     b. if it's not XSM, set the kind as ramdisk.
-     *     So if user want to load ramdisk, it must be the 2nd unknown.
-     * We also detect the XSM Magic for the following unknowns,
-     * then set its kind according to the return value of has_xsm_magic.
-     */
-    if ( kind == BOOTMOD_UNKNOWN )
-    {
-        switch ( kind_guess++ )
-        {
-        case 0: kind = BOOTMOD_KERNEL; break;
-        case 1: kind = BOOTMOD_RAMDISK; break;
-        default: break;
-        }
-        if ( kind_guess > 1 && has_xsm_magic(start) )
-            kind = BOOTMOD_XSM;
-    }
-
-    domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0;
-    add_boot_module(kind, start, size, domU);
-
-    prop = fdt_get_property(fdt, node, "bootargs", &len);
-    if ( !prop )
-        return;
-    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
-                     kind, start, domU);
-}
-
-static int __init process_chosen_node(const void *fdt, int node,
-                                      const char *name,
-                                      u32 address_cells, u32 size_cells)
-{
-    const struct fdt_property *prop;
-    paddr_t start, end;
-    int len;
-
-    if ( fdt_get_property(fdt, node, "xen,static-heap", NULL) )
-    {
-        int rc;
-
-        printk("Checking for static heap in /chosen\n");
-
-        rc = device_tree_get_meminfo(fdt, node, "xen,static-heap",
-                                     address_cells, size_cells,
-                                     bootinfo_get_reserved_mem(),
-                                     MEMBANK_STATIC_HEAP);
-        if ( rc )
-            return rc;
-
-        bootinfo.static_heap = true;
-    }
-
-    printk("Checking for initrd in /chosen\n");
-
-    prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
-    if ( !prop )
-        /* No initrd present. */
-        return 0;
-    if ( len != sizeof(u32) && len != sizeof(u64) )
-    {
-        printk("linux,initrd-start property has invalid length %d\n", len);
-        return -EINVAL;
-    }
-    start = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len));
-
-    prop = fdt_get_property(fdt, node, "linux,initrd-end", &len);
-    if ( !prop )
-    {
-        printk("linux,initrd-end not present but -start was\n");
-        return -EINVAL;
-    }
-    if ( len != sizeof(u32) && len != sizeof(u64) )
-    {
-        printk("linux,initrd-end property has invalid length %d\n", len);
-        return -EINVAL;
-    }
-    end = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len));
-
-    if ( start >= end )
-    {
-        printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
-                  start, end);
-        return -EINVAL;
-    }
-
-    printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
-
-    add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
-
-    return 0;
-}
-
-static int __init process_domain_node(const void *fdt, int node,
-                                      const char *name,
-                                      u32 address_cells, u32 size_cells)
-{
-    const struct fdt_property *prop;
-
-    printk("Checking for \"xen,static-mem\" in domain node\n");
-
-    prop = fdt_get_property(fdt, node, "xen,static-mem", NULL);
-    if ( !prop )
-        /* No "xen,static-mem" present. */
-        return 0;
-
-    return device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells,
-                                   size_cells, bootinfo_get_reserved_mem(),
-                                   MEMBANK_STATIC_DOMAIN);
-}
-
-static int __init early_scan_node(const void *fdt,
-                                  int node, const char *name, int depth,
-                                  u32 address_cells, u32 size_cells,
-                                  void *data)
-{
-    int rc = 0;
-
-    /*
-     * If Xen has been booted via UEFI, the memory banks are
-     * populated. So we should skip the parsing.
-     */
-    if ( !efi_enabled(EFI_BOOT) &&
-         device_tree_node_matches(fdt, node, "memory") )
-        rc = process_memory_node(fdt, node, name, depth,
-                                 address_cells, size_cells, bootinfo_get_mem());
-    else if ( depth == 1 && !dt_node_cmp(name, "reserved-memory") )
-        rc = process_reserved_memory(fdt, node, name, depth,
-                                     address_cells, size_cells);
-    else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
-              device_tree_node_compatible(fdt, node, "multiboot,module" )))
-        process_multiboot_node(fdt, node, name, address_cells, size_cells);
-    else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
-        rc = process_chosen_node(fdt, node, name, address_cells, size_cells);
-    else if ( depth == 2 && device_tree_node_compatible(fdt, node, "xen,domain") )
-        rc = process_domain_node(fdt, node, name, address_cells, size_cells);
-    else if ( depth <= 3 && device_tree_node_compatible(fdt, node, "xen,domain-shared-memory-v1") )
-        rc = process_shm_node(fdt, node, address_cells, size_cells);
-
-    if ( rc < 0 )
-        printk("fdt: node `%s': parsing failed\n", name);
-    return rc;
-}
-
-static void __init early_print_info(void)
-{
-    const struct membanks *mi = bootinfo_get_mem();
-    const struct membanks *mem_resv = bootinfo_get_reserved_mem();
-    struct bootmodules *mods = &bootinfo.modules;
-    struct bootcmdlines *cmds = &bootinfo.cmdlines;
-    unsigned int i;
-
-    for ( i = 0; i < mi->nr_banks; i++ )
-        printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n",
-                mi->bank[i].start,
-                mi->bank[i].start + mi->bank[i].size - 1);
-    printk("\n");
-    for ( i = 0 ; i < mods->nr_mods; i++ )
-        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
-                i,
-                mods->module[i].start,
-                mods->module[i].start + mods->module[i].size,
-                boot_module_kind_as_string(mods->module[i].kind));
-
-    for ( i = 0; i < mem_resv->nr_banks; i++ )
-    {
-        printk(" RESVD[%u]: %"PRIpaddr" - %"PRIpaddr"\n", i,
-               mem_resv->bank[i].start,
-               mem_resv->bank[i].start + mem_resv->bank[i].size - 1);
-    }
-    early_print_info_shmem();
-    printk("\n");
-    for ( i = 0 ; i < cmds->nr_mods; i++ )
-        printk("CMDLINE[%"PRIpaddr"]:%s %s\n", cmds->cmdline[i].start,
-               cmds->cmdline[i].dt_name,
-               &cmds->cmdline[i].cmdline[0]);
-    printk("\n");
-}
-
-/* This function assumes that memory regions are not overlapped */
-static int __init cmp_memory_node(const void *key, const void *elem)
-{
-    const struct membank *handler0 = key;
-    const struct membank *handler1 = elem;
-
-    if ( handler0->start < handler1->start )
-        return -1;
-
-    if ( handler0->start >= (handler1->start + handler1->size) )
-        return 1;
-
-    return 0;
-}
-
-static void __init swap_memory_node(void *_a, void *_b, size_t size)
-{
-    struct membank *a = _a, *b = _b;
-
-    SWAP(*a, *b);
-}
-
-/**
- * boot_fdt_info - initialize bootinfo from a DTB
- * @fdt: flattened device tree binary
- *
- * Returns the size of the DTB.
- */
-size_t __init boot_fdt_info(const void *fdt, paddr_t paddr)
-{
-    struct membanks *reserved_mem = bootinfo_get_reserved_mem();
-    struct membanks *mem = bootinfo_get_mem();
-    unsigned int i;
-    int nr_rsvd;
-    int ret;
-
-    ret = fdt_check_header(fdt);
-    if ( ret < 0 )
-        panic("No valid device tree\n");
-
-    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false);
-
-    nr_rsvd = fdt_num_mem_rsv(fdt);
-    if ( nr_rsvd < 0 )
-        panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd);
-
-    for ( i = 0; i < nr_rsvd; i++ )
-    {
-        struct membank *bank;
-        paddr_t s, sz;
-
-        if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &sz) < 0 )
-            continue;
-
-        if ( reserved_mem->nr_banks < reserved_mem->max_banks )
-        {
-            bank = &reserved_mem->bank[reserved_mem->nr_banks];
-            bank->start = s;
-            bank->size = sz;
-            bank->type = MEMBANK_FDT_RESVMEM;
-            reserved_mem->nr_banks++;
-        }
-        else
-            panic("Cannot allocate reserved memory bank\n");
-    }
-
-    ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL);
-    if ( ret )
-        panic("Early FDT parsing failed (%d)\n", ret);
-
-    /*
-     * On Arm64 setup_directmap_mappings() expects to be called with the lowest
-     * bank in memory first. There is no requirement that the DT will provide
-     * the banks sorted in ascending order. So sort them through.
-     */
-    sort(mem->bank, mem->nr_banks, sizeof(struct membank),
-         cmp_memory_node, swap_memory_node);
-
-    early_print_info();
-
-    return fdt_totalsize(fdt);
-}
-
-const __init char *boot_fdt_cmdline(const void *fdt)
-{
-    int node;
-    const struct fdt_property *prop;
-
-    node = fdt_path_offset(fdt, "/chosen");
-    if ( node < 0 )
-        return NULL;
-
-    prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
-    if ( prop == NULL )
-    {
-        struct bootcmdline *dom0_cmdline =
-            boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
-
-        if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
-            ( dom0_cmdline && dom0_cmdline->cmdline[0] ) )
-            prop = fdt_get_property(fdt, node, "bootargs", NULL);
-    }
-    if ( prop == NULL )
-        return NULL;
-
-    return prop->data;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 1748be29e5..64c227d171 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -41,19 +41,6 @@ void fw_unreserved_regions(paddr_t s, paddr_t e,
                            void (*cb)(paddr_t ps, paddr_t pe),
                            unsigned int first);
 
-bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size);
-
-struct bootmodule *add_boot_module(bootmodule_kind kind,
-                                   paddr_t start, paddr_t size, bool domU);
-struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
-struct bootmodule * boot_module_find_by_addr_and_kind(bootmodule_kind kind,
-                                                             paddr_t start);
-void add_boot_cmdline(const char *name, const char *cmdline,
-                      bootmodule_kind kind, paddr_t start, bool domU);
-struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
-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 setup_mm(void);
 
diff --git a/xen/arch/arm/include/asm/static-shmem.h b/xen/arch/arm/include/asm/static-shmem.h
index 806ee41cfc..fd0867c4f2 100644
--- a/xen/arch/arm/include/asm/static-shmem.h
+++ b/xen/arch/arm/include/asm/static-shmem.h
@@ -80,15 +80,6 @@ static inline int process_shm_chosen(struct domain *d,
     return 0;
 }
 
-static inline int process_shm_node(const void *fdt, int node,
-                                   uint32_t address_cells, uint32_t size_cells)
-{
-    printk("CONFIG_STATIC_SHM must be enabled for parsing static shared memory nodes\n");
-    return -EINVAL;
-}
-
-static inline void early_print_info_shmem(void) {};
-
 static inline void init_sharedmem_pages(void) {};
 
 static inline int remove_shm_from_rangeset(const struct kernel_info *kinfo,
diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile
index da892dd55d..22a053f184 100644
--- a/xen/common/device-tree/Makefile
+++ b/xen/common/device-tree/Makefile
@@ -1,2 +1,3 @@
+obj-y += bootfdt.init.o
 obj-y += bootinfo.init.o
 obj-y += device_tree.o
diff --git a/xen/common/device-tree/bootfdt.c b/xen/common/device-tree/bootfdt.c
new file mode 100644
index 0000000000..748b5f7c69
--- /dev/null
+++ b/xen/common/device-tree/bootfdt.c
@@ -0,0 +1,635 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Early Device Tree
+ *
+ * Copyright (C) 2012-2014 Citrix Systems, Inc.
+ */
+
+#include <xen/bootfdt.h>
+#include <xen/device_tree.h>
+#include <xen/efi.h>
+#include <xen/init.h>
+#include <xen/kernel.h>
+#include <xen/libfdt/libfdt-xen.h>
+#include <xen/sort.h>
+#include <xsm/xsm.h>
+#include <asm/setup.h>
+#ifdef CONFIG_STATIC_SHM
+#include <asm/static-shmem.h>
+#endif
+
+static void __init __maybe_unused build_assertions(void)
+{
+    /*
+     * Check that no padding is between struct membanks "bank" flexible array
+     * member and struct meminfo "bank" member
+     */
+    BUILD_BUG_ON((offsetof(struct membanks, bank) !=
+                 offsetof(struct meminfo, bank)));
+    /* Ensure "struct membanks" is 8-byte aligned */
+    BUILD_BUG_ON(alignof(struct membanks) != 8);
+}
+
+static bool __init device_tree_node_is_available(const void *fdt, int node)
+{
+    const char *status;
+    int len;
+
+    status = fdt_getprop(fdt, node, "status", &len);
+    if ( !status )
+        return true;
+
+    if ( len > 0 )
+    {
+        if ( !strcmp(status, "ok") || !strcmp(status, "okay") )
+            return true;
+    }
+
+    return false;
+}
+
+static bool __init device_tree_node_matches(const void *fdt, int node,
+                                            const char *match)
+{
+    const char *name;
+    size_t match_len;
+
+    name = fdt_get_name(fdt, node, NULL);
+    match_len = strlen(match);
+
+    /* Match both "match" and "match@..." patterns but not
+       "match-foo". */
+    return strncmp(name, match, match_len) == 0
+        && (name[match_len] == '@' || name[match_len] == '\0');
+}
+
+static bool __init device_tree_node_compatible(const void *fdt, int node,
+                                               const char *match)
+{
+    int len, l;
+    const void *prop;
+
+    prop = fdt_getprop(fdt, node, "compatible", &len);
+    if ( prop == NULL )
+        return false;
+
+    while ( len > 0 ) {
+        if ( !dt_compat_cmp(prop, match) )
+            return true;
+        l = strlen(prop) + 1;
+        prop += l;
+        len -= l;
+    }
+
+    return false;
+}
+
+void __init device_tree_get_reg(const __be32 **cell, uint32_t address_cells,
+                                uint32_t size_cells, paddr_t *start,
+                                paddr_t *size)
+{
+    uint64_t dt_start, dt_size;
+
+    /*
+     * dt_next_cell will return uint64_t whereas paddr_t may not be 64-bit.
+     * Thus, there is an implicit cast from uint64_t to paddr_t.
+     */
+    dt_start = dt_next_cell(address_cells, cell);
+    dt_size = dt_next_cell(size_cells, cell);
+
+    if ( dt_start != (paddr_t)dt_start )
+    {
+        printk("Physical address greater than max width supported\n");
+        WARN();
+    }
+
+    if ( dt_size != (paddr_t)dt_size )
+    {
+        printk("Physical size greater than max width supported\n");
+        WARN();
+    }
+
+    /*
+     * Xen will truncate the address/size if it is greater than the maximum
+     * supported width and it will give an appropriate warning.
+     */
+    *start = dt_start;
+    *size = dt_size;
+}
+
+static int __init device_tree_get_meminfo(const void *fdt, int node,
+                                          const char *prop_name,
+                                          u32 address_cells, u32 size_cells,
+                                          struct membanks *mem,
+                                          enum membank_type type)
+{
+    const struct fdt_property *prop;
+    unsigned int i, banks;
+    const __be32 *cell;
+    u32 reg_cells = address_cells + size_cells;
+    paddr_t start, size;
+
+    if ( !device_tree_node_is_available(fdt, node) )
+        return 0;
+
+    if ( address_cells < 1 || size_cells < 1 )
+    {
+        printk("fdt: property `%s': invalid #address-cells or #size-cells",
+               prop_name);
+        return -EINVAL;
+    }
+
+    prop = fdt_get_property(fdt, node, prop_name, NULL);
+    if ( !prop )
+        return -ENOENT;
+
+    cell = (const __be32 *)prop->data;
+    banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));
+
+    for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ )
+    {
+        device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+        if ( mem == bootinfo_get_reserved_mem() &&
+             check_reserved_regions_overlap(start, size) )
+            return -EINVAL;
+        /* Some DT may describe empty bank, ignore them */
+        if ( !size )
+            continue;
+        mem->bank[mem->nr_banks].start = start;
+        mem->bank[mem->nr_banks].size = size;
+        mem->bank[mem->nr_banks].type = type;
+        mem->nr_banks++;
+    }
+
+    if ( i < banks )
+    {
+        printk("Warning: Max number of supported memory regions reached.\n");
+        return -ENOSPC;
+    }
+
+    return 0;
+}
+
+u32 __init device_tree_get_u32(const void *fdt, int node,
+                               const char *prop_name, u32 dflt)
+{
+    const struct fdt_property *prop;
+
+    prop = fdt_get_property(fdt, node, prop_name, NULL);
+    if ( !prop || prop->len < sizeof(u32) )
+        return dflt;
+
+    return fdt32_to_cpu(*(uint32_t*)prop->data);
+}
+
+/**
+ * device_tree_for_each_node - iterate over all device tree sub-nodes
+ * @fdt: flat device tree.
+ * @node: parent node to start the search from
+ * @func: function to call for each sub-node.
+ * @data: data to pass to @func.
+ *
+ * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
+ *
+ * Returns 0 if all nodes were iterated over successfully.  If @func
+ * returns a value different from 0, that value is returned immediately.
+ */
+int __init device_tree_for_each_node(const void *fdt, int node,
+                                     device_tree_node_func func,
+                                     void *data)
+{
+    /*
+     * We only care about relative depth increments, assume depth of
+     * node is 0 for simplicity.
+     */
+    int depth = 0;
+    const int first_node = node;
+    u32 address_cells[DEVICE_TREE_MAX_DEPTH];
+    u32 size_cells[DEVICE_TREE_MAX_DEPTH];
+    int ret;
+
+    do {
+        const char *name = fdt_get_name(fdt, node, NULL);
+        u32 as, ss;
+
+        if ( depth >= DEVICE_TREE_MAX_DEPTH )
+        {
+            printk("Warning: device tree node `%s' is nested too deep\n",
+                   name);
+            continue;
+        }
+
+        as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
+        ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
+
+        address_cells[depth] = device_tree_get_u32(fdt, node,
+                                                   "#address-cells", as);
+        size_cells[depth] = device_tree_get_u32(fdt, node,
+                                                "#size-cells", ss);
+
+        /* skip the first node */
+        if ( node != first_node )
+        {
+            ret = func(fdt, node, name, depth, as, ss, data);
+            if ( ret != 0 )
+                return ret;
+        }
+
+        node = fdt_next_node(fdt, node, &depth);
+    } while ( node >= 0 && depth > 0 );
+
+    return 0;
+}
+
+static int __init process_memory_node(const void *fdt, int node,
+                                      const char *name, int depth,
+                                      u32 address_cells, u32 size_cells,
+                                      struct membanks *mem)
+{
+    return device_tree_get_meminfo(fdt, node, "reg", address_cells, size_cells,
+                                   mem, MEMBANK_DEFAULT);
+}
+
+static int __init process_reserved_memory_node(const void *fdt, int node,
+                                               const char *name, int depth,
+                                               u32 address_cells,
+                                               u32 size_cells,
+                                               void *data)
+{
+    int rc = process_memory_node(fdt, node, name, depth, address_cells,
+                                 size_cells, data);
+
+    if ( rc == -ENOSPC )
+        panic("Max number of supported reserved-memory regions reached.\n");
+    else if ( rc != -ENOENT )
+        return rc;
+    return 0;
+}
+
+static int __init process_reserved_memory(const void *fdt, int node,
+                                          const char *name, int depth,
+                                          u32 address_cells, u32 size_cells)
+{
+    return device_tree_for_each_node(fdt, node,
+                                     process_reserved_memory_node,
+                                     bootinfo_get_reserved_mem());
+}
+
+static void __init process_multiboot_node(const void *fdt, int node,
+                                          const char *name,
+                                          u32 address_cells, u32 size_cells)
+{
+    static int __initdata kind_guess = 0;
+    const struct fdt_property *prop;
+    const __be32 *cell;
+    bootmodule_kind kind;
+    paddr_t start, size;
+    int len;
+    /* sizeof("/chosen/") + DT_MAX_NAME + '/' + DT_MAX_NAME + '/0' => 92 */
+    char path[92];
+    int parent_node, ret;
+    bool domU;
+
+    parent_node = fdt_parent_offset(fdt, node);
+    ASSERT(parent_node >= 0);
+
+    /* Check that the node is under "/chosen" (first 7 chars of path) */
+    ret = fdt_get_path(fdt, node, path, sizeof (path));
+    if ( ret != 0 || strncmp(path, "/chosen", 7) )
+        return;
+
+    prop = fdt_get_property(fdt, node, "reg", &len);
+    if ( !prop )
+        panic("node %s missing `reg' property\n", name);
+
+    if ( len < dt_cells_to_size(address_cells + size_cells) )
+        panic("fdt: node `%s': `reg` property length is too short\n",
+                    name);
+
+    cell = (const __be32 *)prop->data;
+    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+
+    if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 ||
+         fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 )
+        kind = BOOTMOD_KERNEL;
+    else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 ||
+              fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 )
+        kind = BOOTMOD_RAMDISK;
+    else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 )
+        kind = BOOTMOD_XSM;
+    else if ( fdt_node_check_compatible(fdt, node, "multiboot,device-tree") == 0 )
+        kind = BOOTMOD_GUEST_DTB;
+    else
+        kind = BOOTMOD_UNKNOWN;
+
+    /**
+     * Guess the kind of these first two unknowns respectively:
+     * (1) The first unknown must be kernel.
+     * (2) Detect the XSM Magic from the 2nd unknown:
+     *     a. If it's XSM, set the kind as XSM, and that also means we
+     *     won't load ramdisk;
+     *     b. if it's not XSM, set the kind as ramdisk.
+     *     So if user want to load ramdisk, it must be the 2nd unknown.
+     * We also detect the XSM Magic for the following unknowns,
+     * then set its kind according to the return value of has_xsm_magic.
+     */
+    if ( kind == BOOTMOD_UNKNOWN )
+    {
+        switch ( kind_guess++ )
+        {
+        case 0: kind = BOOTMOD_KERNEL; break;
+        case 1: kind = BOOTMOD_RAMDISK; break;
+        default: break;
+        }
+        if ( kind_guess > 1 && has_xsm_magic(start) )
+            kind = BOOTMOD_XSM;
+    }
+
+    domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0;
+    add_boot_module(kind, start, size, domU);
+
+    prop = fdt_get_property(fdt, node, "bootargs", &len);
+    if ( !prop )
+        return;
+    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
+                     kind, start, domU);
+}
+
+static int __init process_chosen_node(const void *fdt, int node,
+                                      const char *name,
+                                      u32 address_cells, u32 size_cells)
+{
+    const struct fdt_property *prop;
+    paddr_t start, end;
+    int len;
+
+    if ( fdt_get_property(fdt, node, "xen,static-heap", NULL) )
+    {
+        int rc;
+
+        printk("Checking for static heap in /chosen\n");
+
+        rc = device_tree_get_meminfo(fdt, node, "xen,static-heap",
+                                     address_cells, size_cells,
+                                     bootinfo_get_reserved_mem(),
+                                     MEMBANK_STATIC_HEAP);
+        if ( rc )
+            return rc;
+
+        bootinfo.static_heap = true;
+    }
+
+    printk("Checking for initrd in /chosen\n");
+
+    prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
+    if ( !prop )
+        /* No initrd present. */
+        return 0;
+    if ( len != sizeof(u32) && len != sizeof(u64) )
+    {
+        printk("linux,initrd-start property has invalid length %d\n", len);
+        return -EINVAL;
+    }
+    start = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len));
+
+    prop = fdt_get_property(fdt, node, "linux,initrd-end", &len);
+    if ( !prop )
+    {
+        printk("linux,initrd-end not present but -start was\n");
+        return -EINVAL;
+    }
+    if ( len != sizeof(u32) && len != sizeof(u64) )
+    {
+        printk("linux,initrd-end property has invalid length %d\n", len);
+        return -EINVAL;
+    }
+    end = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len));
+
+    if ( start >= end )
+    {
+        printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
+                  start, end);
+        return -EINVAL;
+    }
+
+    printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
+
+    add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
+
+    return 0;
+}
+
+static int __init process_domain_node(const void *fdt, int node,
+                                      const char *name,
+                                      u32 address_cells, u32 size_cells)
+{
+    const struct fdt_property *prop;
+
+    printk("Checking for \"xen,static-mem\" in domain node\n");
+
+    prop = fdt_get_property(fdt, node, "xen,static-mem", NULL);
+    if ( !prop )
+        /* No "xen,static-mem" present. */
+        return 0;
+
+    return device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells,
+                                   size_cells, bootinfo_get_reserved_mem(),
+                                   MEMBANK_STATIC_DOMAIN);
+}
+
+#ifndef CONFIG_STATIC_SHM
+static inline int process_shm_node(const void *fdt, int node,
+                                   uint32_t address_cells, uint32_t size_cells)
+{
+    printk("CONFIG_STATIC_SHM must be enabled for parsing static shared"
+            " memory nodes\n");
+    return -EINVAL;
+}
+#endif
+
+static int __init early_scan_node(const void *fdt,
+                                  int node, const char *name, int depth,
+                                  u32 address_cells, u32 size_cells,
+                                  void *data)
+{
+    int rc = 0;
+
+    /*
+     * If Xen has been booted via UEFI, the memory banks are
+     * populated. So we should skip the parsing.
+     */
+    if ( !efi_enabled(EFI_BOOT) &&
+         device_tree_node_matches(fdt, node, "memory") )
+        rc = process_memory_node(fdt, node, name, depth,
+                                 address_cells, size_cells, bootinfo_get_mem());
+    else if ( depth == 1 && !dt_node_cmp(name, "reserved-memory") )
+        rc = process_reserved_memory(fdt, node, name, depth,
+                                     address_cells, size_cells);
+    else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
+              device_tree_node_compatible(fdt, node, "multiboot,module" )))
+        process_multiboot_node(fdt, node, name, address_cells, size_cells);
+    else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
+        rc = process_chosen_node(fdt, node, name, address_cells, size_cells);
+    else if ( depth == 2 && device_tree_node_compatible(fdt, node, "xen,domain") )
+        rc = process_domain_node(fdt, node, name, address_cells, size_cells);
+    else if ( depth <= 3 && device_tree_node_compatible(fdt, node, "xen,domain-shared-memory-v1") )
+        rc = process_shm_node(fdt, node, address_cells, size_cells);
+
+    if ( rc < 0 )
+        printk("fdt: node `%s': parsing failed\n", name);
+    return rc;
+}
+
+static void __init early_print_info(void)
+{
+    const struct membanks *mi = bootinfo_get_mem();
+    const struct membanks *mem_resv = bootinfo_get_reserved_mem();
+    struct bootmodules *mods = &bootinfo.modules;
+    struct bootcmdlines *cmds = &bootinfo.cmdlines;
+    unsigned int i;
+
+    for ( i = 0; i < mi->nr_banks; i++ )
+        printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n",
+                mi->bank[i].start,
+                mi->bank[i].start + mi->bank[i].size - 1);
+    printk("\n");
+    for ( i = 0 ; i < mods->nr_mods; i++ )
+        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
+                i,
+                mods->module[i].start,
+                mods->module[i].start + mods->module[i].size,
+                boot_module_kind_as_string(mods->module[i].kind));
+
+    for ( i = 0; i < mem_resv->nr_banks; i++ )
+    {
+        printk(" RESVD[%u]: %"PRIpaddr" - %"PRIpaddr"\n", i,
+               mem_resv->bank[i].start,
+               mem_resv->bank[i].start + mem_resv->bank[i].size - 1);
+    }
+#ifdef CONFIG_STATIC_SHM
+    early_print_info_shmem();
+#endif
+    printk("\n");
+    for ( i = 0 ; i < cmds->nr_mods; i++ )
+        printk("CMDLINE[%"PRIpaddr"]:%s %s\n", cmds->cmdline[i].start,
+               cmds->cmdline[i].dt_name,
+               &cmds->cmdline[i].cmdline[0]);
+    printk("\n");
+}
+
+/* This function assumes that memory regions are not overlapped */
+static int __init cmp_memory_node(const void *key, const void *elem)
+{
+    const struct membank *handler0 = key;
+    const struct membank *handler1 = elem;
+
+    if ( handler0->start < handler1->start )
+        return -1;
+
+    if ( handler0->start >= (handler1->start + handler1->size) )
+        return 1;
+
+    return 0;
+}
+
+static void __init swap_memory_node(void *_a, void *_b, size_t size)
+{
+    struct membank *a = _a, *b = _b;
+
+    SWAP(*a, *b);
+}
+
+/**
+ * boot_fdt_info - initialize bootinfo from a DTB
+ * @fdt: flattened device tree binary
+ *
+ * Returns the size of the DTB.
+ */
+size_t __init boot_fdt_info(const void *fdt, paddr_t paddr)
+{
+    struct membanks *reserved_mem = bootinfo_get_reserved_mem();
+    struct membanks *mem = bootinfo_get_mem();
+    unsigned int i;
+    int nr_rsvd;
+    int ret;
+
+    ret = fdt_check_header(fdt);
+    if ( ret < 0 )
+        panic("No valid device tree\n");
+
+    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false);
+
+    nr_rsvd = fdt_num_mem_rsv(fdt);
+    if ( nr_rsvd < 0 )
+        panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd);
+
+    for ( i = 0; i < nr_rsvd; i++ )
+    {
+        struct membank *bank;
+        paddr_t s, sz;
+
+        if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &sz) < 0 )
+            continue;
+
+        if ( reserved_mem->nr_banks < reserved_mem->max_banks )
+        {
+            bank = &reserved_mem->bank[reserved_mem->nr_banks];
+            bank->start = s;
+            bank->size = sz;
+            bank->type = MEMBANK_FDT_RESVMEM;
+            reserved_mem->nr_banks++;
+        }
+        else
+            panic("Cannot allocate reserved memory bank\n");
+    }
+
+    ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL);
+    if ( ret )
+        panic("Early FDT parsing failed (%d)\n", ret);
+
+    /*
+     * On Arm64 setup_directmap_mappings() expects to be called with the lowest
+     * bank in memory first. There is no requirement that the DT will provide
+     * the banks sorted in ascending order. So sort them through.
+     */
+    sort(mem->bank, mem->nr_banks, sizeof(struct membank),
+         cmp_memory_node, swap_memory_node);
+
+    early_print_info();
+
+    return fdt_totalsize(fdt);
+}
+
+const __init char *boot_fdt_cmdline(const void *fdt)
+{
+    int node;
+    const struct fdt_property *prop;
+
+    node = fdt_path_offset(fdt, "/chosen");
+    if ( node < 0 )
+        return NULL;
+
+    prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
+    if ( prop == NULL )
+    {
+        struct bootcmdline *dom0_cmdline =
+            boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
+
+        if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
+            ( dom0_cmdline && dom0_cmdline->cmdline[0] ) )
+            prop = fdt_get_property(fdt, node, "bootargs", NULL);
+    }
+    if ( prop == NULL )
+        return NULL;
+
+    return prop->data;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/bootfdt.h b/xen/include/xen/bootfdt.h
index c39428d5f5..16fa05f38f 100644
--- a/xen/include/xen/bootfdt.h
+++ b/xen/include/xen/bootfdt.h
@@ -157,6 +157,20 @@ struct bootinfo {
 
 extern struct bootinfo bootinfo;
 
+bool check_reserved_regions_overlap(paddr_t region_start,
+                                    paddr_t region_size);
+
+struct bootmodule *add_boot_module(bootmodule_kind kind,
+                                   paddr_t start, paddr_t size, bool domU);
+struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
+struct bootmodule * boot_module_find_by_addr_and_kind(bootmodule_kind kind,
+                                                             paddr_t start);
+void add_boot_cmdline(const char *name, const char *cmdline,
+                      bootmodule_kind kind, paddr_t start, bool domU);
+struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
+struct bootcmdline * boot_cmdline_find_by_name(const char *name);
+const char *boot_module_kind_as_string(bootmodule_kind kind);
+
 void populate_boot_allocator(void);
 
 size_t boot_fdt_info(const void *fdt, paddr_t paddr);
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common
  2024-08-05 11:33 ` [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common Oleksii Kurochko
@ 2024-08-05 11:58   ` Jan Beulich
  2024-08-06 10:36     ` oleksii.kurochko
  0 siblings, 1 reply; 7+ messages in thread
From: Jan Beulich @ 2024-08-05 11:58 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Shawn Anastasio, Andrew Cooper, Julien Grall, Stefano Stabellini,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
	Daniel P. Smith, Julien Grall, xen-devel

On 05.08.2024 13:33, 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.
> 
> 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 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                          |    2 +
>  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 ++++++
>  xen/common/device-tree/device_tree.c | 2253 ++++++++++++++++++++++++++
>  xen/common/device_tree.c             | 2253 --------------------------
>  xen/include/xen/bootfdt.h            |  195 +++
>  9 files changed, 2913 insertions(+), 2870 deletions(-)
>  create mode 100644 xen/common/device-tree/Makefile
>  create mode 100644 xen/common/device-tree/bootinfo.c
>  create mode 100644 xen/common/device-tree/device_tree.c

Can the moved file please be in sync with its directory, naming (i.e. dash
vs underscore) wise? I also expect the diff would be quite a bit smaller
with git's rename detection properly enabled.

Jan


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c to common
  2024-08-05 11:33 ` [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c " Oleksii Kurochko
@ 2024-08-05 19:01   ` Julien Grall
  2024-08-06 10:36     ` oleksii.kurochko
  0 siblings, 1 reply; 7+ messages in thread
From: Julien Grall @ 2024-08-05 19:01 UTC (permalink / raw)
  To: Oleksii Kurochko, xen-devel
  Cc: Shawn Anastasio, Stefano Stabellini, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Daniel P. Smith

Hi,

On 05/08/2024 12:33, Oleksii Kurochko wrote:
> From: Shawn Anastasio <sanastasio@raptorengineering.com>
> 
> Move Arm's bootfdt.c to xen/common so that it can be used by other
> device tree architectures like PPC and RISCV.
> 
> Remove stubs for process_shm_node() and early_print_info_shmem()
> from $xen/arch/arm/include/asm/static-shmem.h.
> These stubs are removed to avoid introducing them for architectures
> that do not support CONFIG_STATIC_SHM.
> The process_shm_node() stub is now implemented in common code to
> maintain the current behavior of early_scan_code() on ARM.
> The early_print_info_shmem() stub is only used in early_print_info(),
> so it's now guarded with #ifdef CONFIG_STATIC_SHM ... #endif.
> 
> 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>

Cheers,

-- 
Julien Grall


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common
  2024-08-05 11:58   ` Jan Beulich
@ 2024-08-06 10:36     ` oleksii.kurochko
  0 siblings, 0 replies; 7+ messages in thread
From: oleksii.kurochko @ 2024-08-06 10:36 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Shawn Anastasio, Andrew Cooper, Julien Grall, Stefano Stabellini,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
	Daniel P. Smith, Julien Grall, xen-devel

On Mon, 2024-08-05 at 13:58 +0200, Jan Beulich wrote:
> On 05.08.2024 13:33, 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.
> > 
> > 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 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                          |    2 +
> >  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 ++++++
> >  xen/common/device-tree/device_tree.c | 2253
> > ++++++++++++++++++++++++++
> >  xen/common/device_tree.c             | 2253 ----------------------
> > ----
> >  xen/include/xen/bootfdt.h            |  195 +++
> >  9 files changed, 2913 insertions(+), 2870 deletions(-)
> >  create mode 100644 xen/common/device-tree/Makefile
> >  create mode 100644 xen/common/device-tree/bootinfo.c
> >  create mode 100644 xen/common/device-tree/device_tree.c
> 
> Can the moved file please be in sync with its directory, naming (i.e.
> dash
> vs underscore) wise? I also expect the diff would be quite a bit
> smaller
> with git's rename detection properly enabled.
Sure, I will sent new patch series version soon. Thanks.

~ Oleksii


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c to common
  2024-08-05 19:01   ` Julien Grall
@ 2024-08-06 10:36     ` oleksii.kurochko
  0 siblings, 0 replies; 7+ messages in thread
From: oleksii.kurochko @ 2024-08-06 10:36 UTC (permalink / raw)
  To: Julien Grall, xen-devel
  Cc: Shawn Anastasio, Stefano Stabellini, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Daniel P. Smith

Hi Julien,

On Mon, 2024-08-05 at 20:01 +0100, Julien Grall wrote:
> Hi,
> 
> On 05/08/2024 12:33, Oleksii Kurochko wrote:
> > From: Shawn Anastasio <sanastasio@raptorengineering.com>
> > 
> > Move Arm's bootfdt.c to xen/common so that it can be used by other
> > device tree architectures like PPC and RISCV.
> > 
> > Remove stubs for process_shm_node() and early_print_info_shmem()
> > from $xen/arch/arm/include/asm/static-shmem.h.
> > These stubs are removed to avoid introducing them for architectures
> > that do not support CONFIG_STATIC_SHM.
> > The process_shm_node() stub is now implemented in common code to
> > maintain the current behavior of early_scan_code() on ARM.
> > The early_print_info_shmem() stub is only used in
> > early_print_info(),
> > so it's now guarded with #ifdef CONFIG_STATIC_SHM ... #endif.
> > 
> > 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>
Thanks.

~ Oleksii


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-08-06 10:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-05 11:33 [PATCH v1 0/2] Common device tree stuff Oleksii Kurochko
2024-08-05 11:33 ` [PATCH v8 1/2] xen/device-tree: Move Arm's setup.c bootinfo functions to common Oleksii Kurochko
2024-08-05 11:58   ` Jan Beulich
2024-08-06 10:36     ` oleksii.kurochko
2024-08-05 11:33 ` [PATCH v8 2/2] xen/common: Move Arm's bootfdt.c " Oleksii Kurochko
2024-08-05 19:01   ` Julien Grall
2024-08-06 10:36     ` oleksii.kurochko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.