1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/* Install given context.
Copyright (C) 2008-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David S. Miller <davem@davemloft.net>, 2008.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <sys/trap.h>
#include "ucontext_i.h"
/* int __setcontext (const ucontext_t *ucp)
Restores the machine context in UCP and thereby resumes execution
in that context.
This implementation is intended to be used for *synchronous* context
switches only. Therefore, it does not have to restore anything
other than the PRESERVED state. */
ENTRY(__setcontext)
save %sp, -112, %sp
mov SIG_SETMASK, %o0
add %i0, UC_SIGMASK, %o1
clr %o2
mov 8, %o3
mov __NR_rt_sigprocmask, %g1
ta 0x10
/* This is a bit on the expensive side, and we could optimize
the unwind similar to how the 32-bit sparc longjmp code
does if performance of this routine really matters. */
ta ST_FLUSH_WINDOWS
ldub [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_EN], %g1
cmp %g1, 0
be 1f
nop
ld [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_FSR], %fsr
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D0], %f0
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D2], %f2
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D4], %f4
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D6], %f6
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D8], %f8
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D10], %f10
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D12], %f12
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D14], %f14
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D16], %f16
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D18], %f18
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D20], %f20
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D22], %f22
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D24], %f24
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D26], %f26
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D28], %f28
ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D30], %f30
1:
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_Y], %g1
wr %g1, 0x0, %y
/* We specifically do not restore %g1 since we need it here as
a temporary. */
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G2], %g2
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G3], %g3
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G4], %g4
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G5], %g5
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G6], %g6
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G7], %g7
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O1], %i1
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O2], %i2
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O3], %i3
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O4], %i4
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O5], %i5
ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O6], %i6
restore
ld [%o0 + UC_MCONTEXT + MC_GREGS + GREG_O7], %o7
ld [%o0 + UC_MCONTEXT + MC_GREGS + GREG_PC], %g1
jmpl %g1, %g0
ld [%o0 + UC_MCONTEXT + MC_GREGS + GREG_O0], %o0
END(__setcontext)
weak_alias (__setcontext, setcontext)
/* We add an NOP here to separate between __setcontext/__startcontext. The
wanted behavior that happens is: when unwinding from a function called
inside a makecontext() context, FDE lookup will use '&__startcontext - 1',
then returns NULL for no FDE found, and immediately ends the unwind, in
a normal fashion.
If this NOP word does not exist, FDE lookup just repeatedly finds
__setcontext's FDE in an infinite loop, due to the convention of using
'address - 1' for FDE lookup. Modifiying/deleting the below
__startcontext's FDE has no help on this. */
nop
/* This is the helper code which gets called if a function which is
registered with 'makecontext' returns. In this case we have to
install the context listed in the uc_link element of the context
'makecontext' manipulated at the time of the 'makecontext' call.
If the pointer is NULL the process must terminate. */
ENTRY(__start_context)
ld [%sp + (16 * 4)], %g1
cmp %g1, 0
be,a 1f
clr %o0
call __setcontext
mov %g1, %o0
/* If this returns (which can happen if the syscall fails) we'll
exit the program with the return error value (-1). */
1: call HIDDEN_JUMPTARGET(exit)
nop
/* The 'exit' call should never return. In case it does cause
the process to terminate. */
unimp
END(__start_context)
|