Introduce function which allows to map FDT to Xen.
Also, initialization of device_tree_flattened happens using
early_fdt_map().
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V6-V9:
- Nothing changed. Only rebase.
---
Changes in V5:
- drop usage of PTE_BLOCK for flag argument of map_pages_to_xen() in early_fdt_map()
as block mapping is now default behaviour. Also PTE_BLOCK was dropped in the patch
"xen/riscv: page table handling".
---
Changes in V4:
- s/_PAGE_BLOCK/PTE_BLOCK
- Add Acked-by: Jan Beulich <jbeulich@suse.com>
- unwarap two lines in panic() in case when device_tree_flattened is NULL
so grep-ing for any part of the message line will always produce a hit.
- slightly update the commit message.
---
Changes in V3:
- Code style fixes
- s/SZ_2M/MB(2)
- fix condition to check if early_fdt_map() in setup.c return NULL or not.
---
Changes in V2:
- rework early_fdt_map to use map_pages_to_xen()
- move call early_fdt_map() to C code after MMU is enabled.
---
xen/arch/riscv/include/asm/mm.h | 2 ++
xen/arch/riscv/mm.c | 55 +++++++++++++++++++++++++++++++++
xen/arch/riscv/setup.c | 7 +++++
3 files changed, 64 insertions(+)
diff --git a/xen/arch/riscv/include/asm/mm.h b/xen/arch/riscv/include/asm/mm.h
index ce1557bb27..4b7b00b850 100644
--- a/xen/arch/riscv/include/asm/mm.h
+++ b/xen/arch/riscv/include/asm/mm.h
@@ -259,4 +259,6 @@ static inline unsigned int arch_get_dma_bitsize(void)
void setup_fixmap_mappings(void);
+void *early_fdt_map(paddr_t fdt_paddr);
+
#endif /* _ASM_RISCV_MM_H */
diff --git a/xen/arch/riscv/mm.c b/xen/arch/riscv/mm.c
index e8430def14..4a628aef83 100644
--- a/xen/arch/riscv/mm.c
+++ b/xen/arch/riscv/mm.c
@@ -1,13 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <xen/bootfdt.h>
#include <xen/bug.h>
#include <xen/compiler.h>
#include <xen/init.h>
#include <xen/kernel.h>
+#include <xen/libfdt/libfdt.h>
#include <xen/macros.h>
#include <xen/mm.h>
#include <xen/pfn.h>
#include <xen/sections.h>
+#include <xen/sizes.h>
#include <asm/early_printk.h>
#include <asm/csr.h>
@@ -369,3 +372,55 @@ int destroy_xen_mappings(unsigned long s, unsigned long e)
BUG_ON("unimplemented");
return -1;
}
+
+void * __init early_fdt_map(paddr_t fdt_paddr)
+{
+ /* We are using 2MB superpage for mapping the FDT */
+ paddr_t base_paddr = fdt_paddr & XEN_PT_LEVEL_MAP_MASK(1);
+ paddr_t offset;
+ void *fdt_virt;
+ uint32_t size;
+ int rc;
+
+ /*
+ * Check whether the physical FDT address is set and meets the minimum
+ * alignment requirement. Since we are relying on MIN_FDT_ALIGN to be at
+ * least 8 bytes so that we always access the magic and size fields
+ * of the FDT header after mapping the first chunk, double check if
+ * that is indeed the case.
+ */
+ BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
+ if ( !fdt_paddr || fdt_paddr % MIN_FDT_ALIGN )
+ return NULL;
+
+ /* The FDT is mapped using 2MB superpage */
+ BUILD_BUG_ON(BOOT_FDT_VIRT_START % MB(2));
+
+ rc = map_pages_to_xen(BOOT_FDT_VIRT_START, maddr_to_mfn(base_paddr),
+ MB(2) >> PAGE_SHIFT,
+ PAGE_HYPERVISOR_RO);
+ if ( rc )
+ panic("Unable to map the device-tree.\n");
+
+ offset = fdt_paddr % XEN_PT_LEVEL_SIZE(1);
+ fdt_virt = (void *)BOOT_FDT_VIRT_START + offset;
+
+ if ( fdt_magic(fdt_virt) != FDT_MAGIC )
+ return NULL;
+
+ size = fdt_totalsize(fdt_virt);
+ if ( size > BOOT_FDT_VIRT_SIZE )
+ return NULL;
+
+ if ( (offset + size) > MB(2) )
+ {
+ rc = map_pages_to_xen(BOOT_FDT_VIRT_START + MB(2),
+ maddr_to_mfn(base_paddr + MB(2)),
+ MB(2) >> PAGE_SHIFT,
+ PAGE_HYPERVISOR_RO);
+ if ( rc )
+ panic("Unable to map the device-tree\n");
+ }
+
+ return fdt_virt;
+}
diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c
index 1d81e0b64f..6d156c3a40 100644
--- a/xen/arch/riscv/setup.c
+++ b/xen/arch/riscv/setup.c
@@ -2,6 +2,7 @@
#include <xen/bug.h>
#include <xen/compile.h>
+#include <xen/device_tree.h>
#include <xen/init.h>
#include <xen/mm.h>
#include <xen/shutdown.h>
@@ -37,6 +38,12 @@ void __init noreturn start_xen(unsigned long bootcpu_id,
setup_fixmap_mappings();
+ device_tree_flattened = early_fdt_map(dtb_addr);
+ if ( !device_tree_flattened )
+ panic("Invalid device tree blob at physical address %#lx. The DTB must be 8-byte aligned and must not exceed %lld bytes in size.\n\n"
+ "Please check your bootloader.\n",
+ dtb_addr, BOOT_FDT_VIRT_SIZE);
+
printk("All set up\n");
machine_halt();
--
2.46.1
© 2016 - 2024 Red Hat, Inc.