linux: Add posix_spawnattr_{get, set}cgroup_np (BZ 26371)
[glibc.git] / sysdeps / unix / sysv / linux / i386 / getcontext.S
blobb69a73847b6d15c24e8579e6026fae063f59aef4
1 /* Save current context.
2    Copyright (C) 2001-2023 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <asm/prctl.h>
22 #include "ucontext_i.h"
25 ENTRY(__getcontext)
26         /* Load address of the context data structure.  */
27         movl    4(%esp), %eax
29         /* Save the preserved register values and the return address.  */
30         movl    %edi, oEDI(%eax)
31         movl    %esi, oESI(%eax)
32         movl    %ebp, oEBP(%eax)
33         movl    (%esp), %ecx
34         movl    %ecx, oEIP(%eax)
35         leal    4(%esp), %ecx           /* Exclude the return address.  */
36         movl    %ecx, oESP(%eax)
37         movl    %ebx, oEBX(%eax)
39         /* Save the FS segment register.  We don't touch the GS register
40            since it is used for threads.  */
41         xorl    %edx, %edx
42         movw    %fs, %dx
43         movl    %edx, oFS(%eax)
45 #if SHSTK_ENABLED
46         /* Check if shadow stack is enabled.  */
47         testl   $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
48         jz      L(no_shstk)
50         /* Save EAX in EDX.  */
51         movl    %eax, %edx
53         xorl    %eax, %eax
54         cmpl    %gs:SSP_BASE_OFFSET, %eax
55         jnz     L(shadow_stack_bound_recorded)
57         /* Save EBX in the first scratch register slot.  */
58         movl    %ebx, oSCRATCH1(%edx)
60         /* Get the base address and size of the default shadow stack
61            which must be the current shadow stack since nothing has
62            been recorded yet.  */
63         sub     $24, %esp
64         mov     %esp, %ecx
65         movl    $ARCH_CET_STATUS, %ebx
66         movl    $__NR_arch_prctl, %eax
67         ENTER_KERNEL
68         testl   %eax, %eax
69         jz      L(continue_no_err)
71         /* This should never happen.  */
72         hlt
74 L(continue_no_err):
75         /* Restore EBX from the first scratch register slot.  */
76         movl    oSCRATCH1(%edx), %ebx
78         /* Record the base of the current shadow stack.  */
79         movl    8(%esp), %eax
80         movl    %eax, %gs:SSP_BASE_OFFSET
81         add     $24, %esp
83 L(shadow_stack_bound_recorded):
84         /* Load address of the context data structure.  */
85         movl    4(%esp), %eax
87         /* Get the current shadow stack pointer.  */
88         rdsspd  %edx
89         /* NB: Save the caller's shadow stack so that we can jump back
90            to the caller directly.  */
91         addl    $4, %edx
92         movl    %edx, oSSP(%eax)
94         /* Save the current shadow stack base in ucontext.  */
95         movl    %gs:SSP_BASE_OFFSET, %edx
96         movl    %edx, (oSSP + 4)(%eax)
98 L(no_shstk):
99 #endif
100         /* We have separate floating-point register content memory on the
101            stack.  We use the __fpregs_mem block in the context.  Set the
102            links up correctly.  */
103         leal    oFPREGSMEM(%eax), %ecx
104         movl    %ecx, oFPREGS(%eax)
105         /* Save the floating-point context.  */
106         fnstenv (%ecx)
107         /* And load it right back since the processor changes the mask.
108            Intel thought this opcode to be used in interrupt handlers which
109            would block all exceptions.  */
110         fldenv  (%ecx)
112         /* Save the current signal mask.  */
113         pushl   %ebx
114         cfi_adjust_cfa_offset (4)
115         cfi_rel_offset (ebx, 0)
116         leal    oSIGMASK(%eax), %edx
117         xorl    %ecx, %ecx
118         movl    $SIG_BLOCK, %ebx
119         movl    $__NR_sigprocmask, %eax
120         ENTER_KERNEL
121         popl    %ebx
122         cfi_adjust_cfa_offset (-4)
123         cfi_restore (ebx)
124         cmpl    $-4095, %eax            /* Check %eax for error.  */
125         jae     SYSCALL_ERROR_LABEL     /* Jump to error handler if error.  */
127         /* All done, return 0 for success.  */
128         xorl    %eax, %eax
129         ret
130 PSEUDO_END(__getcontext)
132 weak_alias (__getcontext, getcontext)