arm: Introduce and use GET_TLS

Factor out the sequence needed to call kuser_get_tls, as we can't
play subtract into pc games in thumb mode.  Prepare for hard-tp,
pulling the save of LR into the macro.
This commit is contained in:
Richard Henderson 2013-02-13 20:10:45 -08:00
parent 3ae44082ab
commit 5232b909bf
10 changed files with 77 additions and 42 deletions

View File

@ -1,5 +1,18 @@
2013-03-06 Richard Henderson <rth@redhat.com>
* sysdeps/arm/sysdep.h (GET_TLS): New macro.
* sysdeps/arm/dl-tlsdesc.S (_dl_tlsdesc_undefweak): Use it.
(_dl_tlsdesc_dynamic): Likewise.
* sysdeps/unix/arm/sysdep.S (__syscall_error): Likewise.
* sysdeps/unix/sysv/linux/arm/sysdep.h (GET_TLS): New macro.
* sysdeps/unix/sysv/linux/arm/clone.S (__clone): Likewise.
* sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S (SAVE_PID): Likewise.
* sysdeps/unix/sysv/linux/arm/nptl/vfork.S (SAVE_PID): Likewise.
* sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h (SINGLE_THREAD_P):
Likewise.
* sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S (__aeabi_read_tp):
Add thumb2 alternative.
* sysdeps/arm/sysdep.h (NEGOFF_ADJ_BASE): New macro.
(NEGOFF_ADJ_BASE2, NEGOFF_OFF1, NEGOFF_OFF2): New macros.
* sysdeps/unix/sysv/linux/arm/clone.S (__clone): Use them.

View File

@ -50,18 +50,9 @@ _dl_tlsdesc_return:
.fnstart
.align 2
_dl_tlsdesc_undefweak:
@ Are we allowed a misaligned stack pointer calling read_tp?
.save {lr}
stmdb sp!, {lr}
cfi_adjust_cfa_offset (4)
cfi_rel_offset (lr,0)
bl __aeabi_read_tp
GET_TLS (r1)
rsb r0, r0, #0
ldmia sp!, {lr}
cfi_adjust_cfa_offset (-4)
cfi_restore (lr)
BX (lr)
cfi_endproc
.fnend
.size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
@ -106,7 +97,7 @@ _dl_tlsdesc_dynamic:
cfi_rel_offset (r4,8)
cfi_rel_offset (lr,12)
ldr r1, [r0] /* td */
bl __aeabi_read_tp
GET_TLS (lr)
mov r4, r0 /* r4 = tp */
ldr r0, [r0]
ldr r2, [r1, #8] /* gen_count */

View File

@ -150,6 +150,25 @@
# define NEGOFF_OFF1(R, OFF) [R, $OFF]
# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
# endif
/* Helper to get the TLS base pointer. The interface is that TMP is a
register that may be used to hold the LR, if necessary. TMP may be
LR itself to indicate that LR need not be saved. The base pointer
is returned in R0. Only R0 and TMP are modified.
At this generic level we have no tricks to pull. Call the ABI routine. */
# define GET_TLS(TMP) \
push { r1, r2, r3, lr }; \
cfi_remember_state; \
cfi_adjust_cfa_offset (16); \
cfi_rel_offset (r1, 0); \
cfi_rel_offset (r2, 4); \
cfi_rel_offset (r3, 8); \
cfi_rel_offset (lr, 12); \
bl __aeabi_read_tp; \
pop { r1, r2, r3, lr }; \
cfi_restore_state
#endif /* __ASSEMBLER__ */
/* This number is the offset from the pc at the current location. */

View File

@ -37,14 +37,8 @@ __syscall_error:
#endif
#ifndef IS_IN_rtld
mov ip, lr
cfi_register (lr, ip)
mov r1, r0
mov r0, #0xffff0fff
mov lr, pc
sub pc, r0, #31
mov r1, r0
GET_TLS (r2)
ldr r2, 1f
#ifdef __thumb__
2: add r2, r2, pc
@ -54,7 +48,7 @@ __syscall_error:
#endif
str r1, [r0, r2]
mvn r0, #0
DO_RET(ip)
DO_RET(lr)
1: .word errno(gottpoff) + (. - 2b - PC_OFS)
#elif RTLD_PRIVATE_ERRNO

View File

@ -41,6 +41,12 @@
.hidden __aeabi_read_tp
ENTRY (__aeabi_read_tp)
#ifdef __thumb2__
movw r0, #0x0fe0
movt r0, #0xffff
bx r0
#else
mov r0, #0xffff0fff
sub pc, r0, #31
#endif
END (__aeabi_read_tp)

View File

@ -74,9 +74,7 @@ PSEUDO_END (__clone)
#ifdef RESET_PID
tst ip, #CLONE_THREAD
bne 3f
mov r0, #0xffff0fff
mov lr, pc
sub pc, r0, #31
GET_TLS (lr)
mov r1, r0
tst ip, #CLONE_VM
ldr r7, =SYS_ify(getpid)

View File

@ -19,15 +19,7 @@
/* Save the PID value. */
#define SAVE_PID \
str lr, [sp, #-4]!; /* Save LR. */ \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (lr, 0); \
mov r0, #0xffff0fff; /* Point to the high page. */ \
mov lr, pc; /* Save our return address. */ \
sub pc, r0, #31; /* Jump to the TLS entry. */ \
ldr lr, [sp], #4; /* Restore LR. */ \
cfi_adjust_cfa_offset (-4); \
cfi_restore (lr); \
GET_TLS (r2); \
NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET); /* Save the TLS addr in r2. */ \
ldr r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* Load the saved PID. */ \
rsb r0, r3, #0; /* Negate it. */ \

View File

@ -216,7 +216,7 @@ extern int __local_multiple_threads attribute_hidden;
stmfd sp!, {r0, lr}; \
cfi_adjust_cfa_offset (8); \
cfi_rel_offset (lr, 4); \
bl __aeabi_read_tp; \
GET_TLS (lr); \
NEGOFF_ADJ_BASE (r0, MULTIPLE_THREADS_OFFSET); \
ldr ip, NEGOFF_OFF1 (r0, MULTIPLE_THREADS_OFFSET); \
ldmfd sp!, {r0, lr}; \

View File

@ -19,15 +19,7 @@
/* Save the PID value. */
#define SAVE_PID \
str lr, [sp, #-4]!; /* Save LR. */ \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (lr, 0); \
mov r0, #0xffff0fff; /* Point to the high page. */ \
mov lr, pc; /* Save our return address. */ \
sub pc, r0, #31; /* Jump to the TLS entry. */ \
ldr lr, [sp], #4; /* Restore LR. */ \
cfi_adjust_cfa_offset (-4); \
cfi_restore (lr); \
GET_TLS (r2); \
NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET); /* Save the TLS addr in r2. */ \
ldr r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* Load the saved PID. */ \
rsbs r0, r3, #0; /* Negate it. */ \

View File

@ -45,6 +45,36 @@
#ifdef __ASSEMBLER__
/* Internal macro calling the linux kernel kuser_get_tls helper.
Note that in thumb mode, a constant pool break is often out of range, so
we always expand the constant inline. */
#ifdef __thumb2__
# define GET_TLS_BODY \
movw r0, #0x0fe0; \
movt r0, #0xffff; \
blx r0
#else
# define GET_TLS_BODY \
mov r0, #0xffff0fff; /* Point to the high page. */ \
mov lr, pc; /* Save our return address. */ \
sub pc, r0, #31 /* Jump to the TLS entry. */
#endif
/* Helper to get the TLS base pointer. Save LR in TMP, return in R0,
and no other registers clobbered. TMP may be LR itself to indicate
that no save is necessary. */
#undef GET_TLS
#define GET_TLS(TMP) \
.ifnc TMP, lr; \
mov TMP, lr; \
cfi_register (lr, TMP); \
GET_TLS_BODY; \
mov lr, TMP; \
cfi_restore (lr); \
.else; \
GET_TLS_BODY; \
.endif
/* Linux uses a negative return value to indicate syscall errors,
unlike most Unices, which use the condition codes' carry flag.