Hello,
For an ADRP instruction at page offset 0xff8 or 0xffc,
libs/libc/machine/arm64/arch_elf.c rewrites it as ADR to avoid
Cortex-A53 erratum 843419. ADR reaches only +/-1 MB. When the target is
further away, the loader returns -EINVAL ("Out of range for ADR"), so a
module with more than about 1 MB between an instruction and its data can
fail to load. The bigger the module, the more likely this is.
The Linux arm64 module loader does the same rewrite, but when ADR cannot
reach the target it branches to a veneer in the module's PLT area that
does the ADRP there, at a safe offset.
Possible directions for NuttX:
1. When ADR cannot reach, keep the ADRP and relocate it normally (it
reaches 4 GB). The workaround is then missing for that one
instruction. Only affected Cortex-A53 revisions, with a specific
instruction sequence after the ADRP, can see the erratum.
2. Do it as Linux does: allocate a veneer area per module and emit
veneers. This needs extra executable memory and more code.
3. Apply the workaround only on Cortex-A53 (for example a Kconfig
ARM64_ERRATUM_843419, default y with ARCH_CORTEX_A53), and use plain
ADRP on other cores, combined with 1 or 2 for the Cortex-A53 case.
I have 1 working locally (a few lines). Would 1, or 3 with 1, be
acceptable? Or do you want the veneers?
Thanks,
Marco Casaroli