Hi Alexander,
thanks for taking care of solving the problem upstream, but ... ;-)
On 6/14/26 20:57, Alexander Sverdlin wrote:
Hi Paul,
On Sun, 2026-06-14 at 15:54 +0200, Paul Kocialkowski wrote:
Currently some ARM-based platforms reserve TF-A memory in their own ways:
- Mediatek gets BL31 region via SMC call in ft_system_setup()
- K3 uses CONFIG_K3_ATF_LOAD_ADDR, effectively in ft_system_setup()
And others like Allwinner simply forget to do it, which results in Linux
overwriting TF-A and crashing.
To be fair we've been adding the reserved memory regions statically in
the Linux device-trees to mitigate the issue.
once for H616, but it could be the only SoC among ARM64 platforms doing
this and discouraged for A133:
https://lore.kernel.org/all/[email protected]/
But another thing we do overwrite current is the cpu idle states, which
are added by fdt_add_cpu_idle_states in tf-a. These are only set when the
SCP firmware is available (which is checked at run-time) and they are
never propagated to the final device-tree. Including the definitions
statically would result in cpu idle calls done even without the SCP
firmware, which would probably fail (although maybe some states can
still be supported).
Do you refer to some unmerged code? Didn't find it in the current TF-A
sources...
Also note that the usual way to deal with this is to not load any
device-tree when booting the kernel, which will implicitly let U-Boot
use its current device-tree for Linux (with the modifications brought by
tf-a).
?!
We definitely want to load the very device tree coming in the FIT image
and pass it to the kernel from this FIT image. Sometimes people would
have several DTs to chose from. The thing in U-Boot is basically to
get U-Boot up and running. OF_UPSTREAM is rather to reduce the traffic
on the U-Boot mailing list and maintainers effort, but in most of the
cases we shall expect this DT to be not from the kernel we actually load.
Sorry, buy I completely and strongly disagree here. This concept of "let
me load the DT that shipped with the kernel I am going to load" was
ill-fated from the very beginning, but back 15 years ago it was just the
only practical way of handling things, because the bootloaders were not
ready. I understand that this is how embedded people use to do things
ever since, but I don't think we should continue doing so.
By definition firmware (the combination of SPL, TF-A, U-Boot, crust in
our case) is device specific, so the board DT living in firmware is a
good match. As you said, U-Boot needs the DT anyway, and since the DT
describes the hardware, it's the same DT the kernel gets. Following this
idea, there should be one best (golden) DT for a board at any point in
time, probably the one from the latest kernel tree. And that's the one
that goes into the firmware image, and that both U-Boot and the kernel use.
For distro boot this is basically essential, and for UEFI based boot
there is actually no other choice. And I like to treat the classic
embedded boot methods more as special cases of the more generic ones.
I see a point of loading a custom DT during development, to play around
with nodes and properties, but I think there are better ways to handle this:
- Do the DT changes in the U-Boot tree, and load
u-boot-sunxi-with-spl.bin via FEL. That's what I typically do.
- Put your changes in DT overlays, and load and apply them in U-Boot:
> fdt copy $fdtcontroladdr $fdt_addr_r
> load mmc 0 fdtoverlay_addr_r my_ovl.dtbo
> fdt apply $fdtoverlay_addr_r
- Patch your changes in using U-Boot's fdt command:
> fdt copy $fdtcontroladdr $fdt_addr_r
> fdt set /path/to/node your-property <42>
And even if you really want to completely load your custom DT, this is
probably changed anyway, so you could patch in the things that need
adjustment, like the reserved memory nodes.
Cheers,
Andre
But of course I agree that it is very desirable to "forward" the
device-tree modifications to the kernel device-tree so we are not stuck
with whatever device-tree U-Boot was built with.
Unfortunately seems that the things are not much better on TF-A side and
there is no universal way to get the reserved memory region across
platforms. But there is at least a most common way in TF-A, namely
reserving memory range in the FDT, in particular:
- Allwinner ("tf-a@40000000" node)
- ARM FPGA ("tf-a@80000000" node)
- Xilinx ("tf-a" node)
RaspberryPi seems to be using "atf@0". Generally speaking the property
is a free-form argument to fdt_add_reserved_memory in tf-a and I don't
think we can have a common way to match them.
Introducing a Kconfig property for the prefix would be a satisfying
solution in my opinion.
This was a very conservative patch solving the A133 case, but actually
I don't see anything wrong with just copying all the reserved areas from
the U-Boot live tree to the device tree we are going to pass to the
kernel. Maybe fdtdec_add_reserved_memory() needs to be taught to detect
overlapping ranges and extend them properly, or maybe yet another function
has to be created for this purpose, to avoid duplicated reserved-memory
nodes by all means, but would also solve the PSCI cpuidle issue, as well
as potentially Raspi case of TF-A side and simplify TI K3 on U-Boot side.
While this patch aims to improve the situation for Allwinner platforms,
it's deliberately adding more generic code to pave the potential way of
unification for other platforms.
Note that fdtdec_add_reserved_memory() has a check for an already existing
carveout with exactly matching boundaries and will not create a duplicate
even if the name doesn't match. It would not however detect an already
existing bigger carveout fully containing the one requested.
Signed-off-by: Alexander Sverdlin <[email protected]>
---
The patch has been developed to faciliate Allwinner A133 SoC support, where
most of the work currently happens on TF-A [1] and Linux [2] sides, but
I wanted to send this patch upfront to get the first feedback and because
already supported H616 SoC would already benefit from the patch.
Thanks for looking at this!
Like I said, I guess the same needs to be done for the cpuidle psci
nodes.
See above, maybe there is a way to carefully copy all /reserved-memory nodes?
Maybe this full copy shall be configurable, but with a proper overlapping-aware
implementation maybe even a Kconfig option is not required...