Merge remote-tracking branch 'battery/for-next'
[deliverable/linux.git] / arch / ia64 / kernel / pal.S
CommitLineData
1da177e4
LT
1/*
2 * PAL Firmware support
3 * IA-64 Processor Programmers Reference Vol 2
4 *
5 * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
6 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
7 * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co
8 * David Mosberger <davidm@hpl.hp.com>
9 * Stephane Eranian <eranian@hpl.hp.com>
10 *
11 * 05/22/2000 eranian Added support for stacked register calls
12 * 05/24/2000 eranian Added support for physical mode static calls
13 */
14
15#include <asm/asmmacro.h>
16#include <asm/processor.h>
e007c533 17#include <asm/export.h>
1da177e4
LT
18
19 .data
20pal_entry_point:
21 data8 ia64_pal_default_handler
22 .text
23
24/*
4d5a3197
BH
25 * Set the PAL entry point address. This could be written in C code, but we
26 * do it here to keep it all in one module (besides, it's so trivial that it's
1da177e4
LT
27 * not a big deal).
28 *
4d5a3197
BH
29 * in0 Address of the PAL entry point (text address, NOT a function
30 * descriptor).
1da177e4
LT
31 */
32GLOBAL_ENTRY(ia64_pal_handler_init)
33 alloc r3=ar.pfs,1,0,0,0
34 movl r2=pal_entry_point
35 ;;
36 st8 [r2]=in0
37 br.ret.sptk.many rp
38END(ia64_pal_handler_init)
39
40/*
4d5a3197
BH
41 * Default PAL call handler. This needs to be coded in assembly because it
42 * uses the static calling convention, i.e., the RSE may not be used and
43 * calls are done via "br.cond" (not "br.call").
1da177e4
LT
44 */
45GLOBAL_ENTRY(ia64_pal_default_handler)
46 mov r8=-1
47 br.cond.sptk.many rp
48END(ia64_pal_default_handler)
49
50/*
51 * Make a PAL call using the static calling convention.
52 *
53 * in0 Index of PAL service
54 * in1 - in3 Remaining PAL arguments
1da177e4
LT
55 */
56GLOBAL_ENTRY(ia64_pal_call_static)
c12fb188
BH
57 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
58 alloc loc1 = ar.pfs,4,5,0,0
1da177e4
LT
59 movl loc2 = pal_entry_point
601: {
61 mov r28 = in0
62 mov r29 = in1
63 mov r8 = ip
64 }
65 ;;
66 ld8 loc2 = [loc2] // loc2 <- entry point
1da177e4
LT
67 adds r8 = 1f-1b,r8
68 mov loc4=ar.rsc // save RSE configuration
69 ;;
70 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
71 mov loc3 = psr
72 mov loc0 = rp
73 .body
74 mov r30 = in2
75
1da177e4
LT
76 mov r31 = in3
77 mov b7 = loc2
78
c12fb188 79 rsm psr.i
1da177e4 80 ;;
1da177e4
LT
81 mov rp = r8
82 br.cond.sptk.many b7
831: mov psr.l = loc3
84 mov ar.rsc = loc4 // restore RSE configuration
85 mov ar.pfs = loc1
86 mov rp = loc0
87 ;;
88 srlz.d // seralize restoration of psr.l
89 br.ret.sptk.many b0
90END(ia64_pal_call_static)
e007c533 91EXPORT_SYMBOL(ia64_pal_call_static)
1da177e4
LT
92
93/*
94 * Make a PAL call using the stacked registers calling convention.
95 *
96 * Inputs:
4d5a3197
BH
97 * in0 Index of PAL service
98 * in2 - in3 Remaining PAL arguments
1da177e4
LT
99 */
100GLOBAL_ENTRY(ia64_pal_call_stacked)
101 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
102 alloc loc1 = ar.pfs,4,4,4,0
103 movl loc2 = pal_entry_point
104
105 mov r28 = in0 // Index MUST be copied to r28
106 mov out0 = in0 // AND in0 of PAL function
107 mov loc0 = rp
108 .body
109 ;;
110 ld8 loc2 = [loc2] // loc2 <- entry point
111 mov out1 = in1
112 mov out2 = in2
113 mov out3 = in3
114 mov loc3 = psr
115 ;;
116 rsm psr.i
117 mov b7 = loc2
118 ;;
119 br.call.sptk.many rp=b7 // now make the call
120.ret0: mov psr.l = loc3
121 mov ar.pfs = loc1
122 mov rp = loc0
123 ;;
124 srlz.d // serialize restoration of psr.l
125 br.ret.sptk.many b0
126END(ia64_pal_call_stacked)
e007c533 127EXPORT_SYMBOL(ia64_pal_call_stacked)
1da177e4
LT
128
129/*
130 * Make a physical mode PAL call using the static registers calling convention.
131 *
132 * Inputs:
4d5a3197
BH
133 * in0 Index of PAL service
134 * in2 - in3 Remaining PAL arguments
1da177e4
LT
135 *
136 * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
137 * So we don't need to clear them.
138 */
4d5a3197
BH
139#define PAL_PSR_BITS_TO_CLEAR \
140 (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | IA64_PSR_RT |\
141 IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \
1da177e4
LT
142 IA64_PSR_DFL | IA64_PSR_DFH)
143
4d5a3197 144#define PAL_PSR_BITS_TO_SET \
1da177e4
LT
145 (IA64_PSR_BN)
146
147
148GLOBAL_ENTRY(ia64_pal_call_phys_static)
149 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
150 alloc loc1 = ar.pfs,4,7,0,0
151 movl loc2 = pal_entry_point
1521: {
153 mov r28 = in0 // copy procedure index
154 mov r8 = ip // save ip to compute branch
155 mov loc0 = rp // save rp
156 }
157 .body
158 ;;
159 ld8 loc2 = [loc2] // loc2 <- entry point
160 mov r29 = in1 // first argument
161 mov r30 = in2 // copy arg2
162 mov r31 = in3 // copy arg3
163 ;;
164 mov loc3 = psr // save psr
165 adds r8 = 1f-1b,r8 // calculate return address for call
166 ;;
167 mov loc4=ar.rsc // save RSE configuration
168 dep.z loc2=loc2,0,61 // convert pal entry point to physical
169 tpa r8=r8 // convert rp to physical
170 ;;
171 mov b7 = loc2 // install target to branch reg
172 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
173 movl r16=PAL_PSR_BITS_TO_CLEAR
174 movl r17=PAL_PSR_BITS_TO_SET
175 ;;
176 or loc3=loc3,r17 // add in psr the bits to set
177 ;;
178 andcm r16=loc3,r16 // removes bits to clear from psr
179 br.call.sptk.many rp=ia64_switch_mode_phys
4d5a3197 180 mov rp = r8 // install return address (physical)
1da177e4
LT
181 mov loc5 = r19
182 mov loc6 = r20
183 br.cond.sptk.many b7
1841:
185 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
186 mov r16=loc3 // r16= original psr
187 mov r19=loc5
188 mov r20=loc6
189 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
1da177e4
LT
190 mov psr.l = loc3 // restore init PSR
191
192 mov ar.pfs = loc1
193 mov rp = loc0
194 ;;
195 mov ar.rsc=loc4 // restore RSE configuration
196 srlz.d // seralize restoration of psr.l
197 br.ret.sptk.many b0
198END(ia64_pal_call_phys_static)
e007c533 199EXPORT_SYMBOL(ia64_pal_call_phys_static)
1da177e4
LT
200
201/*
202 * Make a PAL call using the stacked registers in physical mode.
203 *
204 * Inputs:
4d5a3197
BH
205 * in0 Index of PAL service
206 * in2 - in3 Remaining PAL arguments
1da177e4
LT
207 */
208GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
209 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
210 alloc loc1 = ar.pfs,5,7,4,0
211 movl loc2 = pal_entry_point
2121: {
213 mov r28 = in0 // copy procedure index
4d5a3197 214 mov loc0 = rp // save rp
1da177e4
LT
215 }
216 .body
217 ;;
218 ld8 loc2 = [loc2] // loc2 <- entry point
acb15c85 219 mov loc3 = psr // save psr
1da177e4
LT
220 ;;
221 mov loc4=ar.rsc // save RSE configuration
222 dep.z loc2=loc2,0,61 // convert pal entry point to physical
223 ;;
224 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
225 movl r16=PAL_PSR_BITS_TO_CLEAR
226 movl r17=PAL_PSR_BITS_TO_SET
227 ;;
228 or loc3=loc3,r17 // add in psr the bits to set
229 mov b7 = loc2 // install target to branch reg
230 ;;
231 andcm r16=loc3,r16 // removes bits to clear from psr
232 br.call.sptk.many rp=ia64_switch_mode_phys
acb15c85
ZN
233
234 mov out0 = in0 // first argument
235 mov out1 = in1 // copy arg2
236 mov out2 = in2 // copy arg3
237 mov out3 = in3 // copy arg3
1da177e4
LT
238 mov loc5 = r19
239 mov loc6 = r20
acb15c85 240
1da177e4 241 br.call.sptk.many rp=b7 // now make the call
acb15c85 242
1da177e4
LT
243 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
244 mov r16=loc3 // r16= original psr
245 mov r19=loc5
246 mov r20=loc6
4d5a3197 247 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
1da177e4 248
acb15c85 249 mov psr.l = loc3 // restore init PSR
1da177e4
LT
250 mov ar.pfs = loc1
251 mov rp = loc0
252 ;;
253 mov ar.rsc=loc4 // restore RSE configuration
254 srlz.d // seralize restoration of psr.l
255 br.ret.sptk.many b0
256END(ia64_pal_call_phys_stacked)
e007c533 257EXPORT_SYMBOL(ia64_pal_call_phys_stacked)
1da177e4
LT
258
259/*
4d5a3197
BH
260 * Save scratch fp scratch regs which aren't saved in pt_regs already
261 * (fp10-fp15).
1da177e4 262 *
4d5a3197
BH
263 * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
264 * scratch regs fp-low partition.
1da177e4
LT
265 *
266 * Inputs:
267 * in0 Address of stack storage for fp regs
268 */
269GLOBAL_ENTRY(ia64_save_scratch_fpregs)
270 alloc r3=ar.pfs,1,0,0,0
271 add r2=16,in0
272 ;;
273 stf.spill [in0] = f10,32
274 stf.spill [r2] = f11,32
275 ;;
276 stf.spill [in0] = f12,32
277 stf.spill [r2] = f13,32
278 ;;
279 stf.spill [in0] = f14,32
280 stf.spill [r2] = f15,32
281 br.ret.sptk.many rp
282END(ia64_save_scratch_fpregs)
e007c533 283EXPORT_SYMBOL(ia64_save_scratch_fpregs)
1da177e4
LT
284
285/*
286 * Load scratch fp scratch regs (fp10-fp15)
287 *
288 * Inputs:
289 * in0 Address of stack storage for fp regs
290 */
291GLOBAL_ENTRY(ia64_load_scratch_fpregs)
292 alloc r3=ar.pfs,1,0,0,0
293 add r2=16,in0
294 ;;
295 ldf.fill f10 = [in0],32
296 ldf.fill f11 = [r2],32
297 ;;
298 ldf.fill f12 = [in0],32
299 ldf.fill f13 = [r2],32
300 ;;
301 ldf.fill f14 = [in0],32
302 ldf.fill f15 = [r2],32
303 br.ret.sptk.many rp
304END(ia64_load_scratch_fpregs)
e007c533 305EXPORT_SYMBOL(ia64_load_scratch_fpregs)
This page took 1.322961 seconds and 5 git commands to generate.