From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27636 invoked by alias); 1 Mar 2013 17:36:32 -0000 Received: (qmail 26687 invoked by uid 22791); 1 Mar 2013 17:36:15 -0000 X-SWARE-Spam-Status: No, hits=-5.2 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,KHOP_RCVD_TRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_BL,TW_DM,TW_MV,TW_OV X-Spam-Check-By: sourceware.org Received: from mail-pa0-f45.google.com (HELO mail-pa0-f45.google.com) (209.85.220.45) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 01 Mar 2013 17:35:38 +0000 Received: by mail-pa0-f45.google.com with SMTP id kl14so1942447pab.18 for ; Fri, 01 Mar 2013 09:35:37 -0800 (PST) X-Received: by 10.68.221.68 with SMTP id qc4mr5330985pbc.152.1362159337700; Fri, 01 Mar 2013 09:35:37 -0800 (PST) Received: from fremont.twiddle.net (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPS id kl4sm12679430pbc.31.2013.03.01.09.35.35 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 01 Mar 2013 09:35:36 -0800 (PST) From: Richard Henderson To: libc-ports@sourceware.org Cc: joseph@codesourcery.com Subject: [PATCH v2 03/14] arm: Introduce and use GET_TLS Date: Fri, 01 Mar 2013 17:36:00 -0000 Message-Id: <1362159320-5934-4-git-send-email-rth@twiddle.net> In-Reply-To: <1362159320-5934-1-git-send-email-rth@twiddle.net> References: <1362159320-5934-1-git-send-email-rth@twiddle.net> X-IsSubscribed: yes Mailing-List: contact libc-ports-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: libc-ports-owner@sourceware.org X-SW-Source: 2013-03/txt/msg00009.txt.bz2 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. --- * 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. --- ports/sysdeps/arm/dl-tlsdesc.S | 13 ++-------- ports/sysdeps/arm/sysdep.h | 19 ++++++++++++++ ports/sysdeps/unix/arm/sysdep.S | 12 +++------ ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S | 6 +++++ ports/sysdeps/unix/sysv/linux/arm/clone.S | 4 +-- ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S | 10 +------- .../unix/sysv/linux/arm/nptl/sysdep-cancel.h | 2 +- ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S | 10 +------- ports/sysdeps/unix/sysv/linux/arm/sysdep.h | 30 ++++++++++++++++++++++ 9 files changed, 64 insertions(+), 42 deletions(-) diff --git a/ports/sysdeps/arm/dl-tlsdesc.S b/ports/sysdeps/arm/dl-tlsdesc.S index 7b4c8df..1c3bccf 100644 --- a/ports/sysdeps/arm/dl-tlsdesc.S +++ b/ports/sysdeps/arm/dl-tlsdesc.S @@ -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 */ diff --git a/ports/sysdeps/arm/sysdep.h b/ports/sysdeps/arm/sysdep.h index 9230131..c525d5b 100644 --- a/ports/sysdeps/arm/sysdep.h +++ b/ports/sysdeps/arm/sysdep.h @@ -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. */ diff --git a/ports/sysdeps/unix/arm/sysdep.S b/ports/sysdeps/unix/arm/sysdep.S index d44ee48..b07cba9 100644 --- a/ports/sysdeps/unix/arm/sysdep.S +++ b/ports/sysdeps/unix/arm/sysdep.S @@ -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 diff --git a/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S b/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S index c4ddbc6..ecdc322 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S +++ b/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S @@ -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) diff --git a/ports/sysdeps/unix/sysv/linux/arm/clone.S b/ports/sysdeps/unix/sysv/linux/arm/clone.S index a5f9b4d..1bc5eab 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/clone.S +++ b/ports/sysdeps/unix/sysv/linux/arm/clone.S @@ -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) diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S b/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S index ff88510..c731cd7 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S +++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S @@ -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. */ \ diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h b/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h index 47d4c70..d5e666b 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h +++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h @@ -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}; \ diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S b/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S index c4be1e2..accecf2 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S +++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S @@ -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. */ \ diff --git a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h index 89208a9..01d8123 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -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. -- 1.8.1.2