[PATCH 1/8] ARM: assembler: introduce adr_l, ldr_l and str_l macros

Ard Biesheuvel ard.biesheuvel at linaro.org
Thu Aug 4 00:40:31 PDT 2016


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.

>> +#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.

> (For Thumb2, :lower16:/:upper16: give a full 32-bit range, so no problem
> there -- sad that this isn't available before ARMv7).
>

Indeed.



More information about the linux-arm-kernel mailing list