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