1 | /* |
---|
2 | * Copyright (c) 2007 Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> |
---|
3 | * Description: ia64 specific trap handling. |
---|
4 | * |
---|
5 | **************************************************************************** |
---|
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
7 | * of this software and associated documentation files (the "Software"), to |
---|
8 | * deal in the Software without restriction, including without limitation the |
---|
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
---|
10 | * sell copies of the Software, and to permit persons to whom the Software is |
---|
11 | * furnished to do so, subject to the following conditions: |
---|
12 | * |
---|
13 | * The above copyright notice and this permission notice shall be included in |
---|
14 | * all copies or substantial portions of the Software. |
---|
15 | * |
---|
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
---|
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
---|
22 | * DEALINGS IN THE SOFTWARE. |
---|
23 | * |
---|
24 | */ |
---|
25 | |
---|
26 | |
---|
27 | #include "asm.h" |
---|
28 | #include "page.h" |
---|
29 | #include "ia64_cpu.h" |
---|
30 | #include "privop.h" |
---|
31 | #include "offsets.h" |
---|
32 | |
---|
33 | |
---|
34 | /* General register usage in interrupt handling: |
---|
35 | * r16, r17, ... are used for input parameters of sub-routines |
---|
36 | * r29: used to access memory which may raise nested TLB fault |
---|
37 | * r30: b0 save register |
---|
38 | * r31: predicates save register |
---|
39 | * p30,p31: used for TLB stuff: (0,1)=data, (1,0)=instruction |
---|
40 | */ |
---|
41 | |
---|
42 | |
---|
43 | #define FILL_FP_PAIR(f1, f2, b1, b2) \ |
---|
44 | ldf.fill f1=[b1],32 ;\ |
---|
45 | ldf.fill f2=[b2],32 ;\ |
---|
46 | ;; |
---|
47 | |
---|
48 | #define SPILL_FP_PAIR(f1, f2, b1, b2) \ |
---|
49 | stf.spill [b1]=f1,32 ;\ |
---|
50 | stf.spill [b2]=f2,32 ;\ |
---|
51 | ;; |
---|
52 | |
---|
53 | #define FILL_REG_PAIR(r1, r2, b1, b2) \ |
---|
54 | ld8.fill r1=[b1],16 ;\ |
---|
55 | ld8.fill r2=[b2],16 ;\ |
---|
56 | ;; |
---|
57 | |
---|
58 | #define SPILL_REG_PAIR(r1, r2, b1, b2) \ |
---|
59 | .mem.offset 0,0 ;\ |
---|
60 | st8.spill [b1]=r1,16 ;\ |
---|
61 | .mem.offset 8,0 ;\ |
---|
62 | st8.spill [b2]=r2,16 ;\ |
---|
63 | ;; |
---|
64 | |
---|
65 | |
---|
66 | /** |
---|
67 | * The function does a store of the current processor context |
---|
68 | * to the given exception frame address. |
---|
69 | * These are some special and the scratch registers for calling |
---|
70 | * C-functions later. |
---|
71 | * The bspstore will be the same. A clean RSE is made with the |
---|
72 | * cover instruction. |
---|
73 | * |
---|
74 | * The return is done through a jump to the next bundle after ip (r16). |
---|
75 | * |
---|
76 | * Used register: r16, r18, r19, r20, r21, r22 of bank 0 |
---|
77 | * |
---|
78 | * @param: r16 ip of the bundle with the jump. |
---|
79 | * @param: r18 pointer to the trap frame. |
---|
80 | * @param: r23 trap number/err val |
---|
81 | * |
---|
82 | */ |
---|
83 | |
---|
84 | ENTRY(save_tf_rse_switch) |
---|
85 | movl r21=XSI_IPSR // XEN !! |
---|
86 | movl r22=XSI_IIP // XEN !! |
---|
87 | ;; |
---|
88 | ld8 r21=[r21] // XEN.ipsr |
---|
89 | ld8 r22=[r22];; // XEN.iip |
---|
90 | #if defined(BIG_ENDIAN) |
---|
91 | mux1 r21=r21,@rev // swap because mini-os is in BE |
---|
92 | mux1 r22=r22,@rev // swap because mini-os is in BE |
---|
93 | ;; |
---|
94 | #endif |
---|
95 | add r19=TF_IPSR,r18 |
---|
96 | add r20=TF_IIP,r18 |
---|
97 | ;; |
---|
98 | st8 [r19]=r21 // store cr.ipsr |
---|
99 | st8 [r20]=r22 // store cr.iip |
---|
100 | ;; |
---|
101 | //// r16 return jump pointer, r18 - trap frame base, |
---|
102 | add r19=TF_UNAT,r18 |
---|
103 | mov r20=ar.unat |
---|
104 | ;; |
---|
105 | st8 [r19]=r20 // store scratch unat |
---|
106 | ;; |
---|
107 | |
---|
108 | add r19=TF_GP,r18 |
---|
109 | add r20=TF_SP,r18 |
---|
110 | ;; |
---|
111 | st8 [r19]=gp,TF_TP-TF_GP // store gp |
---|
112 | st8 [r20]=sp,TF_PR-TF_SP // store sp |
---|
113 | mov r21=pr |
---|
114 | ;; |
---|
115 | st8 [r19]=r13 // store tp |
---|
116 | st8 [r20]=r21 // store pr |
---|
117 | ;; |
---|
118 | add r19=TF_GREG2,r18 // Now first general regs. |
---|
119 | add r20=TF_GREG3,r18 |
---|
120 | ;; |
---|
121 | SPILL_REG_PAIR( r2, r3,r19,r20) |
---|
122 | SPILL_REG_PAIR( r8, r9,r19,r20) |
---|
123 | SPILL_REG_PAIR(r10,r11,r19,r20) |
---|
124 | SPILL_REG_PAIR(r14,r15,r19,r20) |
---|
125 | ;; |
---|
126 | mov r14=r18 // move trap frame base for bsw |
---|
127 | mov r15=r16 // save return address |
---|
128 | ;; |
---|
129 | //bsw.1 // switch to bank 1 for saving these registers. |
---|
130 | movl r30=XSI_BANKNUM // Switch to bank 1. |
---|
131 | mov r31=1;; |
---|
132 | #if defined(BIG_ENDIAN) |
---|
133 | mux1 r31=r31,@rev // swap because mini-os is in BE |
---|
134 | ;; |
---|
135 | #endif |
---|
136 | st4 [r30]=r31 |
---|
137 | ;; |
---|
138 | /* |
---|
139 | * On XEN the hypervisor has stored the bank 1 registers |
---|
140 | * r16-r31. I must reload these registers here to get |
---|
141 | * access. |
---|
142 | */ |
---|
143 | movl r30=XSI_BANK1_R16; |
---|
144 | movl r31=XSI_BANK1_R16+8;; |
---|
145 | ld8 r16=[r30],16; ld8 r17=[r31],16;; |
---|
146 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
147 | mux1 r16=r16,@rev; mux1 r17=r17,@rev;; |
---|
148 | #endif |
---|
149 | ld8 r18=[r30],16; ld8 r19=[r31],16;; |
---|
150 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
151 | mux1 r18=r18,@rev; mux1 r19=r19,@rev;; |
---|
152 | #endif |
---|
153 | ld8 r20=[r30],16; ld8 r21=[r31],16;; |
---|
154 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
155 | mux1 r20=r20,@rev; mux1 r21=r21,@rev;; |
---|
156 | #endif |
---|
157 | ld8 r22=[r30],16; ld8 r23=[r31],16;; |
---|
158 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
159 | mux1 r22=r22,@rev; mux1 r23=r23,@rev;; |
---|
160 | #endif |
---|
161 | ld8 r24=[r30],16; ld8 r25=[r31],16;; |
---|
162 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
163 | mux1 r24=r24,@rev; mux1 r25=r25,@rev;; |
---|
164 | #endif |
---|
165 | ld8 r26=[r30],16; ld8 r27=[r31],16;; |
---|
166 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
167 | mux1 r26=r26,@rev; mux1 r27=r27,@rev;; |
---|
168 | #endif |
---|
169 | ld8 r28=[r30],16; ld8 r29=[r31],16;; |
---|
170 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
171 | mux1 r28=r28,@rev; mux1 r29=r29,@rev;; |
---|
172 | #endif |
---|
173 | ld8 r30=[r30]; ld8 r31=[r31];; |
---|
174 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
175 | mux1 r30=r30,@rev; mux1 r31=r31,@rev;; |
---|
176 | #endif |
---|
177 | |
---|
178 | add r2=TF_GREG16,r14 |
---|
179 | add r3=TF_GREG17,r14 |
---|
180 | ;; |
---|
181 | SPILL_REG_PAIR(r16,r17,r2,r3) |
---|
182 | SPILL_REG_PAIR(r18,r19,r2,r3) |
---|
183 | SPILL_REG_PAIR(r20,r21,r2,r3) |
---|
184 | SPILL_REG_PAIR(r22,r23,r2,r3) |
---|
185 | SPILL_REG_PAIR(r24,r25,r2,r3) |
---|
186 | SPILL_REG_PAIR(r26,r27,r2,r3) |
---|
187 | SPILL_REG_PAIR(r28,r29,r2,r3) |
---|
188 | SPILL_REG_PAIR(r30,r31,r2,r3) |
---|
189 | ;; |
---|
190 | //bsw.0 // back to interrupt bank 0 |
---|
191 | movl r2=XSI_BANKNUM;; |
---|
192 | st4 [r2]=r0 |
---|
193 | ;; |
---|
194 | mov r18=r14 // restore context pointer |
---|
195 | mov r16=r15 // restore return address |
---|
196 | ;; |
---|
197 | //// r16 return jump pointer, r18 - trap frame base, |
---|
198 | add r19=TF_CCV,r18 |
---|
199 | add r20=TF_CSD,r18 |
---|
200 | mov r21=ar.ccv |
---|
201 | mov r22=ar.csd |
---|
202 | ;; |
---|
203 | st8 [r19]=r21 // ar.ccv |
---|
204 | st8 [r20]=r22 // ar.csd |
---|
205 | ;; |
---|
206 | add r19=TF_SSD,r18 |
---|
207 | mov r21=ar.ssd |
---|
208 | ;; |
---|
209 | st8 [r19]=r21 // ar.ssd |
---|
210 | ;; |
---|
211 | add r19=TF_FREG6,r18 |
---|
212 | add r20=TF_FREG7,r18 |
---|
213 | ;; |
---|
214 | SPILL_FP_PAIR(f6, f7, r19, r20) |
---|
215 | SPILL_FP_PAIR(f8, f9, r19, r20) |
---|
216 | SPILL_FP_PAIR(f10, f11, r19, r20) |
---|
217 | |
---|
218 | add r19=TF_BREG0,r18 // b0, b6, b7 |
---|
219 | add r20=TF_BREG6,r18 |
---|
220 | mov r21=b0 |
---|
221 | mov r22=b6 |
---|
222 | ;; |
---|
223 | st8 [r19]=r21,TF_BREG7-TF_BREG0 // store b0 |
---|
224 | st8 [r20]=r22,16 // store b6 |
---|
225 | ;; |
---|
226 | mov r21=b7 |
---|
227 | ;; |
---|
228 | st8 [r19]=r21 // store b7 |
---|
229 | |
---|
230 | //// r16 return jump pointer, r18 - trap frame base, |
---|
231 | |
---|
232 | // Read and save RSC, PFS |
---|
233 | add r19=TF_PFS,r18 |
---|
234 | add r20=TF_RSC,r18 |
---|
235 | mov r21=ar.pfs |
---|
236 | mov r22=ar.rsc |
---|
237 | ;; |
---|
238 | { .mmb |
---|
239 | st8 [r19]=r21 // store ar.pfs |
---|
240 | st8 [r20]=r22 // store ar.rsc |
---|
241 | // Issue cover instruction |
---|
242 | cover // must be the last instruction in bundle |
---|
243 | //XEN_HYPER_COVER |
---|
244 | ;; |
---|
245 | } |
---|
246 | // Read and save IFS |
---|
247 | add r19=TF_IFS,r18 |
---|
248 | add r20=TF_CFM,r18 |
---|
249 | /* xen special handling for possibly lazy cover */ |
---|
250 | movl r8=XSI_PRECOVER_IFS; |
---|
251 | ;; |
---|
252 | ld8 r21=[r8]; |
---|
253 | ;; |
---|
254 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
255 | mux1 r21=r21,@rev |
---|
256 | ;; |
---|
257 | #endif |
---|
258 | st8 [r19]=r21 // store cr.ifs |
---|
259 | dep.z r22=r21,0,38 // copy ifm part from ifs.ifm |
---|
260 | ;; |
---|
261 | st8 [r20]=r22 // store cfm |
---|
262 | // RSE in enforced lazy mode |
---|
263 | mov ar.rsc=IA64_RSE_LAZY |
---|
264 | ;; |
---|
265 | // Read and save BSPSTORE and RNAT |
---|
266 | add r19=TF_BSP,r18 |
---|
267 | add r20=TF_RNAT,r18 |
---|
268 | mov r21=ar.bspstore |
---|
269 | mov r22=ar.rnat |
---|
270 | ;; |
---|
271 | st8 [r19]=r21 // store ar.bspstore |
---|
272 | st8 [r20]=r22 // store ar.rnat |
---|
273 | ;; |
---|
274 | // Write new BSPSTORE |
---|
275 | //mov r21=ar.bsp |
---|
276 | //;; |
---|
277 | mov r22=r21 // new bspstore equal to old |
---|
278 | ;; |
---|
279 | mov ar.bspstore=r22 // the new bspstore |
---|
280 | ;; |
---|
281 | // Read and save the new BSP for calculating number of dirty regs. |
---|
282 | mov r21=ar.bsp |
---|
283 | ;; |
---|
284 | sub r21=r21,r22 // r21 -> ndirty |
---|
285 | add r19=TF_NDIRTY-TF_BSP,r19 // TF_NDIRTY pos in r19 |
---|
286 | ;; |
---|
287 | st8 [r19]=r21 // store ndirty |
---|
288 | ;; |
---|
289 | mov ar.rsc=IA64_RSE_EAGER // RSE on again |
---|
290 | ;; |
---|
291 | add r19=TF_FPSR,r18 |
---|
292 | ;; |
---|
293 | mov r21=ar.fpsr |
---|
294 | ;; |
---|
295 | st8 [r19]=r21 // ar.fpsr |
---|
296 | ;; |
---|
297 | //// r16 return jump pointer, r18 - trap frame base, |
---|
298 | // Load the gp with our module __gp |
---|
299 | movl gp=__gp |
---|
300 | ;; |
---|
301 | add r16=16,r16 // for jump to next bundle |
---|
302 | ;; |
---|
303 | mov b7=r16 |
---|
304 | ;; |
---|
305 | |
---|
306 | { .mfb |
---|
307 | srlz.d |
---|
308 | nop 0 |
---|
309 | br.sptk b7 |
---|
310 | ;; |
---|
311 | } |
---|
312 | |
---|
313 | END(save_tf_rse_switch) |
---|
314 | |
---|
315 | |
---|
316 | /** |
---|
317 | * The function reloads the processor context stored in |
---|
318 | * save_tf_rse_switch(). |
---|
319 | * |
---|
320 | * On calling the function the bank 0 must be activ. |
---|
321 | * The return is done through a rfi. |
---|
322 | * Used register: b7, r16, r18, r19, r20, r21, r22 of bank 0 |
---|
323 | * |
---|
324 | * @param: r18 pointer to the exception frame |
---|
325 | * |
---|
326 | */ |
---|
327 | ENTRY(restore_tf_rse_switch) |
---|
328 | add r19=TF_IPSR,r18 |
---|
329 | add r20=TF_IIP,r18 |
---|
330 | ;; |
---|
331 | ld8 r21=[r19] // load cr.ipsr |
---|
332 | ld8 r22=[r20] // load cr.iip |
---|
333 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
334 | ;; |
---|
335 | mux1 r21=r21,@rev |
---|
336 | mux1 r22=r22,@rev |
---|
337 | ;; |
---|
338 | #endif |
---|
339 | movl r16=XSI_IPSR // XEN !! |
---|
340 | ;; |
---|
341 | st8 [r16]=r21,XSI_IIP_OFS-XSI_IPSR_OFS // XEN.ipsr |
---|
342 | mov r2=r21 // save for fp stuff below |
---|
343 | ;; |
---|
344 | st8 [r16]=r22 // XEN.iip |
---|
345 | ;; |
---|
346 | //// r18 - trap frame base |
---|
347 | // Allocate a zero sized frame |
---|
348 | alloc r30=ar.pfs,0,0,0,0 // discard current frame |
---|
349 | ;; |
---|
350 | // calc number of dirty regs and put this into rsc.loardrs |
---|
351 | add r19=TF_NDIRTY,r18 |
---|
352 | ;; |
---|
353 | ld8 r22=[r19] // ndirty |
---|
354 | ;; |
---|
355 | shl r21=r22,16 // value for ar.rsc |
---|
356 | //mov r19=(MOS_IA64_RSC_BE << IA64_RSC_BE) |
---|
357 | ;; |
---|
358 | or r21=(MOS_IA64_RSC_BE << IA64_RSC_BE),r21 |
---|
359 | ;; |
---|
360 | mov ar.rsc=r21 // setup for loadrs |
---|
361 | ;; |
---|
362 | // Issue a loadrs instruction |
---|
363 | { .mmi |
---|
364 | loadrs // must be the first instruction |
---|
365 | ;; |
---|
366 | nop 0x0 |
---|
367 | nop 0x0 |
---|
368 | } |
---|
369 | // Restore BSPSTORE from interrupted context |
---|
370 | add r19=TF_BSP,r18 |
---|
371 | add r20=TF_RNAT,r18 |
---|
372 | ;; |
---|
373 | ld8 r21=[r19] // load ar.bspstore |
---|
374 | ld8 r22=[r20] // load ar.rnat |
---|
375 | ;; |
---|
376 | mov ar.bspstore=r21 // set ar.bspstore |
---|
377 | ;; |
---|
378 | // Restore RNAT |
---|
379 | mov ar.rnat=r22 // set ar.rnat |
---|
380 | ;; |
---|
381 | // Restore PFS and IFS |
---|
382 | add r19=TF_PFS,r18 |
---|
383 | add r20=TF_IFS,r18 |
---|
384 | movl r16=XSI_IFS // XEN !! |
---|
385 | ;; |
---|
386 | ld8 r21=[r19] // load ar.pfs |
---|
387 | ld8 r22=[r20] // load cr.ifs |
---|
388 | ;; |
---|
389 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
390 | mux1 r22=r22,@rev |
---|
391 | ;; |
---|
392 | #endif |
---|
393 | add r19=TF_RSC,r18 |
---|
394 | mov ar.pfs=r21 |
---|
395 | st8 [r16]=r22 // XEN.ifs |
---|
396 | ;; |
---|
397 | // Restore RSC |
---|
398 | ld8 r21=[r19] // load ar.rsc |
---|
399 | ;; |
---|
400 | mov ar.rsc=r21 // set ar.rsc |
---|
401 | //// r18 - trap frame base |
---|
402 | add r19=TF_GP,r18 |
---|
403 | add r20=TF_SP,r18 |
---|
404 | ;; |
---|
405 | ld8 gp=[r19],TF_TP-TF_GP // load gp |
---|
406 | ld8 sp=[r20],TF_PR-TF_SP // load sp |
---|
407 | ;; |
---|
408 | ld8 r13=[r19] // load tp |
---|
409 | ld8 r21=[r20] // load pr |
---|
410 | ;; |
---|
411 | mov pr=r21,-1 // set pr |
---|
412 | ;; |
---|
413 | add r19=TF_BREG0,r18 |
---|
414 | add r20=TF_BREG6,r18 |
---|
415 | ;; |
---|
416 | ld8 r21=[r19],TF_BREG7-TF_BREG0 // load b0 |
---|
417 | ld8 r22=[r20],16 // load b6 |
---|
418 | ;; |
---|
419 | mov b0=r21 |
---|
420 | mov b6=r22 |
---|
421 | ;; |
---|
422 | ld8 r21=[r19] // load b7 |
---|
423 | ld8 r22=[r20],16 // load b3 |
---|
424 | ;; |
---|
425 | mov b7=r21 |
---|
426 | //// r18 - trap frame base |
---|
427 | mov r14=r18 // Save the context pointer |
---|
428 | ;; |
---|
429 | // bsw.1 |
---|
430 | movl r30=XSI_BANKNUM // Switch to bank 1. |
---|
431 | mov r31=1;; |
---|
432 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
433 | mux1 r31=r31,@rev |
---|
434 | ;; |
---|
435 | #endif |
---|
436 | st4 [r30]=r31 |
---|
437 | ;; |
---|
438 | add r2=TF_GREG16,r14 |
---|
439 | add r3=TF_GREG17,r14 |
---|
440 | ;; |
---|
441 | FILL_REG_PAIR(r16,r17,r2,r3) |
---|
442 | FILL_REG_PAIR(r18,r19,r2,r3) |
---|
443 | FILL_REG_PAIR(r20,r21,r2,r3) |
---|
444 | FILL_REG_PAIR(r22,r23,r2,r3) |
---|
445 | FILL_REG_PAIR(r24,r25,r2,r3) |
---|
446 | FILL_REG_PAIR(r26,r27,r2,r3) |
---|
447 | FILL_REG_PAIR(r28,r29,r2,r3) |
---|
448 | FILL_REG_PAIR(r30,r31,r2,r3) |
---|
449 | |
---|
450 | /* |
---|
451 | * On XEN I have to store the bank 1 register into the |
---|
452 | * global XSI_... area. |
---|
453 | */ |
---|
454 | // r16-r31 all now hold bank1 values |
---|
455 | movl r2=XSI_BANK1_R16 |
---|
456 | movl r3=XSI_BANK1_R16+8 |
---|
457 | ;; |
---|
458 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
459 | mux1 r16=r16,@rev; mux1 r17=r17,@rev;; |
---|
460 | #endif |
---|
461 | .mem.offset 0,0; st8.spill [r2]=r16,16 |
---|
462 | .mem.offset 8,0; st8.spill [r3]=r17,16 |
---|
463 | ;; |
---|
464 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
465 | mux1 r18=r18,@rev; mux1 r19=r19,@rev;; |
---|
466 | #endif |
---|
467 | .mem.offset 0,0; st8.spill [r2]=r18,16 |
---|
468 | .mem.offset 8,0; st8.spill [r3]=r19,16 |
---|
469 | ;; |
---|
470 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
471 | mux1 r20=r20,@rev; mux1 r21=r21,@rev;; |
---|
472 | #endif |
---|
473 | .mem.offset 0,0; st8.spill [r2]=r20,16 |
---|
474 | .mem.offset 8,0; st8.spill [r3]=r21,16 |
---|
475 | ;; |
---|
476 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
477 | mux1 r22=r22,@rev; mux1 r23=r23,@rev;; |
---|
478 | #endif |
---|
479 | .mem.offset 0,0; st8.spill [r2]=r22,16 |
---|
480 | .mem.offset 8,0; st8.spill [r3]=r23,16 |
---|
481 | ;; |
---|
482 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
483 | mux1 r24=r24,@rev; mux1 r25=r25,@rev;; |
---|
484 | #endif |
---|
485 | .mem.offset 0,0; st8.spill [r2]=r24,16 |
---|
486 | .mem.offset 8,0; st8.spill [r3]=r25,16 |
---|
487 | ;; |
---|
488 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
489 | mux1 r26=r26,@rev; mux1 r27=r27,@rev;; |
---|
490 | #endif |
---|
491 | .mem.offset 0,0; st8.spill [r2]=r26,16 |
---|
492 | .mem.offset 8,0; st8.spill [r3]=r27,16 |
---|
493 | ;; |
---|
494 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
495 | mux1 r28=r28,@rev; mux1 r29=r29,@rev;; |
---|
496 | #endif |
---|
497 | .mem.offset 0,0; st8.spill [r2]=r28,16 |
---|
498 | .mem.offset 8,0; st8.spill [r3]=r29,16 |
---|
499 | ;; |
---|
500 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
501 | mux1 r30=r30,@rev; mux1 r31=r31,@rev;; |
---|
502 | #endif |
---|
503 | .mem.offset 0,0; st8.spill [r2]=r30,16 |
---|
504 | .mem.offset 8,0; st8.spill [r3]=r31,16 |
---|
505 | ;; |
---|
506 | // bsw.0 |
---|
507 | movl r2=XSI_BANKNUM;; |
---|
508 | st4 [r2]=r0; |
---|
509 | |
---|
510 | mov r18=r14 // Move back the context pointer |
---|
511 | ;; |
---|
512 | add r19=TF_GREG2,r18 |
---|
513 | add r20=TF_GREG3,r18 |
---|
514 | ;; |
---|
515 | FILL_REG_PAIR( r2, r3,r19,r20) |
---|
516 | FILL_REG_PAIR( r8, r9,r19,r20) |
---|
517 | FILL_REG_PAIR(r10,r11,r19,r20) |
---|
518 | FILL_REG_PAIR(r14,r15,r19,r20) |
---|
519 | |
---|
520 | //// r18 - trap frame base, |
---|
521 | |
---|
522 | add r19=TF_CCV,r18 |
---|
523 | add r20=TF_CSD,r18 |
---|
524 | ;; |
---|
525 | ld8 r21=[r19] // ar.ccv |
---|
526 | ld8 r22=[r20] // ar.csd |
---|
527 | ;; |
---|
528 | mov ar.ccv=r21 |
---|
529 | mov ar.csd=r22 |
---|
530 | add r19=TF_SSD,r18 |
---|
531 | ;; |
---|
532 | ld8 r21=[r19] // ar.ssd |
---|
533 | ;; |
---|
534 | mov ar.ssd=r21 |
---|
535 | add r19=TF_FREG6,r18 |
---|
536 | add r20=TF_FREG7,r18 |
---|
537 | ;; |
---|
538 | FILL_FP_PAIR(f6, f7, r19, r20) |
---|
539 | FILL_FP_PAIR(f8, f9, r19, r20) |
---|
540 | FILL_FP_PAIR(f10, f11, r19, r20) |
---|
541 | add r19=TF_FPSR,r18 |
---|
542 | ;; |
---|
543 | ld8 r21=[r19] // ar.fpsr |
---|
544 | ;; |
---|
545 | mov ar.fpsr=r21 |
---|
546 | add r19=TF_UNAT,r18 |
---|
547 | ;; |
---|
548 | ld8 r21=[r19] |
---|
549 | ;; |
---|
550 | mov ar.unat=r21 |
---|
551 | ;; |
---|
552 | srlz.i |
---|
553 | ;; |
---|
554 | //rfi |
---|
555 | XEN_HYPER_RFI; |
---|
556 | ;; |
---|
557 | END(restore_tf_rse_switch) |
---|
558 | |
---|
559 | |
---|
560 | ENTRY(save_special_regs) |
---|
561 | alloc loc0=ar.pfs,1,7,0,0 |
---|
562 | movl loc1=XSI_IFA // XEN !! |
---|
563 | movl loc2=XSI_ISR // XEN !! |
---|
564 | ;; |
---|
565 | ld8 loc3=[loc1],XSI_IIM_OFS-XSI_IFA_OFS // load XEN.ifa |
---|
566 | ld8 loc4=[loc2],XSI_IIPA_OFS-XSI_ISR_OFS // load XEN.isr |
---|
567 | add loc5=TF_IFA,in0 |
---|
568 | add loc6=TF_ISR,in0 |
---|
569 | ;; |
---|
570 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
571 | mux1 loc3=loc3,@rev; mux1 loc4=loc4,@rev;; |
---|
572 | #endif |
---|
573 | st8 [loc5]=loc3,TF_IIM-TF_IFA // store cr.ifa |
---|
574 | st8 [loc6]=loc4 // store cr.isr |
---|
575 | ;; |
---|
576 | ld8 loc3=[loc1] // load XEN.iim |
---|
577 | ;; |
---|
578 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
579 | mux1 loc3=loc3,@rev;; |
---|
580 | #endif |
---|
581 | st8 [loc5]=loc3 // store cr.iim |
---|
582 | ;; |
---|
583 | mov ar.pfs=loc0 |
---|
584 | ;; |
---|
585 | br.ret.sptk.few rp |
---|
586 | END(save_special_regs) |
---|
587 | |
---|
588 | |
---|
589 | ENTRY(hypervisor_callback) |
---|
590 | // Calculate the stack address for storing. |
---|
591 | // Use the kernel stack here because it's mapped wired! |
---|
592 | // -> no nested tlb faults! |
---|
593 | movl r18=kstack+KSTACK_PAGES * PAGE_SIZE - 16 - TF_SIZE |
---|
594 | |
---|
595 | //add r18=-TF_SIZE,sp |
---|
596 | add r30=0xabab,r0 |
---|
597 | ;; |
---|
598 | { .mib |
---|
599 | nop 0x02 |
---|
600 | mov r16=ip // for jump back from save_tf_rse_switch |
---|
601 | br.sptk save_tf_rse_switch |
---|
602 | ;; |
---|
603 | } |
---|
604 | add sp=-16,r18 // the new stack |
---|
605 | alloc r15=ar.pfs,0,0,1,0 // 1 out for do_trap_error |
---|
606 | ;; |
---|
607 | mov out0=r18 // the trap frame |
---|
608 | movl r22=XSI_PSR_IC |
---|
609 | mov r23=1;; |
---|
610 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
611 | mux1 r23=r23,@rev;; |
---|
612 | #endif |
---|
613 | st8 [r22]=r23 // ssm psr.ic |
---|
614 | ;; |
---|
615 | br.call.sptk.few rp = do_hypervisor_callback |
---|
616 | |
---|
617 | movl r22=XSI_PSR_IC |
---|
618 | ;; |
---|
619 | st4 [r22]=r0 // rsm psr.ic |
---|
620 | |
---|
621 | add r16=16,sp // load EF-pointer again |
---|
622 | ;; |
---|
623 | //mov r18=sp |
---|
624 | movl r18=kstack+KSTACK_PAGES * PAGE_SIZE - 16 - TF_SIZE |
---|
625 | ;; |
---|
626 | |
---|
627 | // must have r18-efp, calls rfi at the end. |
---|
628 | br.sptk restore_tf_rse_switch |
---|
629 | ;; |
---|
630 | END(hypervisor_callback) |
---|
631 | |
---|
632 | /* |
---|
633 | * In: r30 - trap number |
---|
634 | */ |
---|
635 | ENTRY(trap_error) |
---|
636 | // Calculate the stack address for storing. |
---|
637 | add r18=-TF_SIZE,sp |
---|
638 | ;; |
---|
639 | add r20=TF_TRAP_NUM,r18 |
---|
640 | ;; |
---|
641 | st2 [r20]=r30 // save trap number |
---|
642 | ;; |
---|
643 | |
---|
644 | { .mib |
---|
645 | nop 0x02 |
---|
646 | mov r16=ip // for jumping back from save_tf_rse_switch |
---|
647 | // Used register: r16, r18, r19, r20, r21, r22 of bank 0 |
---|
648 | br.sptk save_tf_rse_switch |
---|
649 | ;; |
---|
650 | } |
---|
651 | |
---|
652 | alloc r15=ar.pfs,0,0,1,0 // 1 out for do_trap_error |
---|
653 | ;; |
---|
654 | mov out0=r18 // the trap frame |
---|
655 | add sp=-16,r18 // C-call abi |
---|
656 | ;; |
---|
657 | |
---|
658 | //bsw.1 |
---|
659 | movl r30=XSI_BANKNUM |
---|
660 | mov r31=1;; |
---|
661 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
662 | mux1 r31=r31,@rev;; |
---|
663 | #endif |
---|
664 | st4 [r30]=r31;; |
---|
665 | |
---|
666 | /* Save extra interrupt registers to the trap frame. */ |
---|
667 | br.call.sptk.few rp = save_special_regs |
---|
668 | ;; |
---|
669 | |
---|
670 | movl r22=XSI_PSR_IC |
---|
671 | movl r23=XSI_PSR_I_ADDR |
---|
672 | ;; |
---|
673 | ld8 r23=[r23] |
---|
674 | mov r25=1 |
---|
675 | ;; |
---|
676 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
677 | mux1 r25=r25,@rev; mux1 r23=r23,@rev;; |
---|
678 | #endif |
---|
679 | st4 [r22]=r25 // ssm psr.ic |
---|
680 | st1 [r23]=r0 // ssm psr.i |
---|
681 | ;; |
---|
682 | |
---|
683 | br.call.sptk.few rp = do_trap_error |
---|
684 | ;; |
---|
685 | // --> currently not reached!!! |
---|
686 | movl r23=XSI_PSR_I_ADDR |
---|
687 | movl r22=XSI_PSR_IC |
---|
688 | ;; |
---|
689 | ld8 r23=[r23] |
---|
690 | mov r25=1 |
---|
691 | ;; |
---|
692 | #if defined(BIG_ENDIAN) // swap because mini-os is in BE |
---|
693 | mux1 r25=r25,@rev;; |
---|
694 | mux1 r25=r25,@rev; mux1 r23=r23,@rev;; |
---|
695 | #endif |
---|
696 | st1 [r23]=r25 |
---|
697 | st4 [r22]=r0 // note: clears both vpsr.i and vpsr.ic! |
---|
698 | ;; |
---|
699 | bsw.0 |
---|
700 | ;; |
---|
701 | add r18=16,sp // load EF-pointer again |
---|
702 | ;; |
---|
703 | mov sp=r18 |
---|
704 | // must have r18-efp, calls rfi at the end. |
---|
705 | br.sptk restore_tf_rse_switch |
---|
706 | ;; |
---|
707 | END(trap_error) |
---|
708 | |
---|
709 | |
---|
710 | /* |
---|
711 | * The trap handler stuff. |
---|
712 | */ |
---|
713 | |
---|
714 | #define TRAP_ERR(num) \ |
---|
715 | mov r30 = num; \ |
---|
716 | ;; ; \ |
---|
717 | br.sptk trap_error \ |
---|
718 | ;; |
---|
719 | |
---|
720 | #define IVT_ENTRY(name, offset) \ |
---|
721 | .org ia64_trap_table + offset; \ |
---|
722 | .global hivt_##name; \ |
---|
723 | .proc hivt_##name; \ |
---|
724 | .prologue; \ |
---|
725 | .body; \ |
---|
726 | hivt_##name: |
---|
727 | |
---|
728 | #define IVT_END(name) \ |
---|
729 | .endp hivt_##name; \ |
---|
730 | .align 0x100 |
---|
731 | |
---|
732 | #define IVT_ERR(name, num, offset) \ |
---|
733 | IVT_ENTRY(name, offset); \ |
---|
734 | TRAP_ERR(num); \ |
---|
735 | IVT_END(name) |
---|
736 | /* |
---|
737 | * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 |
---|
738 | * bundles per vector and 48 slots with 16 bundles per vector. |
---|
739 | */ |
---|
740 | |
---|
741 | .section .text.hivt,"ax" |
---|
742 | .align 32768 |
---|
743 | .global ia64_trap_table |
---|
744 | .size ia64_trap_table, 32768 |
---|
745 | ia64_trap_table: |
---|
746 | |
---|
747 | IVT_ERR(VHPT_Translation, 0, 0x0) |
---|
748 | IVT_ERR(Instruction_TLB, 1, 0x0400) |
---|
749 | IVT_ERR(Data_TLB, 2, 0x0800) |
---|
750 | IVT_ERR(Alternate_Instruction_TLB, 3, 0x0c00) |
---|
751 | |
---|
752 | |
---|
753 | IVT_ENTRY(Alternate_Data_TLB, 0x1000) |
---|
754 | mov r30=4 // trap number |
---|
755 | mov r16=cr.ifa // where did it happen |
---|
756 | mov r31=pr // save predicates |
---|
757 | ;; |
---|
758 | extr.u r17=r16,IA64_RR_IDX_POS,3 // get region number |
---|
759 | ;; |
---|
760 | cmp.eq p14,p15=7,r17 |
---|
761 | ;; |
---|
762 | //(p14) br.sptk adt_regf_addr // Check for region 7 - phys addresses |
---|
763 | // ;; |
---|
764 | // br.sptk trap_error |
---|
765 | // // No return |
---|
766 | // |
---|
767 | //adt_regf_addr: |
---|
768 | // extr.u r17=r16,60,4 // get region number |
---|
769 | // ;; |
---|
770 | // cmp.eq p14,p15=0xf,r17 |
---|
771 | // ;; |
---|
772 | (p14) br.sptk adt_reg7_addr // Check for region 7 - phys addresses |
---|
773 | ;; |
---|
774 | br.sptk trap_error |
---|
775 | |
---|
776 | adt_reg7_addr: |
---|
777 | /* |
---|
778 | * region 7 addresses are only directly mapped physically |
---|
779 | * addresses. Currently I don't do a check. |
---|
780 | */ |
---|
781 | movl r20=~((7 << IA64_RR_IDX_POS) | 0xfff) |
---|
782 | movl r18=((PTE_PS_16K<<IA64_ITIR_PS)|(0<<IA64_ITIR_KEY)) |
---|
783 | ;; |
---|
784 | movl r19= ((1<<PTE_OFF_P) | (PTE_MA_WB<<PTE_OFF_MA) | \ |
---|
785 | (1<<PTE_OFF_A) | (1<<PTE_OFF_D) | \ |
---|
786 | (PTE_PL_KERN<<PTE_OFF_PL) | (PTE_AR_RW<<PTE_OFF_AR)) |
---|
787 | // clear the region bits and 0-11 |
---|
788 | // extract the pfn from the ifa |
---|
789 | mov cr.itir=r18 |
---|
790 | and r20=r20, r16 |
---|
791 | ;; |
---|
792 | or r20=r20,r19 // put pfn into pte |
---|
793 | ;; |
---|
794 | mov pr=r31,-1 // restore predicates |
---|
795 | itc.d r20 |
---|
796 | ;; |
---|
797 | XEN_HYPER_RFI; |
---|
798 | ;; |
---|
799 | |
---|
800 | IVT_END(Alternate_Data_TLB) |
---|
801 | |
---|
802 | |
---|
803 | IVT_ERR(Data_Nested_TLB, 5, 0x1400) |
---|
804 | IVT_ERR(Instruction_Key_Miss, 6, 0x1800) |
---|
805 | IVT_ERR(Data_Key_Miss, 7, 0x1c00) |
---|
806 | IVT_ERR(Dirty_Bit, 8, 0x2000) |
---|
807 | IVT_ERR(Instruction_Access_Bit, 9, 0x2400) |
---|
808 | IVT_ERR(Data_Access_Bit, 10, 0x2800) |
---|
809 | IVT_ERR(Break_Instruction, 11, 0x2c00) |
---|
810 | IVT_ERR(External_Interrupt, 12, 0x3000) |
---|
811 | IVT_ERR(Reserved_3400, 13, 0x3400) |
---|
812 | IVT_ERR(Reserved_3800, 14, 0x3800) |
---|
813 | IVT_ERR(Reserved_3c00, 15, 0x3c00) |
---|
814 | IVT_ERR(Reserved_4000, 16, 0x4000) |
---|
815 | IVT_ERR(Reserved_4400, 17, 0x4400) |
---|
816 | IVT_ERR(Reserved_4800, 18, 0x4800) |
---|
817 | IVT_ERR(Reserved_4c00, 19, 0x4c00) |
---|
818 | IVT_ERR(Page_Not_Present, 20, 0x5000) |
---|
819 | IVT_ERR(Key_Permission, 21, 0x5100) |
---|
820 | IVT_ERR(Instruction_Access_Rights, 22, 0x5200) |
---|
821 | IVT_ERR(Data_Access_Rights, 23, 0x5300) |
---|
822 | IVT_ERR(General_Exception, 24, 0x5400) |
---|
823 | IVT_ERR(Disabled_FP_Register, 25, 0x5500) |
---|
824 | IVT_ERR(NaT_Consumption, 26, 0x5600) |
---|
825 | IVT_ERR(Speculation, 27, 0x5700) |
---|
826 | IVT_ERR(Reserved_5800, 28, 0x5800) |
---|
827 | IVT_ERR(Debug, 29, 0x5900) |
---|
828 | IVT_ERR(Unaligned_Reference, 30, 0x5a00) |
---|
829 | IVT_ERR(Unsupported_Data_Reference, 31, 0x5b00) |
---|
830 | IVT_ERR(Floating_Point_Fault, 32, 0x5c00) |
---|
831 | IVT_ERR(Floating_Point_Trap, 33, 0x5d00) |
---|
832 | IVT_ERR(Lower_Privilege_Transfer_Trap, 34, 0x5e00) |
---|
833 | IVT_ERR(Taken_Branch_Trap, 35, 0x5f00) |
---|
834 | IVT_ERR(Single_Step_Trap, 36, 0x6000) |
---|
835 | IVT_ERR(Reserved_6100, 37, 0x6100) |
---|
836 | IVT_ERR(Reserved_6200, 38, 0x6200) |
---|
837 | IVT_ERR(Reserved_6300, 39, 0x6300) |
---|
838 | IVT_ERR(Reserved_6400, 40, 0x6400) |
---|
839 | IVT_ERR(Reserved_6500, 41, 0x6500) |
---|
840 | IVT_ERR(Reserved_6600, 42, 0x6600) |
---|
841 | IVT_ERR(Reserved_6700, 43, 0x6700) |
---|
842 | IVT_ERR(Reserved_6800, 44, 0x6800) |
---|
843 | IVT_ERR(IA_32_Exception, 45, 0x6900) |
---|
844 | IVT_ERR(IA_32_Intercept, 46, 0x6a00) |
---|
845 | IVT_ERR(IA_32_Interrupt, 47, 0x6b00) |
---|
846 | IVT_ERR(Reserved_6c00, 48, 0x6c00) |
---|
847 | IVT_ERR(Reserved_6d00, 49, 0x6d00) |
---|
848 | IVT_ERR(Reserved_6e00, 50, 0x6e00) |
---|
849 | IVT_ERR(Reserved_6f00, 51, 0x6f00) |
---|
850 | IVT_ERR(Reserved_7000, 52, 0x7000) |
---|
851 | IVT_ERR(Reserved_7100, 53, 0x7100) |
---|
852 | IVT_ERR(Reserved_7200, 54, 0x7200) |
---|
853 | IVT_ERR(Reserved_7300, 55, 0x7300) |
---|
854 | IVT_ERR(Reserved_7400, 56, 0x7400) |
---|
855 | IVT_ERR(Reserved_7500, 57, 0x7500) |
---|
856 | IVT_ERR(Reserved_7600, 58, 0x7600) |
---|
857 | IVT_ERR(Reserved_7700, 59, 0x7700) |
---|
858 | IVT_ERR(Reserved_7800, 60, 0x7800) |
---|
859 | IVT_ERR(Reserved_7900, 61, 0x7900) |
---|
860 | IVT_ERR(Reserved_7a00, 62, 0x7a00) |
---|
861 | IVT_ERR(Reserved_7b00, 63, 0x7b00) |
---|
862 | IVT_ERR(Reserved_7c00, 64, 0x7c00) |
---|
863 | IVT_ERR(Reserved_7d00, 65, 0x7d00) |
---|
864 | IVT_ERR(Reserved_7e00, 66, 0x7e00) |
---|
865 | IVT_ERR(Reserved_7f00, 67, 0x7f00) |
---|