Message ID | 20220322132839.3653682-1-mick@ics.forth.gr (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | RISC-V-fixes: relocate DTB if it's outside memory region | expand |
On 22/03/2022 13:28, Nick Kossifidis wrote: > In case the DTB provided by the bootloader/BootROM is before the kernel > image or outside /memory, we won't be able to access it through the > linear mapping, and get a segfault on setup_arch(). Currently OpenSBI > relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR > is not specified), and it's also not the most portable approach since > the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB > at a specific offset that may not be available. To avoid this situation > copy DTB so that it's visible through the linear mapping. Ran into the same issue & have been carrying a hack for it, this looks *a lot* cleaner. I'll dig out the offending configuration tomorrow and try to give you a tested-by. Thanks, Conor. > > Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> > --- > arch/riscv/mm/init.c | 21 +++++++++++++++++++-- > 1 file changed, 19 insertions(+), 2 deletions(-) > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index 0d588032d..697a9aed4 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) > * early_init_fdt_reserve_self() since __pa() does > * not work for DTB pointers that are fixmap addresses > */ > - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) > - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); > + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { > + /* > + * In case the DTB is not located in a memory region we won't > + * be able to locate it later on via the linear mapping and > + * get a segfault when accessing it via __va(dtb_early_pa). > + * To avoid this situation copy DTB to a memory region. > + * Note that memblock_phys_alloc will also reserve DTB region. > + */ > + if (!memblock_is_memory(dtb_early_pa)) { > + size_t fdt_size = fdt_totalsize(dtb_early_va); > + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); > + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); > + > + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); > + early_memunmap(new_dtb_early_va, fdt_size); > + _dtb_early_pa = new_dtb_early_pa; > + } else > + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); > + } > > early_init_fdt_scan_reserved_mem(); > dma_contiguous_reserve(dma32_phys_limit);
On 22/03/2022 13:28, Nick Kossifidis wrote: > In case the DTB provided by the bootloader/BootROM is before the kernel > image or outside /memory, we won't be able to access it through the > linear mapping, and get a segfault on setup_arch(). Currently OpenSBI > relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR > is not specified), and it's also not the most portable approach since > the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB > at a specific offset that may not be available. To avoid this situation > copy DTB so that it's visible through the linear mapping. > > Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> Albeit in a backport, I tested this on a PolarFire SoC based board. So I guess, Tested-by: Conor Dooley <conor.dooley@microchip.com> And a lot cleaner than using create_pgd_mapping in setup_vm_final to do it :) Thanks, Conor. > --- > arch/riscv/mm/init.c | 21 +++++++++++++++++++-- > 1 file changed, 19 insertions(+), 2 deletions(-) > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index 0d588032d..697a9aed4 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) > * early_init_fdt_reserve_self() since __pa() does > * not work for DTB pointers that are fixmap addresses > */ > - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) > - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); > + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { > + /* > + * In case the DTB is not located in a memory region we won't > + * be able to locate it later on via the linear mapping and > + * get a segfault when accessing it via __va(dtb_early_pa). > + * To avoid this situation copy DTB to a memory region. > + * Note that memblock_phys_alloc will also reserve DTB region. > + */ > + if (!memblock_is_memory(dtb_early_pa)) { > + size_t fdt_size = fdt_totalsize(dtb_early_va); > + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); > + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); > + > + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); > + early_memunmap(new_dtb_early_va, fdt_size); > + _dtb_early_pa = new_dtb_early_pa; > + } else > + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); > + } > > early_init_fdt_scan_reserved_mem(); > dma_contiguous_reserve(dma32_phys_limit);
Στις 2022-03-24 11:37, Conor.Dooley@microchip.com έγραψε: > On 22/03/2022 13:28, Nick Kossifidis wrote: >> In case the DTB provided by the bootloader/BootROM is before the >> kernel >> image or outside /memory, we won't be able to access it through the >> linear mapping, and get a segfault on setup_arch(). Currently OpenSBI >> relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR >> is not specified), and it's also not the most portable approach since >> the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB >> at a specific offset that may not be available. To avoid this >> situation >> copy DTB so that it's visible through the linear mapping. >> >> Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> > > Albeit in a backport, I tested this on a PolarFire SoC based board. > So I guess, Tested-by: Conor Dooley <conor.dooley@microchip.com> > > And a lot cleaner than using create_pgd_mapping in setup_vm_final to do > it :) > > Thanks, > Conor. > Thanks !
Hello Palmer, Any updates on this ? Regards, Nick On 3/22/22 15:28, Nick Kossifidis wrote: > In case the DTB provided by the bootloader/BootROM is before the kernel > image or outside /memory, we won't be able to access it through the > linear mapping, and get a segfault on setup_arch(). Currently OpenSBI > relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR > is not specified), and it's also not the most portable approach since > the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB > at a specific offset that may not be available. To avoid this situation > copy DTB so that it's visible through the linear mapping. > > Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> > --- > arch/riscv/mm/init.c | 21 +++++++++++++++++++-- > 1 file changed, 19 insertions(+), 2 deletions(-) > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index 0d588032d..697a9aed4 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) > * early_init_fdt_reserve_self() since __pa() does > * not work for DTB pointers that are fixmap addresses > */ > - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) > - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); > + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { > + /* > + * In case the DTB is not located in a memory region we won't > + * be able to locate it later on via the linear mapping and > + * get a segfault when accessing it via __va(dtb_early_pa). > + * To avoid this situation copy DTB to a memory region. > + * Note that memblock_phys_alloc will also reserve DTB region. > + */ > + if (!memblock_is_memory(dtb_early_pa)) { > + size_t fdt_size = fdt_totalsize(dtb_early_va); > + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); > + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); > + > + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); > + early_memunmap(new_dtb_early_va, fdt_size); > + _dtb_early_pa = new_dtb_early_pa; > + } else > + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); > + } > > early_init_fdt_scan_reserved_mem(); > dma_contiguous_reserve(dma32_phys_limit);
On Thu, 24 Mar 2022 02:37:29 PDT (-0700), Conor.Dooley@microchip.com wrote: > > On 22/03/2022 13:28, Nick Kossifidis wrote: >> In case the DTB provided by the bootloader/BootROM is before the kernel >> image or outside /memory, we won't be able to access it through the >> linear mapping, and get a segfault on setup_arch(). Currently OpenSBI >> relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR >> is not specified), and it's also not the most portable approach since >> the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB >> at a specific offset that may not be available. To avoid this situation >> copy DTB so that it's visible through the linear mapping. >> >> Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> > > Albeit in a backport, I tested this on a PolarFire SoC based board. > So I guess, Tested-by: Conor Dooley <conor.dooley@microchip.com> My scripts don't pick these up unless they're on their own line, not sure if that's too conservative but it's on purpose. I just sort of stumbled into this one so it's in. > > And a lot cleaner than using create_pgd_mapping in setup_vm_final to do it :) > > Thanks, > Conor. > >> --- >> arch/riscv/mm/init.c | 21 +++++++++++++++++++-- >> 1 file changed, 19 insertions(+), 2 deletions(-) >> >> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c >> index 0d588032d..697a9aed4 100644 >> --- a/arch/riscv/mm/init.c >> +++ b/arch/riscv/mm/init.c >> @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) >> * early_init_fdt_reserve_self() since __pa() does >> * not work for DTB pointers that are fixmap addresses >> */ >> - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) >> - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >> + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { >> + /* >> + * In case the DTB is not located in a memory region we won't >> + * be able to locate it later on via the linear mapping and >> + * get a segfault when accessing it via __va(dtb_early_pa). >> + * To avoid this situation copy DTB to a memory region. >> + * Note that memblock_phys_alloc will also reserve DTB region. >> + */ >> + if (!memblock_is_memory(dtb_early_pa)) { >> + size_t fdt_size = fdt_totalsize(dtb_early_va); >> + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); >> + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); >> + >> + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); >> + early_memunmap(new_dtb_early_va, fdt_size); >> + _dtb_early_pa = new_dtb_early_pa; >> + } else >> + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >> + } >> >> early_init_fdt_scan_reserved_mem(); >> dma_contiguous_reserve(dma32_phys_limit);
On Mon, 25 Apr 2022 23:11:23 PDT (-0700), mick@ics.forth.gr wrote: > Hello Palmer, > > Any updates on this ? Sorry about that, it's on fixes. > > Regards, > Nick > > On 3/22/22 15:28, Nick Kossifidis wrote: >> In case the DTB provided by the bootloader/BootROM is before the kernel >> image or outside /memory, we won't be able to access it through the >> linear mapping, and get a segfault on setup_arch(). Currently OpenSBI >> relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR >> is not specified), and it's also not the most portable approach since >> the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB >> at a specific offset that may not be available. To avoid this situation >> copy DTB so that it's visible through the linear mapping. >> >> Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> >> --- >> arch/riscv/mm/init.c | 21 +++++++++++++++++++-- >> 1 file changed, 19 insertions(+), 2 deletions(-) >> >> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c >> index 0d588032d..697a9aed4 100644 >> --- a/arch/riscv/mm/init.c >> +++ b/arch/riscv/mm/init.c >> @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) >> * early_init_fdt_reserve_self() since __pa() does >> * not work for DTB pointers that are fixmap addresses >> */ >> - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) >> - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >> + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { >> + /* >> + * In case the DTB is not located in a memory region we won't >> + * be able to locate it later on via the linear mapping and >> + * get a segfault when accessing it via __va(dtb_early_pa). >> + * To avoid this situation copy DTB to a memory region. >> + * Note that memblock_phys_alloc will also reserve DTB region. >> + */ >> + if (!memblock_is_memory(dtb_early_pa)) { >> + size_t fdt_size = fdt_totalsize(dtb_early_va); >> + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); >> + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); >> + >> + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); >> + early_memunmap(new_dtb_early_va, fdt_size); >> + _dtb_early_pa = new_dtb_early_pa; >> + } else >> + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >> + } >> >> early_init_fdt_scan_reserved_mem(); >> dma_contiguous_reserve(dma32_phys_limit);
On 28/04/2022 22:48, Palmer Dabbelt wrote: > On Thu, 24 Mar 2022 02:37:29 PDT (-0700), Conor.Dooley@microchip.com wrote: >> >> On 22/03/2022 13:28, Nick Kossifidis wrote: >>> In case the DTB provided by the bootloader/BootROM is before the kernel >>> image or outside /memory, we won't be able to access it through the >>> linear mapping, and get a segfault on setup_arch(). Currently OpenSBI >>> relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR >>> is not specified), and it's also not the most portable approach since >>> the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB >>> at a specific offset that may not be available. To avoid this situation >>> copy DTB so that it's visible through the linear mapping. >>> >>> Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> >> >> Albeit in a backport, I tested this on a PolarFire SoC based board. >> So I guess, Tested-by: Conor Dooley <conor.dooley@microchip.com> > > My scripts don't pick these up unless they're on their own line, not sure if that's too conservative but it's on purpose. I just sort of stumbled into this one so it's in. Uhh, I checked and b4 doesn't pick it up either. I'm not overly concerned about getting "credit" for testing it, more interested in pointing out that it does solve a real issue that I have run into in case you were looking for incentive to apply it :) I realised immediately after sending that it was likely an invalid tag, but figured it'd serve that purpose either way. Thanks, Conor. > >> >> And a lot cleaner than using create_pgd_mapping in setup_vm_final to do it :) >> >> Thanks, >> Conor. >> >>> --- >>> arch/riscv/mm/init.c | 21 +++++++++++++++++++-- >>> 1 file changed, 19 insertions(+), 2 deletions(-) >>> >>> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c >>> index 0d588032d..697a9aed4 100644 >>> --- a/arch/riscv/mm/init.c >>> +++ b/arch/riscv/mm/init.c >>> @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) >>> * early_init_fdt_reserve_self() since __pa() does >>> * not work for DTB pointers that are fixmap addresses >>> */ >>> - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) >>> - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >>> + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { >>> + /* >>> + * In case the DTB is not located in a memory region we won't >>> + * be able to locate it later on via the linear mapping and >>> + * get a segfault when accessing it via __va(dtb_early_pa). >>> + * To avoid this situation copy DTB to a memory region. >>> + * Note that memblock_phys_alloc will also reserve DTB region. >>> + */ >>> + if (!memblock_is_memory(dtb_early_pa)) { >>> + size_t fdt_size = fdt_totalsize(dtb_early_va); >>> + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); >>> + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); >>> + >>> + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); >>> + early_memunmap(new_dtb_early_va, fdt_size); >>> + _dtb_early_pa = new_dtb_early_pa; >>> + } else >>> + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >>> + } >>> early_init_fdt_scan_reserved_mem(); >>> dma_contiguous_reserve(dma32_phys_limit);
On Thu, 28 Apr 2022 14:48:14 PDT (-0700), Palmer Dabbelt wrote: > On Mon, 25 Apr 2022 23:11:23 PDT (-0700), mick@ics.forth.gr wrote: >> Hello Palmer, >> >> Any updates on this ? > > Sorry about that, it's on fixes. Not sure if I just wasn't paying attention yesterday or if I'm grumpier this morning, but that "RISC-V-fixes: " prefix is just a bit too odd -- I know we've got a split between "RISC-V" and "riscv" so maybe it doesn't matter, but even that is kind of ugly. I re-wrote it, but I'm going to let it round trip through linux-next so I'll send it up next time. Sorry, I know this happened twice recently but I'll try not to make a habit of it. > >> >> Regards, >> Nick >> >> On 3/22/22 15:28, Nick Kossifidis wrote: >>> In case the DTB provided by the bootloader/BootROM is before the kernel >>> image or outside /memory, we won't be able to access it through the >>> linear mapping, and get a segfault on setup_arch(). Currently OpenSBI >>> relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR >>> is not specified), and it's also not the most portable approach since >>> the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB >>> at a specific offset that may not be available. To avoid this situation >>> copy DTB so that it's visible through the linear mapping. >>> >>> Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> >>> --- >>> arch/riscv/mm/init.c | 21 +++++++++++++++++++-- >>> 1 file changed, 19 insertions(+), 2 deletions(-) >>> >>> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c >>> index 0d588032d..697a9aed4 100644 >>> --- a/arch/riscv/mm/init.c >>> +++ b/arch/riscv/mm/init.c >>> @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) >>> * early_init_fdt_reserve_self() since __pa() does >>> * not work for DTB pointers that are fixmap addresses >>> */ >>> - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) >>> - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >>> + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { >>> + /* >>> + * In case the DTB is not located in a memory region we won't >>> + * be able to locate it later on via the linear mapping and >>> + * get a segfault when accessing it via __va(dtb_early_pa). >>> + * To avoid this situation copy DTB to a memory region. >>> + * Note that memblock_phys_alloc will also reserve DTB region. >>> + */ >>> + if (!memblock_is_memory(dtb_early_pa)) { >>> + size_t fdt_size = fdt_totalsize(dtb_early_va); >>> + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); >>> + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); >>> + >>> + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); >>> + early_memunmap(new_dtb_early_va, fdt_size); >>> + _dtb_early_pa = new_dtb_early_pa; >>> + } else >>> + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); >>> + } >>> >>> early_init_fdt_scan_reserved_mem(); >>> dma_contiguous_reserve(dma32_phys_limit);
Στις 2022-04-29 18:28, Palmer Dabbelt έγραψε: > On Thu, 28 Apr 2022 14:48:14 PDT (-0700), Palmer Dabbelt wrote: >> On Mon, 25 Apr 2022 23:11:23 PDT (-0700), mick@ics.forth.gr wrote: >>> Hello Palmer, >>> >>> Any updates on this ? >> >> Sorry about that, it's on fixes. > > Not sure if I just wasn't paying attention yesterday or if I'm > grumpier this morning, but that "RISC-V-fixes: " prefix is just a bit > too odd -- I know we've got a split between "RISC-V" and "riscv" so > maybe it doesn't matter, but even that is kind of ugly. > > I re-wrote it, but I'm going to let it round trip through linux-next > so I'll send it up next time. > > Sorry, I know this happened twice recently but I'll try not to make a > habit of it. > Don't worry about it, just let me know what works better for you, would "[PATCH -fixes] riscv:" be ok next time ? Regards, Nick
On Fri, 29 Apr 2022 12:18:14 PDT (-0700), mick@ics.forth.gr wrote: > Στις 2022-04-29 18:28, Palmer Dabbelt έγραψε: >> On Thu, 28 Apr 2022 14:48:14 PDT (-0700), Palmer Dabbelt wrote: >>> On Mon, 25 Apr 2022 23:11:23 PDT (-0700), mick@ics.forth.gr wrote: >>>> Hello Palmer, >>>> >>>> Any updates on this ? >>> >>> Sorry about that, it's on fixes. >> >> Not sure if I just wasn't paying attention yesterday or if I'm >> grumpier this morning, but that "RISC-V-fixes: " prefix is just a bit >> too odd -- I know we've got a split between "RISC-V" and "riscv" so >> maybe it doesn't matter, but even that is kind of ugly. >> >> I re-wrote it, but I'm going to let it round trip through linux-next >> so I'll send it up next time. >> >> Sorry, I know this happened twice recently but I'll try not to make a >> habit of it. >> > > Don't worry about it, just let me know what works better for you, would > "[PATCH -fixes] riscv:" be ok next time ? That's generally how folks do it, but I just look for "fix" anywhere in the subject line.
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 0d588032d..697a9aed4 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -206,8 +206,25 @@ static void __init setup_bootmem(void) * early_init_fdt_reserve_self() since __pa() does * not work for DTB pointers that are fixmap addresses */ - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { + /* + * In case the DTB is not located in a memory region we won't + * be able to locate it later on via the linear mapping and + * get a segfault when accessing it via __va(dtb_early_pa). + * To avoid this situation copy DTB to a memory region. + * Note that memblock_phys_alloc will also reserve DTB region. + */ + if (!memblock_is_memory(dtb_early_pa)) { + size_t fdt_size = fdt_totalsize(dtb_early_va); + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); + + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); + early_memunmap(new_dtb_early_va, fdt_size); + _dtb_early_pa = new_dtb_early_pa; + } else + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); + } early_init_fdt_scan_reserved_mem(); dma_contiguous_reserve(dma32_phys_limit);
In case the DTB provided by the bootloader/BootROM is before the kernel image or outside /memory, we won't be able to access it through the linear mapping, and get a segfault on setup_arch(). Currently OpenSBI relocates DTB but that's not always the case (e.g. if FW_JUMP_FDT_ADDR is not specified), and it's also not the most portable approach since the default FW_JUMP_FDT_ADDR of the generic platform relocates the DTB at a specific offset that may not be available. To avoid this situation copy DTB so that it's visible through the linear mapping. Signed-off-by: Nick Kossifidis <mick@ics.forth.gr> --- arch/riscv/mm/init.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)