1/* Set current context.
2
3 Copyright (C) 2009-2024 Free Software Foundation, Inc.
4
5 This file is part of the GNU C Library.
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <https://www.gnu.org/licenses/>. */
20
21#include <sysdep.h>
22#include "ucontext_i.h"
23#include "ucontext-internal.h"
24
25/* int __setcontext (const ucontext_t *ucp)
26
27 Restores the machine context in UCP and thereby resumes execution
28 in that context.
29
30 This implementation is intended to be used for *synchronous* context
31 switches only. Therefore, it does not have to restore anything
32 other than the PRESERVED state. */
33
34 .text
35
36ENTRY (__setcontext)
37 PTR_ARG (0)
38 /* Save a copy of UCP. */
39 mov x9, x0
40
41 /* Set the signal mask with
42 rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8). */
43 mov x0, #SIG_SETMASK
44 add x1, x9, #UCONTEXT_SIGMASK
45 mov x2, #0
46 mov x3, #_NSIG8
47 mov x8, SYS_ify (rt_sigprocmask)
48 svc 0
49 cbz x0, 1f
50 b C_SYMBOL_NAME (__syscall_error)
511:
52 /* Disable ZA of SME. */
53#if HAVE_AARCH64_PAC_RET
54 PACIASP
55 cfi_window_save
56#endif
57 stp x29, x30, [sp, -16]!
58 cfi_adjust_cfa_offset (16)
59 cfi_rel_offset (x29, 0)
60 cfi_rel_offset (x30, 8)
61 mov x29, sp
62 bl __libc_arm_za_disable
63 ldp x29, x30, [sp], 16
64 cfi_adjust_cfa_offset (-16)
65 cfi_restore (x29)
66 cfi_restore (x30)
67#if HAVE_AARCH64_PAC_RET
68 AUTIASP
69 cfi_window_save
70#endif
71 /* Restore the general purpose registers. */
72 mov x0, x9
73 cfi_def_cfa (x0, 0)
74 cfi_offset (x18, oX0 + 18 * SZREG)
75 cfi_offset (x19, oX0 + 19 * SZREG)
76 cfi_offset (x20, oX0 + 20 * SZREG)
77 cfi_offset (x21, oX0 + 21 * SZREG)
78 cfi_offset (x22, oX0 + 22 * SZREG)
79 cfi_offset (x23, oX0 + 23 * SZREG)
80 cfi_offset (x24, oX0 + 24 * SZREG)
81 cfi_offset (x25, oX0 + 25 * SZREG)
82 cfi_offset (x26, oX0 + 26 * SZREG)
83 cfi_offset (x27, oX0 + 27 * SZREG)
84 cfi_offset (x28, oX0 + 28 * SZREG)
85 cfi_offset (x29, oX0 + 29 * SZREG)
86 cfi_offset (x30, oX0 + 30 * SZREG)
87
88 cfi_offset ( d8, oV0 + 8 * SZVREG)
89 cfi_offset ( d9, oV0 + 9 * SZVREG)
90 cfi_offset (d10, oV0 + 10 * SZVREG)
91 cfi_offset (d11, oV0 + 11 * SZVREG)
92 cfi_offset (d12, oV0 + 12 * SZVREG)
93 cfi_offset (d13, oV0 + 13 * SZVREG)
94 cfi_offset (d14, oV0 + 14 * SZVREG)
95 cfi_offset (d15, oV0 + 15 * SZVREG)
96 ldp x18, x19, [x0, oX0 + 18 * SZREG]
97 ldp x20, x21, [x0, oX0 + 20 * SZREG]
98 ldp x22, x23, [x0, oX0 + 22 * SZREG]
99 ldp x24, x25, [x0, oX0 + 24 * SZREG]
100 ldp x26, x27, [x0, oX0 + 26 * SZREG]
101 ldp x28, x29, [x0, oX0 + 28 * SZREG]
102 ldr x30, [x0, oX0 + 30 * SZREG]
103 ldr x2, [x0, oSP]
104 mov sp, x2
105
106 /* Check for FP SIMD context. We don't support restoring
107 contexts created by the kernel, so this context must have
108 been created by getcontext. Hence we can rely on the
109 first extension block being the FP SIMD context. */
110 add x2, x0, #oEXTENSION
111
112 mov w3, #(FPSIMD_MAGIC & 0xffff)
113 movk w3, #(FPSIMD_MAGIC >> 16), lsl #16
114 ldr w1, [x2, #oHEAD + oMAGIC]
115 cmp w1, w3
116 b.ne 2f
117
118 /* Restore the FP SIMD context. */
119 add x3, x2, #oV0 + 8 * SZVREG
120 ldp q8, q9, [x3], #2 * SZVREG
121 ldp q10, q11, [x3], #2 * SZVREG
122 ldp q12, q13, [x3], #2 * SZVREG
123 ldp q14, q15, [x3], #2 * SZVREG
124
125 add x3, x2, oFPSR
126
127 ldr w4, [x3]
128 msr fpsr, x4
129
130 ldr w4, [x3, oFPCR - oFPSR]
131 msr fpcr, x4
132
1332:
134 ldr x16, [x0, oPC]
135 /* Restore arg registers. */
136 ldp x2, x3, [x0, oX0 + 2 * SZREG]
137 ldp x4, x5, [x0, oX0 + 4 * SZREG]
138 ldp x6, x7, [x0, oX0 + 6 * SZREG]
139 ldp x0, x1, [x0, oX0 + 0 * SZREG]
140 /* Jump to the new pc value. */
141 br x16
142PSEUDO_END (__setcontext)
143weak_alias (__setcontext, setcontext)
144
145ENTRY (__startcontext)
146 mov x0, x19
147 cbnz x0, __setcontext
1481: b HIDDEN_JUMPTARGET (exit)
149END (__startcontext)
150

source code of glibc/sysdeps/unix/sysv/linux/aarch64/setcontext.S