1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <private/bionic_asm.h> 30 31// According to AARCH64 PCS document we need to save the following 32// registers: 33// 34// Core x19 - x30, sp (see section 5.1.1) 35// VFP d8 - d15 (see section 5.1.2) 36// 37// NOTE: All the registers saved here will have 64 bit vales. 38// AAPCS mandates that the higher part of q registers do not need to 39// be saved by the callee. 40// 41// The internal structure of a jmp_buf is totally private. 42// Current layout (changes from release to release): 43// 44// word name description 45// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit 46// 1 sigmask signal mask (not used with _setjmp / _longjmp) 47// 2 core_base base of core registers (x19-x30, sp) 48// 15 float_base base of float registers (d8-d15) 49// 23 checksum checksum of core registers 50// 24 reserved reserved entries (room to grow) 51// 32 52 53#define _JB_SIGFLAG 0 54#define _JB_SIGMASK (_JB_SIGFLAG + 1) 55#define _JB_X30_SP (_JB_SIGMASK + 1) 56#define _JB_X28_X29 (_JB_X30_SP + 2) 57#define _JB_X26_X27 (_JB_X28_X29 + 2) 58#define _JB_X24_X25 (_JB_X26_X27 + 2) 59#define _JB_X22_X23 (_JB_X24_X25 + 2) 60#define _JB_X20_X21 (_JB_X22_X23 + 2) 61#define _JB_X19 (_JB_X20_X21 + 2) 62#define _JB_D14_D15 (_JB_X19 + 1) 63#define _JB_D12_D13 (_JB_D14_D15 + 2) 64#define _JB_D10_D11 (_JB_D12_D13 + 2) 65#define _JB_D8_D9 (_JB_D10_D11 + 2) 66#define _JB_CHECKSUM (_JB_D8_D9 + 2) 67 68#define MANGLE_REGISTERS 1 69#define USE_CHECKSUM 1 70 71.macro m_mangle_registers reg, sp_reg 72#if MANGLE_REGISTERS 73 eor x19, x19, \reg 74 eor x20, x20, \reg 75 eor x21, x21, \reg 76 eor x22, x22, \reg 77 eor x23, x23, \reg 78 eor x24, x24, \reg 79 eor x25, x25, \reg 80 eor x26, x26, \reg 81 eor x27, x27, \reg 82 eor x28, x28, \reg 83 eor x29, x29, \reg 84 eor x30, x30, \reg 85 eor \sp_reg, \sp_reg, \reg 86#endif 87.endm 88 89.macro m_calculate_checksum dst, src, scratch 90 mov \dst, #0 91 .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 92 ldr \scratch, [\src, #(\i * 8)] 93 eor \dst, \dst, \scratch 94 .endr 95.endm 96 97.macro m_unmangle_registers reg, sp_reg 98 m_mangle_registers \reg, sp_reg=\sp_reg 99.endm 100 101ENTRY(setjmp) 102 mov w1, #1 103 b sigsetjmp 104END(setjmp) 105 106ENTRY(_setjmp) 107 mov w1, #0 108 b sigsetjmp 109END(_setjmp) 110 111// int sigsetjmp(sigjmp_buf env, int save_signal_mask); 112ENTRY(sigsetjmp) 113 stp x0, x30, [sp, #-16]! 114 .cfi_def_cfa_offset 16 115 .cfi_rel_offset x0, 0 116 .cfi_rel_offset x30, 8 117 118 // Get the cookie and store it along with the signal flag. 119 mov x0, x1 120 bl __bionic_setjmp_cookie_get 121 mov x1, x0 122 ldr x0, [sp, #0] 123 str x1, [x0, #(_JB_SIGFLAG * 8)] 124 125 // Do we need to save the signal mask? 126 tbz w1, #0, 1f 127 128 // Save the cookie for later. 129 stp x1, xzr, [sp, #-16]! 130 .cfi_adjust_cfa_offset 16 131 132 // Save current signal mask. 133 // The 'how' argument is ignored if new_mask is NULL. 134 mov x1, #0 // NULL. 135 add x2, x0, #(_JB_SIGMASK * 8) // old_mask. 136 bl sigprocmask 137 138 ldp x1, xzr, [sp], #16 139 .cfi_adjust_cfa_offset -16 140 1411: 142 // Restore original x0 and lr. 143 ldp x0, x30, [sp], #16 144 .cfi_adjust_cfa_offset -16 145 .cfi_restore x0 146 .cfi_restore x30 147 148 // Mask off the signal flag bit. 149 bic x1, x1, #1 150 151 // Save core registers. 152 mov x10, sp 153 m_mangle_registers x1, sp_reg=x10 154 stp x30, x10, [x0, #(_JB_X30_SP * 8)] 155 stp x28, x29, [x0, #(_JB_X28_X29 * 8)] 156 stp x26, x27, [x0, #(_JB_X26_X27 * 8)] 157 stp x24, x25, [x0, #(_JB_X24_X25 * 8)] 158 stp x22, x23, [x0, #(_JB_X22_X23 * 8)] 159 stp x20, x21, [x0, #(_JB_X20_X21 * 8)] 160 str x19, [x0, #(_JB_X19 * 8)] 161 m_unmangle_registers x1, sp_reg=x10 162 163 // Save floating point registers. 164 stp d14, d15, [x0, #(_JB_D14_D15 * 8)] 165 stp d12, d13, [x0, #(_JB_D12_D13 * 8)] 166 stp d10, d11, [x0, #(_JB_D10_D11 * 8)] 167 stp d8, d9, [x0, #(_JB_D8_D9 * 8)] 168 169#if USE_CHECKSUM 170 // Calculate the checksum. 171 m_calculate_checksum x12, x0, x2 172 str x12, [x0, #(_JB_CHECKSUM * 8)] 173#endif 174 175 mov w0, #0 176 ret 177END(sigsetjmp) 178 179// void siglongjmp(sigjmp_buf env, int value); 180ENTRY(siglongjmp) 181#if USE_CHECKSUM 182 // Check the checksum before doing anything. 183 m_calculate_checksum x12, x0, x2 184 ldr x2, [x0, #(_JB_CHECKSUM * 8)] 185 186 cmp x2, x12 187 bne __bionic_setjmp_checksum_mismatch 188#endif 189 190 // Do we need to restore the signal mask? 191 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 192 tbz w2, #0, 1f 193 194 stp x0, x30, [sp, #-16]! 195 .cfi_adjust_cfa_offset 16 196 .cfi_rel_offset x0, 0 197 .cfi_rel_offset x30, 8 198 199 // Restore signal mask. 200 mov x19, x1 // Save 'value'. 201 202 mov x2, x0 203 mov x0, #2 // SIG_SETMASK 204 add x1, x2, #(_JB_SIGMASK * 8) // new_mask. 205 mov x2, #0 // NULL. 206 bl sigprocmask 207 mov x1, x19 // Restore 'value'. 208 209 // Restore original x0 and lr. 210 ldp x0, x30, [sp], #16 211 .cfi_adjust_cfa_offset -16 212 .cfi_restore x0 213 .cfi_restore x30 214 215 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 2161: 217 // Restore core registers. 218 bic x2, x2, #1 219 ldp x30, x10, [x0, #(_JB_X30_SP * 8)] 220 ldp x28, x29, [x0, #(_JB_X28_X29 * 8)] 221 ldp x26, x27, [x0, #(_JB_X26_X27 * 8)] 222 ldp x24, x25, [x0, #(_JB_X24_X25 * 8)] 223 ldp x22, x23, [x0, #(_JB_X22_X23 * 8)] 224 ldp x20, x21, [x0, #(_JB_X20_X21 * 8)] 225 ldr x19, [x0, #(_JB_X19 * 8)] 226 m_unmangle_registers x2, sp_reg=x10 227 mov sp, x10 228 229 stp x0, x1, [sp, #-16]! 230 .cfi_adjust_cfa_offset 16 231 .cfi_rel_offset x0, 0 232 .cfi_rel_offset x1, 8 233 stp x30, xzr, [sp, #-16]! 234 .cfi_adjust_cfa_offset 16 235 .cfi_rel_offset x30, 0 236 ldr x0, [x0, #(_JB_SIGFLAG * 8)] 237 bl __bionic_setjmp_cookie_check 238 ldp x30, xzr, [sp], #16 239 .cfi_adjust_cfa_offset -16 240 .cfi_restore x30 241 ldp x0, x1, [sp], #16 242 .cfi_adjust_cfa_offset -16 243 .cfi_restore x0 244 .cfi_restore x1 245 246 // Restore floating point registers. 247 ldp d14, d15, [x0, #(_JB_D14_D15 * 8)] 248 ldp d12, d13, [x0, #(_JB_D12_D13 * 8)] 249 ldp d10, d11, [x0, #(_JB_D10_D11 * 8)] 250 ldp d8, d9, [x0, #(_JB_D8_D9 * 8)] 251 252 // Set return value. 253 cmp w1, wzr 254 csinc w0, w1, wzr, ne 255 ret 256END(siglongjmp) 257 258ALIAS_SYMBOL(longjmp, siglongjmp) 259ALIAS_SYMBOL(_longjmp, siglongjmp) 260