1*8d67ca89SAndroid Build Coastguard Worker/* 2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2024 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#include <private/bionic_elf_dtv_offset.h> 32*8d67ca89SAndroid Build Coastguard Worker 33*8d67ca89SAndroid Build Coastguard Worker#ifndef TLS_DTV_OFFSET 34*8d67ca89SAndroid Build Coastguard Worker #error "TLS_DTV_OFFSET not defined" 35*8d67ca89SAndroid Build Coastguard Worker#endif 36*8d67ca89SAndroid Build Coastguard Worker 37*8d67ca89SAndroid Build Coastguard Worker.globl __tls_get_addr 38*8d67ca89SAndroid Build Coastguard Worker 39*8d67ca89SAndroid Build Coastguard Worker// spill a register onto the stack 40*8d67ca89SAndroid Build Coastguard Worker.macro spill reg, idx, f= 41*8d67ca89SAndroid Build Coastguard Worker \f\()sd \reg, \idx*8(sp) 42*8d67ca89SAndroid Build Coastguard Worker .cfi_rel_offset \reg, (\idx)*8 43*8d67ca89SAndroid Build Coastguard Worker.endm 44*8d67ca89SAndroid Build Coastguard Worker 45*8d67ca89SAndroid Build Coastguard Worker// reload a value from the stack 46*8d67ca89SAndroid Build Coastguard Worker.macro reload reg, idx, f= 47*8d67ca89SAndroid Build Coastguard Worker \f\()ld \reg, \idx*8(sp) 48*8d67ca89SAndroid Build Coastguard Worker .cfi_same_value \reg 49*8d67ca89SAndroid Build Coastguard Worker.endm 50*8d67ca89SAndroid Build Coastguard Worker 51*8d67ca89SAndroid Build Coastguard Worker.macro spill_vector_regs 52*8d67ca89SAndroid Build Coastguard Worker csrr a3, vlenb 53*8d67ca89SAndroid Build Coastguard Worker slli a3, a3, 3 54*8d67ca89SAndroid Build Coastguard Worker sub sp, sp, a3 55*8d67ca89SAndroid Build Coastguard Worker vs8r.v v0, (sp) 56*8d67ca89SAndroid Build Coastguard Worker sub sp, sp, a3 57*8d67ca89SAndroid Build Coastguard Worker vs8r.v v8, (sp) 58*8d67ca89SAndroid Build Coastguard Worker sub sp, sp, a3 59*8d67ca89SAndroid Build Coastguard Worker vs8r.v v16, (sp) 60*8d67ca89SAndroid Build Coastguard Worker sub sp, sp, a3 61*8d67ca89SAndroid Build Coastguard Worker vs8r.v v24, (sp) 62*8d67ca89SAndroid Build Coastguard Worker.endm 63*8d67ca89SAndroid Build Coastguard Worker 64*8d67ca89SAndroid Build Coastguard Worker.macro reload_vector_regs 65*8d67ca89SAndroid Build Coastguard Worker csrr a3, vlenb 66*8d67ca89SAndroid Build Coastguard Worker slli a3, a3, 3 67*8d67ca89SAndroid Build Coastguard Worker vl8r.v v24, (sp) 68*8d67ca89SAndroid Build Coastguard Worker add sp, sp, a3 69*8d67ca89SAndroid Build Coastguard Worker vl8r.v v16, (sp) 70*8d67ca89SAndroid Build Coastguard Worker add sp, sp, a3 71*8d67ca89SAndroid Build Coastguard Worker vl8r.v v8, (sp) 72*8d67ca89SAndroid Build Coastguard Worker add sp, sp, a3 73*8d67ca89SAndroid Build Coastguard Worker vl8r.v v0, (sp) 74*8d67ca89SAndroid Build Coastguard Worker add sp, sp, a3 75*8d67ca89SAndroid Build Coastguard Worker.endm 76*8d67ca89SAndroid Build Coastguard Worker 77*8d67ca89SAndroid Build Coastguard Worker// We save a total of 35 registers 78*8d67ca89SAndroid Build Coastguard Worker.macro for_each_saved_reg op max 79*8d67ca89SAndroid Build Coastguard Worker \op ra, 1 80*8d67ca89SAndroid Build Coastguard Worker \op a1, 2 81*8d67ca89SAndroid Build Coastguard Worker \op a2, 3 82*8d67ca89SAndroid Build Coastguard Worker \op a3, 4 83*8d67ca89SAndroid Build Coastguard Worker \op a4, 5 84*8d67ca89SAndroid Build Coastguard Worker \op a5, 6 85*8d67ca89SAndroid Build Coastguard Worker \op a6, 7 86*8d67ca89SAndroid Build Coastguard Worker \op a7, 8 87*8d67ca89SAndroid Build Coastguard Worker \op t0, 9 88*8d67ca89SAndroid Build Coastguard Worker \op t1, 10 89*8d67ca89SAndroid Build Coastguard Worker \op t2, 11 90*8d67ca89SAndroid Build Coastguard Worker \op t3, 12 91*8d67ca89SAndroid Build Coastguard Worker \op t4, 13 92*8d67ca89SAndroid Build Coastguard Worker \op t5, 14 93*8d67ca89SAndroid Build Coastguard Worker \op t6, 15 94*8d67ca89SAndroid Build Coastguard Worker // save floating point regs 95*8d67ca89SAndroid Build Coastguard Worker \op ft0, 16, f 96*8d67ca89SAndroid Build Coastguard Worker \op ft1, 17, f 97*8d67ca89SAndroid Build Coastguard Worker \op ft2, 18, f 98*8d67ca89SAndroid Build Coastguard Worker \op ft3, 19, f 99*8d67ca89SAndroid Build Coastguard Worker \op ft4, 20, f 100*8d67ca89SAndroid Build Coastguard Worker \op ft5, 21, f 101*8d67ca89SAndroid Build Coastguard Worker \op ft6, 22, f 102*8d67ca89SAndroid Build Coastguard Worker \op ft7, 23, f 103*8d67ca89SAndroid Build Coastguard Worker \op ft8, 24, f 104*8d67ca89SAndroid Build Coastguard Worker \op ft9, 25, f 105*8d67ca89SAndroid Build Coastguard Worker \op ft10, 26, f 106*8d67ca89SAndroid Build Coastguard Worker \op ft11, 27, f 107*8d67ca89SAndroid Build Coastguard Worker \op fa0, 28, f 108*8d67ca89SAndroid Build Coastguard Worker \op fa1, 29, f 109*8d67ca89SAndroid Build Coastguard Worker \op fa2, 30, f 110*8d67ca89SAndroid Build Coastguard Worker \op fa3, 31, f 111*8d67ca89SAndroid Build Coastguard Worker \op fa4, 32, f 112*8d67ca89SAndroid Build Coastguard Worker \op fa5, 33, f 113*8d67ca89SAndroid Build Coastguard Worker \op fa6, 34, f 114*8d67ca89SAndroid Build Coastguard Worker \op fa7, 35, f 115*8d67ca89SAndroid Build Coastguard Worker.endm 116*8d67ca89SAndroid Build Coastguard Worker 117*8d67ca89SAndroid Build Coastguard Worker// These resolver functions must preserve every register except a0. They set a0 118*8d67ca89SAndroid Build Coastguard Worker// to the offset of the TLS symbol relative to the thread pointer. 119*8d67ca89SAndroid Build Coastguard Worker 120*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_static) 121*8d67ca89SAndroid Build Coastguard Worker ld a0, 8(a0) 122*8d67ca89SAndroid Build Coastguard Worker jr t0 123*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_static) 124*8d67ca89SAndroid Build Coastguard Worker 125*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_dynamic) 126*8d67ca89SAndroid Build Coastguard Worker // We only need 3 stack slots, but still require a 4th slot for alignment 127*8d67ca89SAndroid Build Coastguard Worker addi sp, sp, -4*8 128*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset 4*8 129*8d67ca89SAndroid Build Coastguard Worker spill a1, 1 130*8d67ca89SAndroid Build Coastguard Worker spill a2, 2 131*8d67ca89SAndroid Build Coastguard Worker spill a3, 3 132*8d67ca89SAndroid Build Coastguard Worker 133*8d67ca89SAndroid Build Coastguard Worker ld a2, (TLS_SLOT_DTV * 8)(tp) // a2 = &DTV 134*8d67ca89SAndroid Build Coastguard Worker ld a1, (a2) // a1 = TlsDtv::generation (DTV[0]) 135*8d67ca89SAndroid Build Coastguard Worker 136*8d67ca89SAndroid Build Coastguard Worker ld a0, 8(a0) // a0 = TlsDynamicResolverArg* 137*8d67ca89SAndroid Build Coastguard Worker ld a3, (a0) // a3 = TlsDynamicResolverArg::generation 138*8d67ca89SAndroid Build Coastguard Worker 139*8d67ca89SAndroid Build Coastguard Worker // Fallback if TlsDtv::generation < TlsDynamicResolverArg::generation 140*8d67ca89SAndroid Build Coastguard Worker // since we need to call __tls_get_addr 141*8d67ca89SAndroid Build Coastguard Worker blt a1, a3, L(fallback) 142*8d67ca89SAndroid Build Coastguard Worker 143*8d67ca89SAndroid Build Coastguard Worker // We can't modify a0 yet, since tlsdesc_resolver_dynamic_slow_path requires 144*8d67ca89SAndroid Build Coastguard Worker // a pointer to the TlsIndex, which is the second field of the 145*8d67ca89SAndroid Build Coastguard Worker // TlsDynamicResolverArg. As a result, we can't modify a0 until we will no 146*8d67ca89SAndroid Build Coastguard Worker // longer fallback. 147*8d67ca89SAndroid Build Coastguard Worker ld a1, 8(a0) // a1 = TlsIndex::module_id 148*8d67ca89SAndroid Build Coastguard Worker slli a1, a1, 3 // a1 = module_id*8 -- scale the idx 149*8d67ca89SAndroid Build Coastguard Worker add a1, a2, a1 // a1 = &TlsDtv::modules[module_id] 150*8d67ca89SAndroid Build Coastguard Worker ld a1, (a1) // a1 = TlsDtv::modules[module_id] 151*8d67ca89SAndroid Build Coastguard Worker beqz a1, L(fallback) 152*8d67ca89SAndroid Build Coastguard Worker ld a3, 16(a0) // a3 = TlsIndex::offset 153*8d67ca89SAndroid Build Coastguard Worker add a0, a1, a3 // a0 = TlsDtv::modules[module_id] + offset 154*8d67ca89SAndroid Build Coastguard Worker sub a0, a0, tp // a0 = TlsDtv::modules[module_id] + offset - tp 155*8d67ca89SAndroid Build Coastguard Worker 156*8d67ca89SAndroid Build Coastguard Worker .cfi_remember_state 157*8d67ca89SAndroid Build Coastguard Worker reload a3, 3 158*8d67ca89SAndroid Build Coastguard Worker reload a2, 2 159*8d67ca89SAndroid Build Coastguard Worker reload a1, 1 160*8d67ca89SAndroid Build Coastguard Worker addi sp, sp, 4*8 161*8d67ca89SAndroid Build Coastguard Worker .cfi_adjust_cfa_offset -4*8 162*8d67ca89SAndroid Build Coastguard Worker jr t0 163*8d67ca89SAndroid Build Coastguard Worker 164*8d67ca89SAndroid Build Coastguard WorkerL(fallback): 165*8d67ca89SAndroid Build Coastguard Worker reload a3, 3 166*8d67ca89SAndroid Build Coastguard Worker reload a2, 2 167*8d67ca89SAndroid Build Coastguard Worker reload a1, 1 168*8d67ca89SAndroid Build Coastguard Worker addi sp, sp, 4*8 169*8d67ca89SAndroid Build Coastguard Worker .cfi_adjust_cfa_offset -4*8 170*8d67ca89SAndroid Build Coastguard Worker j tlsdesc_resolver_dynamic_slow_path 171*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_dynamic) 172*8d67ca89SAndroid Build Coastguard Worker 173*8d67ca89SAndroid Build Coastguard Worker// On entry, a0 is the address of a TlsDynamicResolverArg object rather than 174*8d67ca89SAndroid Build Coastguard Worker// the TlsDescriptor address passed to the original resolver function. 175*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_dynamic_slow_path) 176*8d67ca89SAndroid Build Coastguard Worker // We save a total of 35 registers, but vector spills require an alignment 177*8d67ca89SAndroid Build Coastguard Worker // of 16, so use an extra slot to align it correctly. 178*8d67ca89SAndroid Build Coastguard Worker addi sp, sp, (-8*36) 179*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset (8 * 36) 180*8d67ca89SAndroid Build Coastguard Worker for_each_saved_reg spill, 36 181*8d67ca89SAndroid Build Coastguard Worker spill_vector_regs 182*8d67ca89SAndroid Build Coastguard Worker 183*8d67ca89SAndroid Build Coastguard Worker add a0, a0, 8 184*8d67ca89SAndroid Build Coastguard Worker call __tls_get_addr 185*8d67ca89SAndroid Build Coastguard Worker addi a0, a0, (-1 * TLS_DTV_OFFSET) // Correct the address by TLS_DTV_OFFSET 186*8d67ca89SAndroid Build Coastguard Worker sub a0, a0, tp 187*8d67ca89SAndroid Build Coastguard Worker 188*8d67ca89SAndroid Build Coastguard Worker reload_vector_regs 189*8d67ca89SAndroid Build Coastguard Worker for_each_saved_reg reload, 36 190*8d67ca89SAndroid Build Coastguard Worker addi sp, sp, 8*36 191*8d67ca89SAndroid Build Coastguard Worker .cfi_def_cfa_offset 0 192*8d67ca89SAndroid Build Coastguard Worker jr t0 193*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_dynamic_slow_path) 194*8d67ca89SAndroid Build Coastguard Worker 195*8d67ca89SAndroid Build Coastguard Worker// The address of an unresolved weak TLS symbol evaluates to NULL with TLSDESC. 196*8d67ca89SAndroid Build Coastguard Worker// The value returned by this function is added to the thread pointer, so return 197*8d67ca89SAndroid Build Coastguard Worker// a negated thread pointer to cancel it out. 198*8d67ca89SAndroid Build Coastguard WorkerENTRY_PRIVATE(tlsdesc_resolver_unresolved_weak) 199*8d67ca89SAndroid Build Coastguard Worker sub a0, zero, tp 200*8d67ca89SAndroid Build Coastguard Worker jr t0 201*8d67ca89SAndroid Build Coastguard WorkerEND(tlsdesc_resolver_unresolved_weak) 202