File: gate.S

package info (click to toggle)
kernel-source-2.4.14 2.4.14-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 139,160 kB
  • ctags: 428,423
  • sloc: ansic: 2,435,554; asm: 141,119; makefile: 8,258; sh: 3,099; perl: 2,561; yacc: 1,177; cpp: 755; tcl: 577; lex: 352; awk: 251; lisp: 218; sed: 72
file content (183 lines) | stat: -rw-r--r-- 6,258 bytes parent folder | download | duplicates (2)
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
/*
 * 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-2001 Hewlett-Packard Co
 * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
 */

#include <asm/asmmacro.h>
#include <asm/offsets.h>
#include <asm/sigcontext.h>
#include <asm/system.h>
#include <asm/unistd.h>
#include <asm/page.h>

	.section .text.gate,"ax"

#	define ARG0_OFF		(16 + IA64_SIGFRAME_ARG0_OFFSET)
#	define ARG1_OFF		(16 + IA64_SIGFRAME_ARG1_OFFSET)
#	define ARG2_OFF		(16 + IA64_SIGFRAME_ARG2_OFFSET)
#	define RBS_BASE_OFF	(16 + IA64_SIGFRAME_RBS_BASE_OFFSET)
#	define SIGHANDLER_OFF	(16 + IA64_SIGFRAME_HANDLER_OFFSET)
#	define SIGCONTEXT_OFF	(16 + IA64_SIGFRAME_SIGCONTEXT_OFFSET)

#	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 UNAT_OFF		IA64_SIGCONTEXT_AR_UNAT_OFFSET
#	define FPSR_OFF		IA64_SIGCONTEXT_AR_FPSR_OFFSET
#	define PR_OFF		IA64_SIGCONTEXT_PR_OFFSET
#	define RP_OFF		IA64_SIGCONTEXT_B0_OFFSET
#	define SP_OFF		IA64_SIGCONTEXT_R12_OFFSET
#	define base0		r2
#	define base1		r3
	/*
	 * When we get here, the memory stack looks like this:
	 *
	 *   +===============================+
       	 *   |				     |
       	 *   //	    struct sigframe          //
       	 *   |				     |
	 *   +-------------------------------+ <-- sp+16
	 *   |      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 (including sp, in which case the
	 * process ends up dying with a SIGSEGV).
	 *
	 * The first thing 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.
	 */

GLOBAL_ENTRY(ia64_sigtramp)
	// describe the state that is active when we get here:
	.prologue
	.unwabi @svr4, 's'		// mark this as a sigtramp handler (saves scratch regs)
	.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF
	.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF
	.savesp pr, PR_OFF+SIGCONTEXT_OFF
	.savesp rp, RP_OFF+SIGCONTEXT_OFF
	.vframesp SP_OFF+SIGCONTEXT_OFF
	.body

	.prologue
	adds base0=SIGHANDLER_OFF,sp
	adds base1=RBS_BASE_OFF,sp
	br.call.sptk.many rp=1f
1:
	ld8 r17=[base0],(ARG0_OFF-SIGHANDLER_OFF)	// get pointer to signal handler's plabel
	ld8 r15=[base1],(ARG1_OFF-RBS_BASE_OFF)		// get address of new RBS base (or NULL)
	cover				// push args in interrupted frame onto backing store
	;;
	.save ar.pfs, r8
	alloc r8=ar.pfs,0,0,3,0		// get CFM0, EC0, and CPL0 into r8
	ld8 out0=[base0],16		// load arg0 (signum)
	;;
	ld8 out1=[base1]		// load arg1 (siginfop)
	ld8 r10=[r17],8			// get signal handler entry point
	;;
	ld8 out2=[base0]		// load arg2 (sigcontextp)
	ld8 gp=[r17]			// get signal handler's global pointer
	cmp.ne p8,p0=r15,r0		// do we need to switch the rbs?

	mov.m r17=ar.bsp		// fetch ar.bsp
	.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
(p8)	br.cond.spnt.few setup_rbs	// yup -> (clobbers r14 and r16)
back_from_setup_rbs:
	adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
	;;
	.spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
	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
	;;
	.spillsp ar.pfs, CFM_OFF
	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
	mov b6=r10
	;;
	stf.spill [base0]=f10,32
	stf.spill [base1]=f11,32
	;;
	stf.spill [base0]=f12,32
	stf.spill [base1]=f13,32
	;;
	stf.spill [base0]=f14,32
	stf.spill [base1]=f15,32
	br.call.sptk.few rp=b6			// call the signal handler
.ret0:	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

setup_rbs:
	flushrs					// must be first in insn
	mov ar.rsc=0				// 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
	;;
	.spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
	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

restore_rbs:
	flushrs
	mov ar.rsc=0				// 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
END(ia64_sigtramp)