Linux Audio

Check our new training course

Linux kernel drivers training

May 6-19, 2025
Register
Loading...
v5.4
  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				// seralize 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				// seralize 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				// seralize 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)
v6.2
  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)