1 /* SPDX-License-Identifier: GPL-2.0 */
4 * IA-64 Processor Programmers Reference Vol 2
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>
12 * 05/22/2000 eranian Added support for stacked register calls
13 * 05/24/2000 eranian Added support for physical mode static calls
16 #include <asm/asmmacro.h>
17 #include <asm/processor.h>
18 #include <asm/export.h>
22 data8 ia64_pal_default_handler
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
30 * in0 Address of the PAL entry point (text address, NOT a function
33 GLOBAL_ENTRY(ia64_pal_handler_init)
34 alloc r3=ar.pfs,1,0,0,0
35 movl r2=pal_entry_point
39 END(ia64_pal_handler_init)
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").
46 GLOBAL_ENTRY(ia64_pal_default_handler)
49 END(ia64_pal_default_handler)
52 * Make a PAL call using the static calling convention.
54 * in0 Index of PAL service
55 * in1 - in3 Remaining PAL arguments
57 GLOBAL_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
67 ld8 loc2 = [loc2] // loc2 <- entry point
69 mov loc4=ar.rsc // save RSE configuration
71 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
85 mov ar.rsc = loc4 // restore RSE configuration
89 srlz.d // seralize restoration of psr.l
91 END(ia64_pal_call_static)
92 EXPORT_SYMBOL(ia64_pal_call_static)
95 * Make a PAL call using the stacked registers calling convention.
98 * in0 Index of PAL service
99 * in2 - in3 Remaining PAL arguments
101 GLOBAL_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
106 mov r28 = in0 // Index MUST be copied to r28
107 mov out0 = in0 // AND in0 of PAL function
111 ld8 loc2 = [loc2] // loc2 <- entry point
120 br.call.sptk.many rp=b7 // now make the call
121 .ret0: mov psr.l = loc3
125 srlz.d // serialize restoration of psr.l
127 END(ia64_pal_call_stacked)
128 EXPORT_SYMBOL(ia64_pal_call_stacked)
131 * Make a physical mode PAL call using the static registers calling convention.
134 * in0 Index of PAL service
135 * in2 - in3 Remaining PAL arguments
137 * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
138 * So we don't need to clear them.
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)
145 #define PAL_PSR_BITS_TO_SET \
149 GLOBAL_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
154 mov r28 = in0 // copy procedure index
155 mov r8 = ip // save ip to compute branch
156 mov loc0 = rp // save rp
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
165 mov loc3 = psr // save psr
166 adds r8 = 1f-1b,r8 // calculate return address for call
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
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
177 or loc3=loc3,r17 // add in psr the bits to set
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)
186 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
187 mov r16=loc3 // r16= original psr
190 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
191 mov psr.l = loc3 // restore init PSR
196 mov ar.rsc=loc4 // restore RSE configuration
197 srlz.d // seralize restoration of psr.l
199 END(ia64_pal_call_phys_static)
200 EXPORT_SYMBOL(ia64_pal_call_phys_static)
203 * Make a PAL call using the stacked registers in physical mode.
206 * in0 Index of PAL service
207 * in2 - in3 Remaining PAL arguments
209 GLOBAL_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
214 mov r28 = in0 // copy procedure index
215 mov loc0 = rp // save rp
219 ld8 loc2 = [loc2] // loc2 <- entry point
220 mov loc3 = psr // save psr
222 mov loc4=ar.rsc // save RSE configuration
223 dep.z loc2=loc2,0,61 // convert pal entry point to physical
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
229 or loc3=loc3,r17 // add in psr the bits to set
230 mov b7 = loc2 // install target to branch reg
232 andcm r16=loc3,r16 // removes bits to clear from psr
233 br.call.sptk.many rp=ia64_switch_mode_phys
235 mov out0 = in0 // first argument
236 mov out1 = in1 // copy arg2
237 mov out2 = in2 // copy arg3
238 mov out3 = in3 // copy arg3
242 br.call.sptk.many rp=b7 // now make the call
244 mov ar.rsc=0 // put RSE in enforced lazy, LE mode
245 mov r16=loc3 // r16= original psr
248 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
250 mov psr.l = loc3 // restore init PSR
254 mov ar.rsc=loc4 // restore RSE configuration
255 srlz.d // seralize restoration of psr.l
257 END(ia64_pal_call_phys_stacked)
258 EXPORT_SYMBOL(ia64_pal_call_phys_stacked)
261 * Save scratch fp scratch regs which aren't saved in pt_regs already
264 * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
265 * scratch regs fp-low partition.
268 * in0 Address of stack storage for fp regs
270 GLOBAL_ENTRY(ia64_save_scratch_fpregs)
271 alloc r3=ar.pfs,1,0,0,0
274 stf.spill [in0] = f10,32
275 stf.spill [r2] = f11,32
277 stf.spill [in0] = f12,32
278 stf.spill [r2] = f13,32
280 stf.spill [in0] = f14,32
281 stf.spill [r2] = f15,32
283 END(ia64_save_scratch_fpregs)
284 EXPORT_SYMBOL(ia64_save_scratch_fpregs)
287 * Load scratch fp scratch regs (fp10-fp15)
290 * in0 Address of stack storage for fp regs
292 GLOBAL_ENTRY(ia64_load_scratch_fpregs)
293 alloc r3=ar.pfs,1,0,0,0
296 ldf.fill f10 = [in0],32
297 ldf.fill f11 = [r2],32
299 ldf.fill f12 = [in0],32
300 ldf.fill f13 = [r2],32
302 ldf.fill f14 = [in0],32
303 ldf.fill f15 = [r2],32
305 END(ia64_load_scratch_fpregs)
306 EXPORT_SYMBOL(ia64_load_scratch_fpregs)