7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 .file "getcontext.s"
28
29 #include <sys/asm_linkage.h>
30
31 ANSI_PRAGMA_WEAK(getcontext,function)
32 ANSI_PRAGMA_WEAK(swapcontext,function)
33
34 #include "SYS.h"
35 #include <../assym.h>
36
37 /*
38 * getcontext() is written in assembler since it has to capture the correct
39 * machine state of the calle.
40 *
41 * As swapcontext() is actually equivalent to getcontext() + setcontext(),
42 * swapcontext() shares the most code with getcontext().
43 */
44
45 #define GETCONTEXT_IMPL(offset) \
46 pushq %rdi; /* preserve the ucontext_t pointer */ \
47 call __getcontext; \
48 /* call getcontext: syscall */ \
49 popq %rdx; \
50 andl %eax, %eax; /* if (error_return_from_syscall) */ \
51 je 1f; \
52 addq $offset, %rsp; \
53 ret; /* then just return */ \
54 1: \
55 /* \
56 * fix up %rsp and %rip \
57 */ \
58 addq $UC_MCONTEXT_GREGS, %rdx; \
59 /* &ucp->uc_mcontext.gregs */ \
60 movq offset+0(%rsp), %rax; \
61 /* read return PC from stack */ \
62 movq %rax, RIP_OFF (%rdx); \
63 /* store ret PC in EIP of env var */ \
64 leaq offset+8(%rsp), %rax; \
65 /* get caller's sp at time of call */ \
66 movq %rax, RSP_OFF (%rdx); \
67 /* store the sp into UESP of env var */ \
68 xorq %rax, %rax; /* return 0 */ \
69 movq %rax, RAX_OFF (%rdx); \
70 /* getcontext returns 0 after setcontext */
71
72 /*
73 * getcontext(ucontext_t *ucp)
74 */
75
76 ENTRY(getcontext)
77 GETCONTEXT_IMPL(0)
78 ret
79 SET_SIZE(getcontext)
80
81 /*
82 * swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
83 */
84
85 ENTRY(swapcontext)
86 pushq %rsi /* preserve the 2nd argument */
87
88 GETCONTEXT_IMPL(8)
89
90 /* call setcontext */
91 popq %rdi
92 call setcontext
93 ret
94 SET_SIZE(swapcontext)
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2023 Oxide Computer Company
29 */
30
31 .file "getcontext.s"
32
33 #include <sys/asm_linkage.h>
34
35 ANSI_PRAGMA_WEAK(getcontext,function)
36 ANSI_PRAGMA_WEAK(swapcontext,function)
37
38 #include "SYS.h"
39 #include <../assym.h>
40
41 /*
42 * getcontext() is written in assembler since it has to capture the correct
43 * machine state of the calle.
44 *
45 * As swapcontext() is actually equivalent to getcontext() + setcontext(),
46 * swapcontext() shares the most code with getcontext().
47 */
48
49 #define GETCONTEXT_IMPL(offset, func) \
50 pushq %rdi; /* preserve the ucontext_t pointer */ \
51 call func; \
52 /* call getcontext: syscall */ \
53 popq %rdx; \
54 andl %eax, %eax; /* if (error_return_from_syscall) */ \
55 je 1f; \
56 addq $offset, %rsp; \
57 ret; /* then just return */ \
58 1: \
59 /* \
60 * fix up %rsp and %rip \
61 */ \
62 addq $UC_MCONTEXT_GREGS, %rdx; \
63 /* &ucp->uc_mcontext.gregs */ \
64 movq offset+0(%rsp), %rax; \
65 /* read return PC from stack */ \
66 movq %rax, RIP_OFF (%rdx); \
67 /* store ret PC in EIP of env var */ \
68 leaq offset+8(%rsp), %rax; \
69 /* get caller's sp at time of call */ \
70 movq %rax, RSP_OFF (%rdx); \
71 /* store the sp into UESP of env var */ \
72 xorq %rax, %rax; /* return 0 */ \
73 movq %rax, RAX_OFF (%rdx); \
74 /* getcontext returns 0 after setcontext */
75
76 /*
77 * int getcontext(ucontext_t *ucp)
78 */
79
80 ENTRY(getcontext)
81 GETCONTEXT_IMPL(0, __getcontext)
82 ret
83 SET_SIZE(getcontext)
84
85 /*
86 * int swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
87 */
88
89 ENTRY(swapcontext)
90 pushq %rsi /* preserve the 2nd argument */
91
92 GETCONTEXT_IMPL(8, __getcontext)
93
94 /* call setcontext */
95 popq %rdi
96 call setcontext
97 ret
98 SET_SIZE(swapcontext)
99
100 /*
101 * int getcontext_extd(ucontext_t * ctx, uint32_t flags)
102 */
103 ENTRY(getcontext_extd)
104 cmpl $0, %esi
105 jne 2f
106 GETCONTEXT_IMPL(0, __getcontext_extd)
107 ret
108 2:
109 movl $EINVAL, %eax /* errno = EINVAL */
110 jmp __cerror /* return (-1) */
111 SET_SIZE(getcontext_extd)
112
113 /*
114 * int swapcontext_extd(ucontext_t *oucp, uint32_t flags, const ucontext_t *ucp)
115 */
116
117 ENTRY(swapcontext_extd)
118 cmpl $0, %esi
119 jne 2f
120 pushq %rdx /* preserve the 3rd argument */
121
122 GETCONTEXT_IMPL(8, __getcontext_extd)
123
124 /* call setcontext */
125 popq %rdi
126 call setcontext
127 ret
128 2:
129 movl $EINVAL, %eax /* errno = EINVAL */
130 jmp __cerror /* return (-1) */
131 SET_SIZE(swapcontext_extd)
|