Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/ia64/kernel/pal.S
10817 views
1
/*
2
* PAL Firmware support
3
* IA-64 Processor Programmers Reference Vol 2
4
*
5
* Copyright (C) 1999 Don Dugger <[email protected]>
6
* Copyright (C) 1999 Walt Drummond <[email protected]>
7
* Copyright (C) 1999-2001, 2003 Hewlett-Packard Co
8
* David Mosberger <[email protected]>
9
* Stephane Eranian <[email protected]>
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
19
pal_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
*/
31
GLOBAL_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
37
END(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
*/
44
GLOBAL_ENTRY(ia64_pal_default_handler)
45
mov r8=-1
46
br.cond.sptk.many rp
47
END(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
*/
55
GLOBAL_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
59
1: {
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
82
1: 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
89
END(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
*/
98
GLOBAL_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
124
END(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
145
GLOBAL_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
149
1: {
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
181
1:
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
195
END(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
*/
204
GLOBAL_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
208
1: {
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
252
END(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
*/
264
GLOBAL_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
277
END(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
*/
285
GLOBAL_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
298
END(ia64_load_scratch_fpregs)
299
300