Linux Audio

Check our new training course

Embedded Linux training

Mar 31-Apr 8, 2025
Register
Loading...
  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#include <asm/export.h>
 18
 19	.data
 20pal_entry_point:
 21	data8 ia64_pal_default_handler
 22	.text
 23
 24/*
 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
 27 * not a big deal).
 28 *
 29 * in0		Address of the PAL entry point (text address, NOT a function
 30 *		descriptor).
 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/*
 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").
 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
 55 */
 56GLOBAL_ENTRY(ia64_pal_call_static)
 57	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
 58	alloc loc1 = ar.pfs,4,5,0,0
 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
 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
 76	mov r31 = in3
 77	mov b7 = loc2
 78
 79	rsm psr.i
 80	;;
 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)
 91EXPORT_SYMBOL(ia64_pal_call_static)
 92
 93/*
 94 * Make a PAL call using the stacked registers calling convention.
 95 *
 96 * Inputs:
 97 *	in0         Index of PAL service
 98 *	in2 - in3   Remaining PAL arguments
 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)
127EXPORT_SYMBOL(ia64_pal_call_stacked)
128
129/*
130 * Make a physical mode PAL call using the static registers calling convention.
131 *
132 * Inputs:
133 *	in0         Index of PAL service
134 *	in2 - in3   Remaining PAL arguments
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 */
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 |	      \
142	 IA64_PSR_DFL | IA64_PSR_DFH)
143
144#define PAL_PSR_BITS_TO_SET						      \
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
180	mov rp = r8			// install return address (physical)
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
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)
199EXPORT_SYMBOL(ia64_pal_call_phys_static)
200
201/*
202 * Make a PAL call using the stacked registers in physical mode.
203 *
204 * Inputs:
205 *	in0         Index of PAL service
206 *	in2 - in3   Remaining PAL arguments
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
214	  mov loc0 = rp			// save rp
215	}
216	.body
217	;;
218	ld8 loc2 = [loc2]		// loc2 <- entry point
219	mov loc3 = psr			// save psr
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
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
238	mov loc5 = r19
239	mov loc6 = r20
240
241	br.call.sptk.many rp=b7		// now make the call
242
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
247	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
248
249	mov psr.l  = loc3		// restore init PSR
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)
257EXPORT_SYMBOL(ia64_pal_call_phys_stacked)
258
259/*
260 * Save scratch fp scratch regs which aren't saved in pt_regs already
261 * (fp10-fp15).
262 *
263 * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
264 * scratch regs fp-low partition.
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)
283EXPORT_SYMBOL(ia64_save_scratch_fpregs)
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)
305EXPORT_SYMBOL(ia64_load_scratch_fpregs)