Port-arm archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: u-boot places device-tree in bss
> Am 14.12.2025 um 21:39 schrieb Nick Hudson <nick.hudson%gmx.co.uk@localhost>:
>
> On 14/12/2025 18:56, Yuri Honegger wrote:
>> Hello,
>> When the memory address for the device tree isn't provided to u-boot, u-boot
>> decides where to place the device tree by itself. For me, it chooses to place it
>> right after the code, overlapping the bss section. This means the device tree
>> gets overwritten when clearing the bss and a bit later, NetBSD rightfully panics
>> because of a corrupt device tree.
>> Since u-boot leaves some space between the code and the device tree, it works
>> with a small kernel, but as soon as I enable more features and bss grows, I run
>> into this issue.
>
> I'm a little surprised that NetBSD's GENERIC_V5 is bloated compared to your u-boot's idea of how big the kernel is, but not completely.
I think u-boot might only considers text + other initialized segments and ignores bss when allocating the memory, then round up or something like that. I’ll have to investigate it more thoroughly.
>
>> I can work around this by giving u-boot a boot.scr that manually places the
>> device tree, but I'm wondering if this could be fixed in NetBSD.
>> We could add a panic if we encounter this situation. That would be a bit more
>> helpful than the current error:
>> [ 1.0000000] panic: fdt_check_header failed: FDT_ERR_BADMAGIC
>
> Sure... something like the attached. Oh, looking at arm32_bootmem_init it's a bit more complicated, but you get the idea.
It almost works. One issue is that the fdt address is physical memory while the bss start/end addresses are virtual memory.
In my case:
FDT VA: 0x42b93000 PA: 0x42b93000
BSS VA: 0xc05de580 PA: 0x425de580
Once you account for that it it catches the issue for me. I’ve also changed to lower bound comparison to <=.
diff --git a/sys/arch/evbarm/fdt/fdt_machdep.c b/sys/arch/evbarm/fdt/fdt_machdep.c
index 89a1d4a06f5e..06cc8e13d12f 100644
--- a/sys/arch/evbarm/fdt/fdt_machdep.c
+++ b/sys/arch/evbarm/fdt/fdt_machdep.c
@@ -257,10 +257,17 @@ initarm(void *arg)
{
const struct fdt_platform *plat;
uint64_t memory_start, memory_end;
+ extern char etext[];
+ extern char _end[];
+ extern u_long kern_vtopdiff;
/* set temporally to work printf()/panic() even before consinit() */
cn_tab = &earlycons;
+ vaddr_t fdt_va = ((vaddr_t)fdt_addr_r)+kern_vtopdiff;
+ if ((vaddr_t)etext <= fdt_va && fdt_va < (vaddr_t)_end)
+ panic("FDT placed within loaded kernel");
+
/* Load FDT */
int error = fdt_check_header(fdt_addr_r);
if (error != 0)
I don’t quite get your point about arm32_bootmem_init. When we reach it, we’ve already copied the fdt using fdt_open_into so we don’t need the original fdt anymore.
>
>
>> Another option would be to add some logic that preserves the device tree in this
>> scenario. For example, we could move the device tree out of the way of the bss
>> if they overlap. The question is where would we move it though? Perhaps
>> beyond the end of the bss section?
>
> This isn't possible. the fdt needs to be loaded outside of the kernel text, data and bss.
>
> <diff.txt>
Home |
Main Index |
Thread Index |
Old Index