xref: /aosp_15_r20/external/llvm-libc/src/setjmp/aarch64/longjmp.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Implementation of longjmp for AArch64 -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/setjmp/longjmp.h"
10 #include "src/__support/common.h"
11 #include "src/__support/macros/config.h"
12 
13 namespace LIBC_NAMESPACE_DECL {
14 
15 // TODO: if MTE stack tagging is in use (-fsanitize=memtag-stack), we need to
16 // iterate over the region between the old and new values of sp, using STG or
17 // ST2G instructions to clear the memory tags on the invalidated region of the
18 // stack. But this requires a means of finding out that we're in that mode, and
19 // as far as I can see there isn't currently a predefined macro for that.
20 //
21 // (__ARM_FEATURE_MEMORY_TAGGING only indicates whether the target architecture
22 // supports the MTE instructions, not whether the compiler is configured to use
23 // them.)
24 
25 [[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp,
26                                   ([[maybe_unused]] jmp_buf buf,
27                                    [[maybe_unused]] int val)) {
28   // If BTI branch protection is in use, the compiler will automatically insert
29   // a BTI here, so we don't need to make any extra effort to do so.
30 
31   // If PAC branch protection is in use, there's no need to sign the return
32   // address at the start of longjmp, because we're not going to use it anyway!
33 
34   asm(
35       // Reload the callee-saved GPRs, including fp and lr.
36       R"(
37         ldp x19, x20, [x0,  #0*16]
38         ldp x21, x22, [x0,  #1*16]
39         ldp x23, x24, [x0,  #2*16]
40         ldp x25, x26, [x0,  #3*16]
41         ldp x27, x28, [x0,  #4*16]
42         ldp x29, x30, [x0,  #5*16]
43       )"
44 
45 #if LIBC_COPT_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER
46       // Reload the stack pointer, and the platform register x18.
47       R"(
48         ldp x2,  x18, [x0,  #6*16]
49         mov sp, x2
50       )"
51 #else
52       // Reload just the stack pointer.
53       R"(
54         ldr x2,       [x0,  #6*16]
55         mov sp, x2
56       )"
57 #endif
58 
59 #if __ARM_FP
60       // Reload the callee-saved FP registers.
61       R"(
62         ldp d8,  d9,  [x0,  #7*16]
63         ldp d10, d11, [x0,  #8*16]
64         ldp d12, d13, [x0,  #9*16]
65         ldp d14, d15, [x0, #10*16]
66       )"
67 #endif
68 
69       // Calculate the return value.
70       R"(
71         cmp w1, #0
72         cinc w0, w1, eq
73       )"
74 
75 #if __ARM_FEATURE_PAC_DEFAULT & 1
76       // Authenticate the return address using the PAC A key.
77       R"(
78         autiasp
79       )"
80 #elif __ARM_FEATURE_PAC_DEFAULT & 2
81       // Authenticate the return address using the PAC B key.
82       R"(
83         autibsp
84       )"
85 #endif
86 
87       R"(
88         ret
89       )");
90 }
91 
92 } // namespace LIBC_NAMESPACE_DECL
93