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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
/*
* This file contains the code that gets mapped at the upper end of
* each task's text region. For now, it contains the signal
* trampoline code only.
*
* Copyright (C) 1999 Hewlett-Packard Co
* Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <asm/offsets.h>
#include <asm/sigcontext.h>
#include <asm/system.h>
#include <asm/unistd.h>
#include <asm/page.h>
.psr abi64
.psr lsb
.lsb
.section __gate_section,"ax"
.align PAGE_SIZE
# define SIGINFO_OFF 16
# define SIGCONTEXT_OFF (SIGINFO_OFF + ((IA64_SIGINFO_SIZE + 15) & ~15))
# define FLAGS_OFF IA64_SIGCONTEXT_FLAGS_OFFSET
# define CFM_OFF IA64_SIGCONTEXT_CFM_OFFSET
# define FR6_OFF IA64_SIGCONTEXT_FR6_OFFSET
# define BSP_OFF IA64_SIGCONTEXT_AR_BSP_OFFSET
# define RNAT_OFF IA64_SIGCONTEXT_AR_RNAT_OFFSET
# define base0 r2
# define base1 r3
/*
* When we get here, the memory stack looks like this:
*
* +===============================+
* | |
* // struct sigcontext //
* | |
* +===============================+ <-- sp+SIGCONTEXT_OFF
* | |
* // rest of siginfo //
* | |
* + +---------------+
* | | siginfo.code |
* +---------------+---------------+
* | siginfo.errno | siginfo.signo |
* +-------------------------------+ <-- sp+SIGINFO_OFF
* | 16 byte of scratch |
* | space |
* +-------------------------------+ <-- sp
*
* The register stack looks _exactly_ the way it looked at the
* time the signal occurred. In other words, we're treading
* on a potential mine-field: each incoming general register
* may be a NaT value (includeing sp, in which case the process
* ends up dying with a SIGSEGV).
*
* The first need to do is a cover to get the registers onto
* the backing store. Once that is done, we invoke the signal
* handler which may modify some of the machine state. After
* returning from the signal handler, we return control to the
* previous context by executing a sigreturn system call. A
* signal handler may call the rt_sigreturn() function to
* directly return to a given sigcontext. However, the
* user-level sigreturn() needs to do much more than calling
* the rt_sigreturn() system call as it needs to unwind the
* stack to restore preserved registers that may have been
* saved on the signal handler's call stack.
*
* On entry:
* r2 = signal number
* r3 = plabel of signal handler
* r15 = new register backing store (ignored)
* [sp+16] = sigframe
*/
.global ia64_sigtramp
.proc ia64_sigtramp
ia64_sigtramp:
ld8 r10=[r3],8 // get signal handler entry point
br.call.sptk.many rp=invoke_sighandler
.endp ia64_sigtramp
.proc invoke_sighandler
invoke_sighandler:
ld8 gp=[r3] // get signal handler's global pointer
mov b6=r10
cover // push args in interrupted frame onto backing store
;;
alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8
;;
mov r17=ar.bsp // fetch ar.bsp
cmp.ne p8,p0=r15,r0 // do we need to switch the rbs?
mov out0=r2 // signal number
(p8) br.cond.spnt.few setup_rbs // yup -> (clobbers r14 and r16)
back_from_setup_rbs:
adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
;;
st8 [base0]=r17,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits
adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
;;
st8 [base0]=r8 // save CFM0
adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
;;
stf.spill [base0]=f6,32
stf.spill [base1]=f7,32
;;
stf.spill [base0]=f8,32
stf.spill [base1]=f9,32
;;
stf.spill [base0]=f10,32
stf.spill [base1]=f11,32
adds out1=SIGINFO_OFF,sp // siginfo pointer
;;
stf.spill [base0]=f12,32
stf.spill [base1]=f13,32
adds out2=SIGCONTEXT_OFF,sp // sigcontext pointer
;;
stf.spill [base0]=f14,32
stf.spill [base1]=f15,32
br.call.sptk.few rp=b6 // call the signal handler
.ret2:
adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
;;
ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF
mov r14=ar.bsp
;;
ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0
cmp.ne p8,p0=r14,r15 // do we need to restore the rbs?
(p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16)
;;
back_from_restore_rbs:
adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
;;
ldf.fill f6=[base0],32
ldf.fill f7=[base1],32
;;
ldf.fill f8=[base0],32
ldf.fill f9=[base1],32
;;
ldf.fill f10=[base0],32
ldf.fill f11=[base1],32
;;
ldf.fill f12=[base0],32
ldf.fill f13=[base1],32
;;
ldf.fill f14=[base0],32
ldf.fill f15=[base1],32
mov r15=__NR_rt_sigreturn
break __BREAK_SYSCALL
.endp invoke_sighandler
.proc setup_rbs
setup_rbs:
flushrs // must be first in insn
mov ar.rsc=r0 // put RSE into enforced lazy mode
adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
;;
mov r14=ar.rnat // get rnat as updated by flushrs
mov ar.bspstore=r15 // set new register backing store area
;;
st8 [r16]=r14 // save sc_ar_rnat
mov ar.rsc=0xf // set RSE into eager mode, pl 3
invala // invalidate ALAT
br.cond.sptk.many back_from_setup_rbs
.proc restore_rbs
restore_rbs:
flushrs
mov ar.rsc=r0 // put RSE into enforced lazy mode
adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
;;
ld8 r14=[r16] // get new rnat
mov ar.bspstore=r15 // set old register backing store area
;;
mov ar.rnat=r14 // establish new rnat
mov ar.rsc=0xf // (will be restored later on from sc_ar_rsc)
// invala not necessary as that will happen when returning to user-mode
br.cond.sptk.many back_from_restore_rbs
.endp restore_rbs
|