1*8d67ca89SAndroid Build Coastguard Worker/* 2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project 3*8d67ca89SAndroid Build Coastguard Worker * All rights reserved. 4*8d67ca89SAndroid Build Coastguard Worker * 5*8d67ca89SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 6*8d67ca89SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions 7*8d67ca89SAndroid Build Coastguard Worker * are met: 8*8d67ca89SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright 9*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer. 10*8d67ca89SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright 11*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in 12*8d67ca89SAndroid Build Coastguard Worker * the documentation and/or other materials provided with the 13*8d67ca89SAndroid Build Coastguard Worker * distribution. 14*8d67ca89SAndroid Build Coastguard Worker * 15*8d67ca89SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16*8d67ca89SAndroid Build Coastguard Worker * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17*8d67ca89SAndroid Build Coastguard Worker * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18*8d67ca89SAndroid Build Coastguard Worker * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19*8d67ca89SAndroid Build Coastguard Worker * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20*8d67ca89SAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21*8d67ca89SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22*8d67ca89SAndroid Build Coastguard Worker * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23*8d67ca89SAndroid Build Coastguard Worker * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24*8d67ca89SAndroid Build Coastguard Worker * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25*8d67ca89SAndroid Build Coastguard Worker * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*8d67ca89SAndroid Build Coastguard Worker * SUCH DAMAGE. 27*8d67ca89SAndroid Build Coastguard Worker */ 28*8d67ca89SAndroid Build Coastguard Worker 29*8d67ca89SAndroid Build Coastguard Worker#include <platform/bionic/tls_defines.h> 30*8d67ca89SAndroid Build Coastguard Worker#include <private/bionic_asm.h> 31*8d67ca89SAndroid Build Coastguard Worker 32*8d67ca89SAndroid Build Coastguard Worker.globl __tls_get_addr 33*8d67ca89SAndroid Build Coastguard Worker 34*8d67ca89SAndroid Build Coastguard Worker// These resolver functions must preserve every register except x0. They set x0 35*8d67ca89SAndroid Build Coastguard Worker// to the offset of the TLS symbol relative to the thread pointer. 36*8d67ca89SAndroid Build Coastguard Worker 37*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_static) 38*8d67ca89SAndroid Build Coastguard Worker ldr x0, [x0, #8] 39*8d67ca89SAndroid Build Coastguard Worker ret 40*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_static) 41*8d67ca89SAndroid Build Coastguard Worker 42*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_dynamic) 43*8d67ca89SAndroid Build Coastguard Worker stp x19, x20, [sp, #-32]! 44*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset 32 45*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x19, 0 46*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x20, 8 47*8d67ca89SAndroid Build Coastguard Worker stp x21, x22, [sp, #16] 48*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x21, 16 49*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x22, 24 50*8d67ca89SAndroid Build Coastguard Worker 51*8d67ca89SAndroid Build Coastguard Worker mrs x19, tpidr_el0 // __get_tls() 52*8d67ca89SAndroid Build Coastguard Worker ldr x20, [x19, #(TLS_SLOT_DTV * 8)] 53*8d67ca89SAndroid Build Coastguard Worker ldr x21, [x20] // TlsDtv::generation 54*8d67ca89SAndroid Build Coastguard Worker 55*8d67ca89SAndroid Build Coastguard Worker ldr x0, [x0, #8] // TlsDynamicResolverArg* 56*8d67ca89SAndroid Build Coastguard Worker ldr x22, [x0] // TlsDynamicResolverArg::generation 57*8d67ca89SAndroid Build Coastguard Worker 58*8d67ca89SAndroid Build Coastguard Worker cmp x21, x22 59*8d67ca89SAndroid Build Coastguard Worker b.lo L(fallback) 60*8d67ca89SAndroid Build Coastguard Worker 61*8d67ca89SAndroid Build Coastguard Worker ldr x21, [x0, #8] // TlsIndex::module_id 62*8d67ca89SAndroid Build Coastguard Worker ldr x22, [x0, #16] // TlsIndex::offset 63*8d67ca89SAndroid Build Coastguard Worker ldr x21, [x20, x21, lsl #3] // TlsDtv::modules[module_id] 64*8d67ca89SAndroid Build Coastguard Worker cbz x21, L(fallback) 65*8d67ca89SAndroid Build Coastguard Worker add x0, x21, x22 66*8d67ca89SAndroid Build Coastguard Worker sub x0, x0, x19 67*8d67ca89SAndroid Build Coastguard Worker 68*8d67ca89SAndroid Build Coastguard Worker ldp x21, x22, [sp, #16] 69*8d67ca89SAndroid Build Coastguard Worker .cfi_remember_state 70*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x21 71*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x22 72*8d67ca89SAndroid Build Coastguard Worker ldp x19, x20, [sp], #32 73*8d67ca89SAndroid Build Coastguard Worker .cfi_adjust_cfa_offset -32 74*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x19 75*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x20 76*8d67ca89SAndroid Build Coastguard Worker ret 77*8d67ca89SAndroid Build Coastguard Worker 78*8d67ca89SAndroid Build Coastguard WorkerL(fallback): 79*8d67ca89SAndroid Build Coastguard Worker .cfi_restore_state 80*8d67ca89SAndroid Build Coastguard Worker ldp x21, x22, [sp, #16] 81*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x21 82*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x22 83*8d67ca89SAndroid Build Coastguard Worker ldp x19, x20, [sp], #32 84*8d67ca89SAndroid Build Coastguard Worker .cfi_adjust_cfa_offset -32 85*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x19 86*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x20 87*8d67ca89SAndroid Build Coastguard Worker b tlsdesc_resolver_dynamic_slow_path 88*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_dynamic) 89*8d67ca89SAndroid Build Coastguard Worker 90*8d67ca89SAndroid Build Coastguard Worker#define SAVE_REG(x, slot) \ 91*8d67ca89SAndroid Build Coastguard Worker str x, [sp, #((slot) * 8)]; \ 92*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x, (slot) * 8; \ 93*8d67ca89SAndroid Build Coastguard Worker 94*8d67ca89SAndroid Build Coastguard Worker#define SAVE_GPR_PAIR(x, y, slot) \ 95*8d67ca89SAndroid Build Coastguard Worker stp x, y, [sp, #((slot) * 8)]; \ 96*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x, (slot) * 8; \ 97*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset y, ((slot) + 1) * 8; \ 98*8d67ca89SAndroid Build Coastguard Worker 99*8d67ca89SAndroid Build Coastguard Worker#define SAVE_VEC_PAIR(x, y, slot) \ 100*8d67ca89SAndroid Build Coastguard Worker stp x, y, [sp, #((slot) * 8)]; \ 101*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x, (slot) * 8; \ 102*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset y, ((slot) + 2) * 8; \ 103*8d67ca89SAndroid Build Coastguard Worker 104*8d67ca89SAndroid Build Coastguard Worker#define RESTORE_REG(x, slot) \ 105*8d67ca89SAndroid Build Coastguard Worker ldr x, [sp, #((slot) * 8)]; \ 106*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x; \ 107*8d67ca89SAndroid Build Coastguard Worker 108*8d67ca89SAndroid Build Coastguard Worker#define RESTORE_REG_PAIR(x, y, slot) \ 109*8d67ca89SAndroid Build Coastguard Worker ldp x, y, [sp, #((slot) * 8)]; \ 110*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x; \ 111*8d67ca89SAndroid Build Coastguard Worker .cfi_restore y; \ 112*8d67ca89SAndroid Build Coastguard Worker 113*8d67ca89SAndroid Build Coastguard Worker// On entry, x0 is the address of a TlsDynamicResolverArg object rather than 114*8d67ca89SAndroid Build Coastguard Worker// the TlsDescriptor address passed to the original resolver function. 115*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_dynamic_slow_path) 116*8d67ca89SAndroid Build Coastguard Worker sub sp, sp, #(8 * 84) 117*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset (8 * 84) 118*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x29, x30, 0) 119*8d67ca89SAndroid Build Coastguard Worker mov x29, sp 120*8d67ca89SAndroid Build Coastguard Worker 121*8d67ca89SAndroid Build Coastguard Worker // Avoid leaking the contents of the shadow call stack register (x18) into 122*8d67ca89SAndroid Build Coastguard Worker // memory. x19 through x29 are callee-save registers, so we do not need to 123*8d67ca89SAndroid Build Coastguard Worker // save them. 124*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x1, x2, 2) 125*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x3, x4, 4) 126*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x5, x6, 6) 127*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x7, x8, 8) 128*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x9, x10, 10) 129*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x11, x12, 12) 130*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x13, x14, 14) 131*8d67ca89SAndroid Build Coastguard Worker SAVE_GPR_PAIR(x15, x16, 16) 132*8d67ca89SAndroid Build Coastguard Worker SAVE_REG(x17, 18) 133*8d67ca89SAndroid Build Coastguard Worker 134*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q0, q1, 20) 135*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q2, q3, 24) 136*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q4, q5, 28) 137*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q6, q7, 32) 138*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q8, q9, 36) 139*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q10, q11, 40) 140*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q12, q13, 44) 141*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q14, q15, 48) 142*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q16, q17, 52) 143*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q18, q19, 56) 144*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q20, q21, 60) 145*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q22, q23, 64) 146*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q24, q25, 68) 147*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q26, q27, 72) 148*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q28, q29, 76) 149*8d67ca89SAndroid Build Coastguard Worker SAVE_VEC_PAIR(q30, q31, 80) 150*8d67ca89SAndroid Build Coastguard Worker 151*8d67ca89SAndroid Build Coastguard Worker add x0, x0, #8 152*8d67ca89SAndroid Build Coastguard Worker bl __tls_get_addr 153*8d67ca89SAndroid Build Coastguard Worker mrs x1, tpidr_el0 // __get_tls() 154*8d67ca89SAndroid Build Coastguard Worker sub x0, x0, x1 155*8d67ca89SAndroid Build Coastguard Worker 156*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q30, q31, 80) 157*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q28, q29, 76) 158*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q26, q27, 72) 159*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q24, q25, 68) 160*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q22, q23, 64) 161*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q20, q21, 60) 162*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q18, q19, 56) 163*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q16, q17, 52) 164*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q14, q15, 48) 165*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q12, q13, 44) 166*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q10, q11, 40) 167*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q8, q9, 36) 168*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q6, q7, 32) 169*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q4, q5, 28) 170*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q2, q3, 24) 171*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(q0, q1, 20) 172*8d67ca89SAndroid Build Coastguard Worker 173*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG(x17, 18) 174*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x15, x16, 16) 175*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x13, x14, 14) 176*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x11, x12, 12) 177*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x9, x10, 10) 178*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x7, x8, 8) 179*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x5, x6, 6) 180*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x3, x4, 4) 181*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x1, x2, 2) 182*8d67ca89SAndroid Build Coastguard Worker 183*8d67ca89SAndroid Build Coastguard Worker RESTORE_REG_PAIR(x29, x30, 0) 184*8d67ca89SAndroid Build Coastguard Worker add sp, sp, #(8 * 84) 185*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset 0 186*8d67ca89SAndroid Build Coastguard Worker ret 187*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_dynamic_slow_path) 188*8d67ca89SAndroid Build Coastguard Worker 189*8d67ca89SAndroid Build Coastguard Worker// The address of an unresolved weak TLS symbol evaluates to NULL with TLSDESC. 190*8d67ca89SAndroid Build Coastguard Worker// The value returned by this function is added to the thread pointer, so return 191*8d67ca89SAndroid Build Coastguard Worker// a negated thread pointer to cancel it out. 192*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_unresolved_weak) 193*8d67ca89SAndroid Build Coastguard Worker str x19, [sp, #-16]! 194*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset 16 195*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset x19, 0 196*8d67ca89SAndroid Build Coastguard Worker ldr x19, [x0, #8] 197*8d67ca89SAndroid Build Coastguard Worker mrs x0, tpidr_el0 // __get_tls() 198*8d67ca89SAndroid Build Coastguard Worker sub x0, x19, x0 199*8d67ca89SAndroid Build Coastguard Worker ldr x19, [sp], #16 200*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset 0 201*8d67ca89SAndroid Build Coastguard Worker .cfi_restore x19 202*8d67ca89SAndroid Build Coastguard Worker ret 203*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_unresolved_weak) 204