Thread (36 messages) 36 messages, 4 authors, 2020-10-06

Re: [PATCH 1/6 v14] ARM: Handle a device tree in lowmem

From: Linus Walleij <hidden>
Date: 2020-10-05 12:28:57

Hi Ard,

thanks for helping out, finally we're getting somewhere with this!

On Mon, Oct 5, 2020 at 9:15 AM Ard Biesheuvel [off-list ref] wrote:
On Sun, 4 Oct 2020 at 22:50, Linus Walleij [off-list ref] wrote:
OK, so from your explanation, I gathered that:
- the 'appended DTB' is not appended anymore when the core kernel
boots, and the problem is caused by the fact that the decompressor
blindly chooses a location for it, whereas the firmware makes a more
informed decision when it places the DT in memory
- the memory holding the DT may be unmapped inadvertently
- the memory holding the DT may be wiped inadvertently.
Correct.
quoted
The kernel actually fits in the first memblock, but then it clears
the lowmem right below itself and by that point the MMU
has figured out that there is another memblock below it
that it will happily use for lowmem and just goes ahead and
wipes that. The code has no awareness
that there might be a DTB there.
Where in the code does this happen?
This happens in mm/mmu.c, prepare_page_table(), line1283:

/*
* Clear out all the kernel space mappings, except for the first
* memory bank, up to the vmalloc region.
*/
for (addr = __phys_to_virt(end); addr < VMALLOC_START; addr += PMD_SIZE)
        pmd_clear(pmd_off_k(addr));

Here end is augmented roofed at arm_lowmem_limit which seems
common but that incidentally does not happen on my platform
because of the small size of the first memblock.
It seems to me that at this point,
the DT memory should have been memblock_reserve()d, and the code in
question should disregard it from wiping.
This code seems pretty ignorant about anything like that,
This  happens as the first call in paging_init() after
arm_memblock_init() but before we
have called memblock_set_current_limit().

We need to keep these mappings alive until we
have called unflatten_and_copy_device_tree()
which transfers the device tree into memory the kernel
controls. Then we should free/unmap that memory
so that the kernel can use it. What happens to the memory
where the DTB is stored right now is kind of "undefined"
which doesn't feel good to me at all.
I think putting the mapping of the DT outside of the linear region is
reasonable, tbh, and this is what we do on arm64.
Yes that is much better. Arm64 also relies on the bootloader
to do the decompression and some other simplifications I really
like.
One option would be to create a virtual mapping for the DT at the base
of the modules region. This takes up 1 MB in the typical (non-LPAE)
case, and 4 MB in the worst case, making it more likely that you will
run out of module space, but we already have infrastructure to deal
with that.
2MB (two section mappings) is what head.S always maps
and that would be 4MB on LPAE indeed.

I tried to use the earlymaps for this but I couldn't get it to
work, besides it only supports some 16 pages so not good
approach since the early boot maps a whopping 2MB.

Yours,
Linus Walleij

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help