• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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