blob: e94e5f41ec95f5fb03a5b79b87aa819f1f8bc22b [file] [log] [blame]
Serban Constantinescue2104882013-09-26 11:37:10 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Elliott Hughes54a74942014-01-03 16:40:37 -08003 * All rights reserved.
Serban Constantinescue2104882013-09-26 11:37:10 +01004 *
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
Elliott Hughes851e68a2014-02-19 16:53:20 -080029#include <private/bionic_asm.h>
Peter Collingbourne734beec2018-11-14 12:41:41 -080030#include <private/bionic_constants.h>
Serban Constantinescue2104882013-09-26 11:37:10 +010031
Elliott Hughes9fb536d2014-12-05 12:17:25 -080032// According to AARCH64 PCS document we need to save the following
33// registers:
34//
35// Core x19 - x30, sp (see section 5.1.1)
36// VFP d8 - d15 (see section 5.1.2)
37//
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080038// NOTE: All the registers saved here will have 64 bit vales.
Elliott Hughes9fb536d2014-12-05 12:17:25 -080039// AAPCS mandates that the higher part of q registers do not need to
40// be saved by the callee.
Josh Gao0c3655a2016-03-02 19:45:29 -080041//
42// The internal structure of a jmp_buf is totally private.
43// Current layout (changes from release to release):
44//
45// word name description
46// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
47// 1 sigmask signal mask (not used with _setjmp / _longjmp)
Peter Collingbourne734beec2018-11-14 12:41:41 -080048// 2 core_base base of core registers (x18-x30, sp)
Peter Collingbourne734beec2018-11-14 12:41:41 -080049// 16 float_base base of float registers (d8-d15)
50// 24 checksum checksum of core registers
51// 25 reserved reserved entries (room to grow)
Josh Gao0c3655a2016-03-02 19:45:29 -080052// 32
Elliott Hughes9fb536d2014-12-05 12:17:25 -080053
Elliott Hughes75096222014-12-08 16:01:20 -080054#define _JB_SIGFLAG 0
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080055#define _JB_SIGMASK (_JB_SIGFLAG + 1)
56#define _JB_X30_SP (_JB_SIGMASK + 1)
57#define _JB_X28_X29 (_JB_X30_SP + 2)
58#define _JB_X26_X27 (_JB_X28_X29 + 2)
59#define _JB_X24_X25 (_JB_X26_X27 + 2)
60#define _JB_X22_X23 (_JB_X24_X25 + 2)
61#define _JB_X20_X21 (_JB_X22_X23 + 2)
Peter Collingbourne734beec2018-11-14 12:41:41 -080062#define _JB_SCS_X19 (_JB_X20_X21 + 2)
63#define _JB_D14_D15 (_JB_SCS_X19 + 2)
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080064#define _JB_D12_D13 (_JB_D14_D15 + 2)
Duane Sanddbaab262015-01-26 16:20:05 -080065#define _JB_D10_D11 (_JB_D12_D13 + 2)
66#define _JB_D8_D9 (_JB_D10_D11 + 2)
Josh Gao0c3655a2016-03-02 19:45:29 -080067#define _JB_CHECKSUM (_JB_D8_D9 + 2)
Serban Constantinescue2104882013-09-26 11:37:10 +010068
Josh Gao54db0df2015-09-11 15:23:32 -070069.macro m_mangle_registers reg, sp_reg
Peter Collingbourne734beec2018-11-14 12:41:41 -080070 eor x3, x3, \reg
Josh Gao54db0df2015-09-11 15:23:32 -070071 eor x19, x19, \reg
72 eor x20, x20, \reg
73 eor x21, x21, \reg
74 eor x22, x22, \reg
75 eor x23, x23, \reg
76 eor x24, x24, \reg
77 eor x25, x25, \reg
78 eor x26, x26, \reg
79 eor x27, x27, \reg
80 eor x28, x28, \reg
81 eor x29, x29, \reg
82 eor x30, x30, \reg
83 eor \sp_reg, \sp_reg, \reg
Josh Gao54db0df2015-09-11 15:23:32 -070084.endm
85
Josh Gao0c3655a2016-03-02 19:45:29 -080086.macro m_calculate_checksum dst, src, scratch
87 mov \dst, #0
Peter Collingbourne734beec2018-11-14 12:41:41 -080088 .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,23
Josh Gao0c3655a2016-03-02 19:45:29 -080089 ldr \scratch, [\src, #(\i * 8)]
90 eor \dst, \dst, \scratch
91 .endr
92.endm
93
Josh Gao54db0df2015-09-11 15:23:32 -070094.macro m_unmangle_registers reg, sp_reg
95 m_mangle_registers \reg, sp_reg=\sp_reg
96.endm
97
Elliott Hughesd7831202024-01-19 20:55:31 +000098ENTRY_WEAK_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080099 mov w1, #1
100 b sigsetjmp
Serban Constantinescue2104882013-09-26 11:37:10 +0100101END(setjmp)
102
Elliott Hughesd7831202024-01-19 20:55:31 +0000103ENTRY_WEAK_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800104 mov w1, #0
105 b sigsetjmp
106END(_setjmp)
Serban Constantinescue2104882013-09-26 11:37:10 +0100107
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800108// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
Elliott Hughesd7831202024-01-19 20:55:31 +0000109ENTRY_WEAK_FOR_NATIVE_BRIDGE(sigsetjmp)
Elliott Hughes3e1d5562021-01-25 08:49:01 -0800110 paciasp
Tamas Petzf5bdee72020-08-31 15:09:40 +0200111 .cfi_negate_ra_state
Josh Gao54db0df2015-09-11 15:23:32 -0700112 stp x0, x30, [sp, #-16]!
113 .cfi_def_cfa_offset 16
114 .cfi_rel_offset x0, 0
115 .cfi_rel_offset x30, 8
116
Tamas Zsoldos436f3f12025-04-28 10:07:30 -0700117 // Commit SME's ZA lazy save. Note that the call preserves x1.
118 bl __arm_za_disable
119
Josh Gao54db0df2015-09-11 15:23:32 -0700120 // Get the cookie and store it along with the signal flag.
121 mov x0, x1
122 bl __bionic_setjmp_cookie_get
123 mov x1, x0
124 ldr x0, [sp, #0]
125 str x1, [x0, #(_JB_SIGFLAG * 8)]
Elliott Hughes75096222014-12-08 16:01:20 -0800126
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800127 // Do we need to save the signal mask?
Josh Gao54db0df2015-09-11 15:23:32 -0700128 tbz w1, #0, 1f
129
130 // Save the cookie for later.
131 stp x1, xzr, [sp, #-16]!
132 .cfi_adjust_cfa_offset 16
Serban Constantinescue2104882013-09-26 11:37:10 +0100133
Elliott Hughes7b78e812014-12-05 22:57:55 -0800134 // Save current signal mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800135 // The 'how' argument is ignored if new_mask is NULL.
136 mov x1, #0 // NULL.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800137 add x2, x0, #(_JB_SIGMASK * 8) // old_mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800138 bl sigprocmask
Josh Gao54db0df2015-09-11 15:23:32 -0700139
140 ldp x1, xzr, [sp], #16
141 .cfi_adjust_cfa_offset -16
Serban Constantinescue2104882013-09-26 11:37:10 +0100142
Elliott Hughes9fb536d2014-12-05 12:17:25 -08001431:
Josh Gao54db0df2015-09-11 15:23:32 -0700144 // Restore original x0 and lr.
145 ldp x0, x30, [sp], #16
146 .cfi_adjust_cfa_offset -16
147 .cfi_restore x0
148 .cfi_restore x30
149
150 // Mask off the signal flag bit.
151 bic x1, x1, #1
152
Peter Collingbourne734beec2018-11-14 12:41:41 -0800153 // Mask off the high bits of the shadow call stack pointer.
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000154 // We only store the low bits of x18 to avoid leaking the
155 // shadow call stack address into memory.
156 // See the SCS commentary in pthread_internal.h for more detail.
Peter Collingbourne734beec2018-11-14 12:41:41 -0800157 and x3, x18, #SCS_MASK
158
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800159 // Save core registers.
160 mov x10, sp
Josh Gao54db0df2015-09-11 15:23:32 -0700161 m_mangle_registers x1, sp_reg=x10
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800162 stp x30, x10, [x0, #(_JB_X30_SP * 8)]
163 stp x28, x29, [x0, #(_JB_X28_X29 * 8)]
164 stp x26, x27, [x0, #(_JB_X26_X27 * 8)]
165 stp x24, x25, [x0, #(_JB_X24_X25 * 8)]
166 stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
167 stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
Peter Collingbourne734beec2018-11-14 12:41:41 -0800168 stp x3, x19, [x0, #(_JB_SCS_X19 * 8)]
Josh Gao54db0df2015-09-11 15:23:32 -0700169 m_unmangle_registers x1, sp_reg=x10
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800170
171 // Save floating point registers.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800172 stp d14, d15, [x0, #(_JB_D14_D15 * 8)]
173 stp d12, d13, [x0, #(_JB_D12_D13 * 8)]
174 stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
175 stp d8, d9, [x0, #(_JB_D8_D9 * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800176
Josh Gao0c3655a2016-03-02 19:45:29 -0800177 // Calculate the checksum.
178 m_calculate_checksum x12, x0, x2
179 str x12, [x0, #(_JB_CHECKSUM * 8)]
Josh Gao0c3655a2016-03-02 19:45:29 -0800180
Elliott Hughes75096222014-12-08 16:01:20 -0800181 mov w0, #0
Elliott Hughes3e1d5562021-01-25 08:49:01 -0800182 autiasp
Tamas Petzf5bdee72020-08-31 15:09:40 +0200183 .cfi_negate_ra_state
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800184 ret
185END(sigsetjmp)
186
187// void siglongjmp(sigjmp_buf env, int value);
Elliott Hughesd7831202024-01-19 20:55:31 +0000188ENTRY_WEAK_FOR_NATIVE_BRIDGE(siglongjmp)
Tamas Zsoldos436f3f12025-04-28 10:07:30 -0700189 // First of all, disable SME's ZA, so that it does not interfere
190 // with anything else. Note that __arm_za_disable is guaranteed to
191 // preserve x0 and x1.
192 str x30, [sp, #-16]!
193 .cfi_adjust_cfa_offset 16
194 .cfi_rel_offset x30, 0
195 bl __arm_za_disable
196 ldr x30, [sp], #16
197 .cfi_adjust_cfa_offset -16
198 .cfi_restore x30
199
Josh Gao0c3655a2016-03-02 19:45:29 -0800200 // Check the checksum before doing anything.
201 m_calculate_checksum x12, x0, x2
202 ldr x2, [x0, #(_JB_CHECKSUM * 8)]
Josh Gao0c3655a2016-03-02 19:45:29 -0800203 cmp x2, x12
204 bne __bionic_setjmp_checksum_mismatch
Josh Gao0c3655a2016-03-02 19:45:29 -0800205
Evgenii Stepanov3031a7e2022-05-12 15:50:47 -0700206 // Update stack memory tags (MTE + hwasan).
Evgenii Stepanovb16e9ce2018-08-31 13:02:06 -0700207 stp x0, x30, [sp, #-16]!
208 .cfi_adjust_cfa_offset 16
209 .cfi_rel_offset x0, 0
210 .cfi_rel_offset x30, 8
211 mov x19, x1 // Save 'value'.
212
213 // load and unmangle destination SP
214 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
215 bic x2, x2, #1
216 ldr x0, [x0, #(_JB_X30_SP * 8 + 8)]
217 eor x0, x0, x2
Florian Mayer0e1412e2024-03-06 16:42:45 -0800218 add x1, sp, #16
Evgenii Stepanov3031a7e2022-05-12 15:50:47 -0700219 bl memtag_handle_longjmp
Evgenii Stepanovb16e9ce2018-08-31 13:02:06 -0700220
221 mov x1, x19 // Restore 'value'.
222 // Restore original x0 and lr.
223 ldp x0, x30, [sp], #16
224 .cfi_adjust_cfa_offset -16
225 .cfi_restore x0
226 .cfi_restore x30
Evgenii Stepanovb16e9ce2018-08-31 13:02:06 -0700227
Elliott Hughes75096222014-12-08 16:01:20 -0800228 // Do we need to restore the signal mask?
Josh Gao54db0df2015-09-11 15:23:32 -0700229 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
230 tbz w2, #0, 1f
231
232 stp x0, x30, [sp, #-16]!
233 .cfi_adjust_cfa_offset 16
234 .cfi_rel_offset x0, 0
235 .cfi_rel_offset x30, 8
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800236
237 // Restore signal mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800238 mov x19, x1 // Save 'value'.
Josh Gao54db0df2015-09-11 15:23:32 -0700239
Elliott Hughes7b78e812014-12-05 22:57:55 -0800240 mov x2, x0
241 mov x0, #2 // SIG_SETMASK
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800242 add x1, x2, #(_JB_SIGMASK * 8) // new_mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800243 mov x2, #0 // NULL.
244 bl sigprocmask
245 mov x1, x19 // Restore 'value'.
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800246
Josh Gao54db0df2015-09-11 15:23:32 -0700247 // Restore original x0 and lr.
248 ldp x0, x30, [sp], #16
249 .cfi_adjust_cfa_offset -16
250 .cfi_restore x0
251 .cfi_restore x30
252
253 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -08002541:
255 // Restore core registers.
Josh Gao54db0df2015-09-11 15:23:32 -0700256 bic x2, x2, #1
Tamas Petzf5bdee72020-08-31 15:09:40 +0200257 // x30 was saved with PAC to jmp_buf in sigsetjmp().
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800258 ldp x30, x10, [x0, #(_JB_X30_SP * 8)]
Tamas Petzf5bdee72020-08-31 15:09:40 +0200259 .cfi_negate_ra_state
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800260 ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
261 ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
262 ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
263 ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
264 ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
Peter Collingbourne734beec2018-11-14 12:41:41 -0800265 ldp x3, x19, [x0, #(_JB_SCS_X19 * 8)]
Josh Gao54db0df2015-09-11 15:23:32 -0700266 m_unmangle_registers x2, sp_reg=x10
267 mov sp, x10
268
Peter Collingbourne734beec2018-11-14 12:41:41 -0800269 // Restore the low bits of the shadow call stack pointer.
270 and x18, x18, #~SCS_MASK
271 orr x18, x3, x18
272
Josh Gao54db0df2015-09-11 15:23:32 -0700273 stp x0, x1, [sp, #-16]!
274 .cfi_adjust_cfa_offset 16
275 .cfi_rel_offset x0, 0
276 .cfi_rel_offset x1, 8
277 stp x30, xzr, [sp, #-16]!
278 .cfi_adjust_cfa_offset 16
279 .cfi_rel_offset x30, 0
280 ldr x0, [x0, #(_JB_SIGFLAG * 8)]
281 bl __bionic_setjmp_cookie_check
282 ldp x30, xzr, [sp], #16
283 .cfi_adjust_cfa_offset -16
284 .cfi_restore x30
285 ldp x0, x1, [sp], #16
286 .cfi_adjust_cfa_offset -16
287 .cfi_restore x0
288 .cfi_restore x1
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800289
290 // Restore floating point registers.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800291 ldp d14, d15, [x0, #(_JB_D14_D15 * 8)]
292 ldp d12, d13, [x0, #(_JB_D12_D13 * 8)]
293 ldp d10, d11, [x0, #(_JB_D10_D11 * 8)]
294 ldp d8, d9, [x0, #(_JB_D8_D9 * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800295
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800296 // Set return value.
297 cmp w1, wzr
298 csinc w0, w1, wzr, ne
Elliott Hughes3e1d5562021-01-25 08:49:01 -0800299 autiasp
Tamas Petzf5bdee72020-08-31 15:09:40 +0200300 .cfi_negate_ra_state
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800301 ret
302END(siglongjmp)
303
Elliott Hughesd7831202024-01-19 20:55:31 +0000304ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(longjmp, siglongjmp)
305ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(_longjmp, siglongjmp)
Tamas Petzf5bdee72020-08-31 15:09:40 +0200306
307NOTE_GNU_PROPERTY()