Message ID | 65c49e7aa25249cd94be3ce9b850d023c9dff731.1727449154.git.oleksii.kurochko@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | device tree mapping | expand |
Add missing revision log: --- Changes in V6-V8: - 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. --- ~ Oleksii On Fri, 2024-09-27 at 18:33 +0200, Oleksii Kurochko wrote: > 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> > --- > 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 c4fadd36c6..a316901fd4 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> > @@ -57,6 +58,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();
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 c4fadd36c6..a316901fd4 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> @@ -57,6 +58,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();