1 | /* Modify saved context. |
2 | |
3 | Copyright (C) 2009-2022 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 | |
23 | #include "ucontext_i.h" |
24 | #include "ucontext-internal.h" |
25 | |
26 | /* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ |
27 | |
28 | .text |
29 | ENTRY(__swapcontext) |
30 | PTR_ARG (0) |
31 | /* Set the value returned when swapcontext() returns in this context. |
32 | And set up x1 to become the return address of the caller, so we |
33 | can return there with a normal RET instead of an indirect jump. */ |
34 | stp xzr, x30, [x0, oX0 + 0 * SZREG] |
35 | /* Arrange the oucp context to return to 2f. */ |
36 | adr x30, 2f |
37 | |
38 | stp x18, x19, [x0, oX0 + 18 * SZREG] |
39 | stp x20, x21, [x0, oX0 + 20 * SZREG] |
40 | stp x22, x23, [x0, oX0 + 22 * SZREG] |
41 | stp x24, x25, [x0, oX0 + 24 * SZREG] |
42 | stp x26, x27, [x0, oX0 + 26 * SZREG] |
43 | stp x28, x29, [x0, oX0 + 28 * SZREG] |
44 | str x30, [x0, oX0 + 30 * SZREG] |
45 | str x30, [x0, oPC] |
46 | mov x2, sp |
47 | str x2, [x0, oSP] |
48 | |
49 | /* Figure out where to place the first context extension |
50 | block. */ |
51 | add x2, x0, #oEXTENSION |
52 | |
53 | /* Write the context extension fpsimd header. */ |
54 | mov w3, #(FPSIMD_MAGIC & 0xffff) |
55 | movk w3, #(FPSIMD_MAGIC >> 16), lsl #16 |
56 | str w3, [x2, #oHEAD + oMAGIC] |
57 | mov w3, #FPSIMD_CONTEXT_SIZE |
58 | str w3, [x2, #oHEAD + oSIZE] |
59 | |
60 | /* Fill in the FP SIMD context. */ |
61 | add x3, x2, #oV0 + 8 * SZVREG |
62 | stp q8, q9, [x3], #2 * SZVREG |
63 | stp q10, q11, [x3], #2 * SZVREG |
64 | stp q12, q13, [x3], #2 * SZVREG |
65 | stp q14, q15, [x3], #2 * SZVREG |
66 | |
67 | add x3, x2, #oFPSR |
68 | |
69 | mrs x4, fpsr |
70 | str w4, [x3, #oFPSR - oFPSR] |
71 | |
72 | mrs x4, fpcr |
73 | str w4, [x3, #oFPCR - oFPSR] |
74 | |
75 | /* Write the termination context extension header. */ |
76 | add x2, x2, #FPSIMD_CONTEXT_SIZE |
77 | |
78 | str xzr, [x2, #oHEAD + oMAGIC] |
79 | str xzr, [x2, #oHEAD + oSIZE] |
80 | |
81 | /* Preserve ucp. */ |
82 | mov x21, x1 |
83 | |
84 | /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, |
85 | _NSIG8) */ |
86 | /* Grab the signal mask */ |
87 | /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ |
88 | add x2, x0, #UCONTEXT_SIGMASK |
89 | mov x0, SIG_BLOCK |
90 | mov x1, 0 |
91 | mov x3, _NSIG8 |
92 | mov x8, SYS_ify (rt_sigprocmask) |
93 | svc 0 |
94 | cbnz x0, 1f |
95 | |
96 | mov x22, x30 |
97 | mov x0, x21 |
98 | bl JUMPTARGET (__setcontext) |
99 | mov x30, x22 |
100 | RET |
101 | |
102 | 1: |
103 | b C_SYMBOL_NAME(__syscall_error) |
104 | 2: |
105 | /* The oucp context is restored here via an indirect branch, |
106 | x1 must be restored too which has the real return address. */ |
107 | BTI_J |
108 | mov x30, x1 |
109 | RET |
110 | PSEUDO_END (__swapcontext) |
111 | weak_alias (__swapcontext, swapcontext) |
112 | |