[PATCH 1/8] ARM: assembler: introduce adr_l, ldr_l and str_l macros
Dave.Martin at arm.com
Thu Aug 4 02:44:52 PDT 2016
On Thu, Aug 04, 2016 at 09:40:31AM +0200, Ard Biesheuvel wrote:
> On 3 August 2016 at 18:49, Dave Martin <Dave.Martin at arm.com> wrote:
> > On Wed, Aug 03, 2016 at 05:38:43PM +0200, Ard Biesheuvel wrote:
> >> Like arm64, ARM supports position independent code sequences that
> >> produce symbol references with a greater reach than the ordinary
> >> adr/ldr instructions.
> >> Introduce adr_l, that takes the address of a symbol in a PC relative
> >> manner, and ldr_l/str_l that perform a 32-bit loads/stores from a
> >> PC-relative offset.
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> >> ---
> >> arch/arm/include/asm/assembler.h | 59 ++++++++++++++++++++
> >> 1 file changed, 59 insertions(+)
> >> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> >> index 4eaea2173bf8..e1450889f96b 100644
> >> --- a/arch/arm/include/asm/assembler.h
> >> +++ b/arch/arm/include/asm/assembler.h
> >> @@ -512,4 +512,63 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
> >> #endif
> >> .endm
> >> +/*
> >> + * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> operations
> >> + */
> >> +
> >> + /*
> >> + * @dst: destination register
> >> + * @sym: name of the symbol
> >> + */
> >> + .macro adr_l, dst, sym
> >> +#ifdef CONFIG_THUMB2_KERNEL
> >> + movw \dst, #:lower16:(\sym) - (. + 12)
> >> + movt \dst, #:upper16:(\sym) - (. + 8)
> >> + add \dst, \dst, pc
> > pc always reads as the address of that add plus 4, right? I remember
> > some special case where it gets rounded down to a 4-byte boundary, but
> > IIRC that only applies to certain ldr ..., [pc, ...] forms.
> The 4-byte rounding occurs when the linker (or the linux module
> loader) encounters a bl instruction in Thumb that needs to be fixed up
> to blx if the target is ARM.
I think there are a few cases like this -- so long as this add isn't
> >> +#else
> >> + add \dst, pc, #:pc_g0_nc:(\sym) - 8
> >> + add \dst, \dst, #:pc_g1_nc:(\sym) - 4
> >> + add \dst, \dst, #:pc_g2:(\sym)
> > Whoah. I've never seen this syntax before... does this work for any
> > named reloc, or just for certain blessed relocs? (I'm also _assuming_
> > the assembler support for this functionality is ancient -- if not,
> > there may be toolchain compatibility issues.)
> > Based on my understanding of how these relocs work, this should do the
> > right thing, though.
> > Second question: for arm, this reduces the range addressable to
> > pc +/- 26-bit offset (24-bit if sym is not word aligned, but that
> > probably never happens).
> > I can't remember the de facto limit on the size of vmlinux for arm --
> > are you sure this extra limitation won't break some cases of huge
> > initramfs where adr_l gets used for cross-section references?
> Yes, that seems a valid concern. We have +/- 64 MB for the adr_l
> variant (as you say, for word aligned symbols), but this may be
> insufficient. The ldr/str variants don't have the same limitation.
True, but they're still limited, I think in effect to +/- 256 MB.
More information about the linux-arm-kernel