From dba942c80dc2cfa5768a856fff98e22a755fdd27 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 4 Oct 2016 06:51:35 +0200 Subject: add experimental aarch64 support Ported over from GNU C Library and runtime tested in Qemu. --- ldso/ldso/aarch64/dl-tlsdesc.S | 207 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 ldso/ldso/aarch64/dl-tlsdesc.S (limited to 'ldso/ldso/aarch64/dl-tlsdesc.S') diff --git a/ldso/ldso/aarch64/dl-tlsdesc.S b/ldso/ldso/aarch64/dl-tlsdesc.S new file mode 100644 index 000000000..4520da69b --- /dev/null +++ b/ldso/ldso/aarch64/dl-tlsdesc.S @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2017 Waldemar Brodkorb + * Ported from GNU C Library + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Thread-local storage handling in the ELF dynamic linker. + AArch64 version. + Copyright (C) 2011-2017 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +#if defined __UCLIBC_HAS_TLS__ + +#include +#include "tlsdesc.h" + +#define PTR_REG(n) x##n +#define PTR_LOG_SIZE 3 +#define PTR_SIZE (1<arg; + dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + TCBHEAD_DTV); + if (__builtin_expect (td->gen_count <= dtv[0].counter + && (dtv[td->tlsinfo.ti_module].pointer.val + != TLS_DTV_UNALLOCATED), + 1)) + return dtv[td->tlsinfo.ti_module].pointer.val + + td->tlsinfo.ti_offset + - __thread_pointer; + + return ___tls_get_addr (&td->tlsinfo) - __thread_pointer; + } + */ + + .hidden _dl_tlsdesc_dynamic + .global _dl_tlsdesc_dynamic + .type _dl_tlsdesc_dynamic,%function + cfi_startproc + .align 2 +_dl_tlsdesc_dynamic: +# define NSAVEXREGPAIRS 2 + stp x29, x30, [sp,#-(32+16*NSAVEXREGPAIRS)]! + cfi_adjust_cfa_offset (32+16*NSAVEXREGPAIRS) + mov x29, sp + + /* Save just enough registers to support fast path, if we fall + into slow path we will save additional registers. */ + + stp x1, x2, [sp, #32+16*0] + stp x3, x4, [sp, #32+16*1] + + mrs x4, tpidr_el0 + /* The ldar here happens after the load from [x0] at the call site + (that is generated by the compiler as part of the TLS access ABI), + so it reads the same value (this function is the final value of + td->entry) and thus it synchronizes with the release store to + td->entry in _dl_tlsdesc_resolve_rela_fixup ensuring that the load + from [x0,#PTR_SIZE] here happens after the initialization of td->arg. */ + ldar PTR_REG (zr), [x0] + ldr PTR_REG (1), [x0,#TLSDESC_ARG] + ldr PTR_REG (0), [x4,#TCBHEAD_DTV] + ldr PTR_REG (3), [x1,#TLSDESC_GEN_COUNT] + ldr PTR_REG (2), [x0,#DTV_COUNTER] + cmp PTR_REG (3), PTR_REG (2) + b.hi 2f + ldr PTR_REG (2), [x1,#TLSDESC_MODID] + add PTR_REG (0), PTR_REG (0), PTR_REG (2), lsl #(PTR_LOG_SIZE + 1) + ldr PTR_REG (0), [x0] /* Load val member of DTV entry. */ + cmp x0, #TLS_DTV_UNALLOCATED + b.eq 2f + ldr PTR_REG (1), [x1,#TLSDESC_MODOFF] + add PTR_REG (0), PTR_REG (0), PTR_REG (1) + sub PTR_REG (0), PTR_REG (0), PTR_REG (4) +1: + ldp x1, x2, [sp, #32+16*0] + ldp x3, x4, [sp, #32+16*1] + + ldp x29, x30, [sp], #(32+16*NSAVEXREGPAIRS) + cfi_adjust_cfa_offset (-32-16*NSAVEXREGPAIRS) +# undef NSAVEXREGPAIRS + ret +2: + /* This is the slow path. We need to call __tls_get_addr() which + means we need to save and restore all the register that the + callee will trash. */ + + /* Save the remaining registers that we must treat as caller save. */ +# define NSAVEXREGPAIRS 7 + stp x5, x6, [sp, #-16*NSAVEXREGPAIRS]! + cfi_adjust_cfa_offset (16*NSAVEXREGPAIRS) + stp x7, x8, [sp, #16*1] + stp x9, x10, [sp, #16*2] + stp x11, x12, [sp, #16*3] + stp x13, x14, [sp, #16*4] + stp x15, x16, [sp, #16*5] + stp x17, x18, [sp, #16*6] + + SAVE_Q_REGISTERS + + mov x0, x1 + bl __tls_get_addr + + mrs x1, tpidr_el0 + sub PTR_REG (0), PTR_REG (0), PTR_REG (1) + + RESTORE_Q_REGISTERS + + ldp x7, x8, [sp, #16*1] + ldp x9, x10, [sp, #16*2] + ldp x11, x12, [sp, #16*3] + ldp x13, x14, [sp, #16*4] + ldp x15, x16, [sp, #16*5] + ldp x17, x18, [sp, #16*6] + ldp x5, x6, [sp], #16*NSAVEXREGPAIRS + cfi_adjust_cfa_offset (-16*NSAVEXREGPAIRS) + b 1b + cfi_endproc + .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic +# undef NSAVEXREGPAIRS + +#endif // SHARED +#endif // __UCLIBC_HAS_TLS__ -- cgit v1.2.3