ia64/xen-unstable

view xen/arch/ia64/vmx/vmx_entry.S @ 16785:af3550f53874

[IA64] domheap: Don't pin xenheap down. Now it's unnecessary.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Thu Jan 17 12:05:43 2008 -0700 (2008-01-17)
parents 6f7e6608cb74
children 759a9fb42645
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /*
3 * vmx_entry.S:
4 * Copyright (c) 2005, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 * Xuefei Xu (Anthony Xu) (anthony.xu@intel.com)
20 * Kun Tian (Kevin Tian) (kevin.tian@intel.com)
21 */
23 #include <linux/config.h>
24 #include <asm/asmmacro.h>
25 #include <asm/offsets.h>
26 #include "vmx_minstate.h"
28 GLOBAL_ENTRY(ia64_leave_nested)
29 rsm psr.i
30 ;;
31 adds r21=PT(PR)+16,r12
32 ;;
33 lfetch [r21],PT(CR_IPSR)-PT(PR)
34 adds r2=PT(B6)+16,r12
35 adds r3=PT(R16)+16,r12
36 ;;
37 lfetch [r21]
38 ld8 r28=[r2],8 // load b6
39 adds r29=PT(R24)+16,r12
41 ld8.fill r16=[r3]
42 adds r3=PT(AR_CSD)-PT(R16),r3
43 adds r30=PT(AR_CCV)+16,r12
44 ;;
45 ld8.fill r24=[r29]
46 ld8 r15=[r30] // load ar.ccv
47 ;;
48 ld8 r29=[r2],16 // load b7
49 ld8 r30=[r3],16 // load ar.csd
50 ;;
51 ld8 r31=[r2],16 // load ar.ssd
52 ld8.fill r8=[r3],16
53 ;;
54 ld8.fill r9=[r2],16
55 ld8.fill r10=[r3],PT(R17)-PT(R10)
56 ;;
57 ld8.fill r11=[r2],PT(R18)-PT(R11)
58 ld8.fill r17=[r3],16
59 ;;
60 ld8.fill r18=[r2],16
61 ld8.fill r19=[r3],16
62 ;;
63 ld8.fill r20=[r2],16
64 ld8.fill r21=[r3],16
65 mov ar.csd=r30
66 mov ar.ssd=r31
67 ;;
68 rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection
69 invala // invalidate ALAT
70 ;;
71 ld8.fill r22=[r2],24
72 ld8.fill r23=[r3],24
73 mov b6=r28
74 ;;
75 ld8.fill r25=[r2],16
76 ld8.fill r26=[r3],16
77 mov b7=r29
78 ;;
79 ld8.fill r27=[r2],16
80 ld8.fill r28=[r3],16
81 ;;
82 ld8.fill r29=[r2],16
83 ld8.fill r30=[r3],24
84 ;;
85 ld8.fill r31=[r2],PT(F9)-PT(R31)
86 adds r3=PT(F10)-PT(F6),r3
87 ;;
88 ldf.fill f9=[r2],PT(F6)-PT(F9)
89 ldf.fill f10=[r3],PT(F8)-PT(F10)
90 ;;
91 ldf.fill f6=[r2],PT(F7)-PT(F6)
92 ;;
93 ldf.fill f7=[r2],PT(F11)-PT(F7)
94 ldf.fill f8=[r3],32
95 ;;
96 srlz.i // ensure interruption collection is off
97 mov ar.ccv=r15
98 ;;
99 bsw.0 // switch back to bank 0 (no stop bit required beforehand...)
100 ;;
101 ldf.fill f11=[r2]
102 adds r16=PT(CR_IPSR)+16,r12
103 adds r17=PT(CR_IIP)+16,r12
104 ;;
105 ld8 r29=[r16],16 // load cr.ipsr
106 ld8 r28=[r17],16 // load cr.iip
107 ;;
108 ld8 r30=[r16],16 // load cr.ifs
109 ld8 r25=[r17],16 // load ar.unat
110 ;;
111 #ifndef XEN
112 ld8 r26=[r16],16 // load ar.pfs
113 ld8 r27=[r17],16 // load ar.rsc
114 cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
115 ;;
116 ld8 r24=[r16],16 // load ar.rnat (may be garbage)
117 ld8 r23=[r17],16 // load ar.bspstore (may be garbage)
118 ;;
119 ld8 r31=[r16],16 // load predicates
120 #else
121 ld8 r26=[r16],32 // load ar.pfs
122 ld8 r27=[r17],32 // load ar.rsc
123 ;;
124 ld8 r31=[r16],32 // load predicates
125 #endif
126 ld8 r22=[r17],16 // load b0
127 ;;
128 #ifndef XEN
129 ld8 r19=[r16],16 // load ar.rsc value for "loadrs"
130 #endif
131 ld8.fill r1=[r17],16 // load r1
132 ;;
133 ld8.fill r12=[r16],16
134 ld8.fill r13=[r17],16
135 ;;
136 ld8 r20=[r16],16 // ar.fpsr
137 ld8.fill r15=[r17],16
138 ;;
139 ld8.fill r14=[r16],16
140 ld8.fill r2=[r17]
141 ;;
142 ld8.fill r3=[r16]
143 #ifndef XEN
144 ;;
145 mov r16=ar.bsp // get existing backing store pointer
146 ;;
147 #endif
148 mov b0=r22
149 mov ar.pfs=r26
150 mov cr.ifs=r30
151 mov cr.ipsr=r29
152 mov ar.fpsr=r20
153 mov cr.iip=r28
154 ;;
155 mov ar.rsc=r27
156 mov ar.unat=r25
157 mov pr=r31,-1
158 rfi
159 END(ia64_leave_nested)
163 GLOBAL_ENTRY(ia64_leave_hypervisor_prepare)
164 PT_REGS_UNWIND_INFO(0)
165 /*
166 * work.need_resched etc. mustn't get changed by this CPU before it returns to
167 ;;
168 * user- or fsys-mode, hence we disable interrupts early on:
169 */
170 adds r2 = PT(R4)+16,r12
171 adds r3 = PT(R5)+16,r12
172 adds r8 = PT(EML_UNAT)+16,r12
173 ;;
174 ld8 r8 = [r8]
175 ;;
176 mov ar.unat=r8
177 ;;
178 ld8.fill r4=[r2],16 //load r4
179 ld8.fill r5=[r3],16 //load r5
180 ;;
181 ld8.fill r6=[r2] //load r6
182 ld8.fill r7=[r3] //load r7
183 ;;
184 END(ia64_leave_hypervisor_prepare)
185 //fall through
186 GLOBAL_ENTRY(ia64_leave_hypervisor)
187 PT_REGS_UNWIND_INFO(0)
188 rsm psr.i
189 ;;
190 br.call.sptk.many b0=leave_hypervisor_tail
191 ;;
192 adds r20=PT(PR)+16,r12
193 adds r8=PT(EML_UNAT)+16,r12
194 ;;
195 ld8 r8=[r8]
196 ;;
197 mov ar.unat=r8
198 ;;
199 lfetch [r20],PT(CR_IPSR)-PT(PR)
200 adds r2 = PT(B6)+16,r12
201 adds r3 = PT(B7)+16,r12
202 ;;
203 lfetch [r20]
204 ;;
205 ld8 r24=[r2],16 /* B6 */
206 ld8 r25=[r3],16 /* B7 */
207 ;;
208 ld8 r26=[r2],16 /* ar_csd */
209 ld8 r27=[r3],16 /* ar_ssd */
210 mov b6 = r24
211 ;;
212 ld8.fill r8=[r2],16
213 ld8.fill r9=[r3],16
214 mov b7 = r25
215 ;;
216 mov ar.csd = r26
217 mov ar.ssd = r27
218 ;;
219 ld8.fill r10=[r2],PT(R15)-PT(R10)
220 ld8.fill r11=[r3],PT(R14)-PT(R11)
221 ;;
222 ld8.fill r15=[r2],PT(R16)-PT(R15)
223 ld8.fill r14=[r3],PT(R17)-PT(R14)
224 ;;
225 ld8.fill r16=[r2],16
226 ld8.fill r17=[r3],16
227 ;;
228 ld8.fill r18=[r2],16
229 ld8.fill r19=[r3],16
230 ;;
231 ld8.fill r20=[r2],16
232 ld8.fill r21=[r3],16
233 ;;
234 ld8.fill r22=[r2],16
235 ld8.fill r23=[r3],16
236 ;;
237 ld8.fill r24=[r2],16
238 ld8.fill r25=[r3],16
239 ;;
240 ld8.fill r26=[r2],16
241 ld8.fill r27=[r3],16
242 ;;
243 ld8.fill r28=[r2],16
244 ld8.fill r29=[r3],16
245 ;;
246 ld8.fill r30=[r2],PT(F6)-PT(R30)
247 ld8.fill r31=[r3],PT(F7)-PT(R31)
248 ;;
249 rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection
250 invala // invalidate ALAT
251 ;;
252 ldf.fill f6=[r2],32
253 ldf.fill f7=[r3],32
254 ;;
255 ldf.fill f8=[r2],32
256 ldf.fill f9=[r3],32
257 ;;
258 ldf.fill f10=[r2],32
259 ldf.fill f11=[r3],24
260 ;;
261 srlz.i // ensure interruption collection is off
262 ;;
263 bsw.0
264 ;;
265 adds r16 = PT(CR_IPSR)+16,r12
266 adds r17 = PT(CR_IIP)+16,r12
267 mov r21=r13 // get current
268 ;;
269 ld8 r31=[r16],16 // load cr.ipsr
270 ld8 r30=[r17],16 // load cr.iip
271 ;;
272 ld8 r29=[r16],16 // load cr.ifs
273 ld8 r28=[r17],16 // load ar.unat
274 ;;
275 ld8 r27=[r16],16 // load ar.pfs
276 ld8 r26=[r17],16 // load ar.rsc
277 ;;
278 ld8 r25=[r16],16 // load ar.rnat
279 ld8 r24=[r17],16 // load ar.bspstore
280 ;;
281 ld8 r23=[r16],16 // load predicates
282 ld8 r22=[r17],16 // load b0
283 ;;
284 ld8 r20=[r16],16 // load ar.rsc value for "loadrs"
285 ld8.fill r1=[r17],16 //load r1
286 ;;
287 ld8.fill r12=[r16],16 //load r12
288 ld8.fill r13=[r17],PT(R2)-PT(R13) //load r13
289 ;;
290 ld8 r19=[r16],PT(R3)-PT(AR_FPSR) //load ar_fpsr
291 ld8.fill r2=[r17],PT(AR_CCV)-PT(R2) //load r2
292 ;;
293 ld8.fill r3=[r16] //load r3
294 ld8 r18=[r17] //load ar_ccv
295 ;;
296 mov ar.fpsr=r19
297 mov ar.ccv=r18
298 shr.u r18=r20,16
299 ;;
300 vmx_rbs_switch:
301 movl r19= THIS_CPU(ia64_phys_stacked_size_p8)
302 ;;
303 ld4 r19=[r19]
305 vmx_dont_preserve_current_frame:
306 /*
307 * To prevent leaking bits between the hypervisor and guest domain,
308 * we must clear the stacked registers in the "invalid" partition here.
309 * 5 registers/cycle on McKinley).
310 */
311 # define pRecurse p6
312 # define pReturn p7
313 # define Nregs 14
315 alloc loc0=ar.pfs,2,Nregs-2,2,0
316 shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
317 sub r19=r19,r18 // r19 = (physStackedSize + 8) - dirtySize
318 ;;
319 mov ar.rsc=r20 // load ar.rsc to be used for "loadrs"
320 shladd in0=loc1,3,r19
321 mov in1=0
322 ;;
323 TEXT_ALIGN(32)
324 vmx_rse_clear_invalid:
325 alloc loc0=ar.pfs,2,Nregs-2,2,0
326 cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
327 add out0=-Nregs*8,in0
328 add out1=1,in1 // increment recursion count
329 mov loc1=0
330 mov loc2=0
331 ;;
332 mov loc3=0
333 mov loc4=0
334 mov loc5=0
335 mov loc6=0
336 mov loc7=0
337 (pRecurse) br.call.dptk.few b0=vmx_rse_clear_invalid
338 ;;
339 mov loc8=0
340 mov loc9=0
341 cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
342 mov loc10=0
343 mov loc11=0
344 (pReturn) br.ret.dptk.many b0
346 # undef pRecurse
347 # undef pReturn
349 // loadrs has already been shifted
350 alloc r16=ar.pfs,0,0,0,0 // drop current register frame
351 ;;
352 loadrs
353 ;;
354 mov ar.bspstore=r24
355 ;;
356 mov ar.unat=r28
357 mov ar.rnat=r25
358 mov ar.rsc=r26
359 ;;
360 mov cr.ipsr=r31
361 mov cr.iip=r30
362 (pNonSys) mov cr.ifs=r29
363 mov ar.pfs=r27
364 adds r18=IA64_VPD_BASE_OFFSET,r21
365 ;;
366 ld8 r18=[r18] //vpd
367 adds r17=IA64_VCPU_ISR_OFFSET,r21
368 ;;
369 ld8 r17=[r17]
370 adds r19=VPD(VPSR),r18
371 ;;
372 ld8 r19=[r19] //vpsr
373 movl r20=__vsa_base
374 ;;
375 //vsa_sync_write_start
376 ld8 r20=[r20] // read entry point
377 mov r25=r18
378 ;;
379 movl r24=ia64_vmm_entry // calculate return address
380 add r16=PAL_VPS_SYNC_WRITE,r20
381 ;;
382 mov b0=r16
383 br.cond.sptk b0 // call the service
384 ;;
385 END(ia64_leave_hypervisor)
386 // fall through
387 GLOBAL_ENTRY(ia64_vmm_entry)
388 /*
389 * must be at bank 0
390 * parameter:
391 * r17:cr.isr
392 * r18:vpd
393 * r19:vpsr
394 * r20:__vsa_base
395 * r22:b0
396 * r23:predicate
397 */
398 mov r24=r22
399 mov r25=r18
400 tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
401 ;;
402 (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
403 (p1) br.sptk.many ia64_vmm_entry_out
404 ;;
405 tbit.nz p1,p2 = r17,IA64_ISR_IR_BIT //p1=cr.isr.ir
406 ;;
407 (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
408 (p2) add r29=PAL_VPS_RESUME_HANDLER,r20
409 (p2) ld8 r26=[r25]
410 ;;
411 ia64_vmm_entry_out:
412 mov pr=r23,-2
413 mov b0=r29
414 ;;
415 br.cond.sptk b0 // call pal service
416 END(ia64_vmm_entry)
420 /*
421 * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
422 * need to switch to bank 0 and doesn't restore the scratch registers.
423 * To avoid leaking kernel bits, the scratch registers are set to
424 * the following known-to-be-safe values:
425 *
426 * r1: restored (global pointer)
427 * r2: cleared
428 * r3: 1 (when returning to user-level)
429 * r8-r11: restored (syscall return value(s))
430 * r12: restored (user-level stack pointer)
431 * r13: restored (user-level thread pointer)
432 * r14: set to __kernel_syscall_via_epc
433 * r15: restored (syscall #)
434 * r16-r17: cleared
435 * r18: user-level b6
436 * r19: cleared
437 * r20: user-level ar.fpsr
438 * r21: user-level b0
439 * r22: cleared
440 * r23: user-level ar.bspstore
441 * r24: user-level ar.rnat
442 * r25: user-level ar.unat
443 * r26: user-level ar.pfs
444 * r27: user-level ar.rsc
445 * r28: user-level ip
446 * r29: user-level psr
447 * r30: user-level cfm
448 * r31: user-level pr
449 * f6-f11: cleared
450 * pr: restored (user-level pr)
451 * b0: restored (user-level rp)
452 * b6: restored
453 * b7: set to __kernel_syscall_via_epc
454 * ar.unat: restored (user-level ar.unat)
455 * ar.pfs: restored (user-level ar.pfs)
456 * ar.rsc: restored (user-level ar.rsc)
457 * ar.rnat: restored (user-level ar.rnat)
458 * ar.bspstore: restored (user-level ar.bspstore)
459 * ar.fpsr: restored (user-level ar.fpsr)
460 * ar.ccv: cleared
461 * ar.csd: cleared
462 * ar.ssd: cleared
463 */
464 GLOBAL_ENTRY(ia64_leave_hypercall)
465 PT_REGS_UNWIND_INFO(0)
466 /*
467 * work.need_resched etc. mustn't get changed by this CPU before it returns to
468 * user- or fsys-mode, hence we disable interrupts early on.
469 *
470 * p6 controls whether current_thread_info()->flags needs to be check for
471 * extra work. We always check for extra work when returning to user-level.
472 * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
473 * is 0. After extra work processing has been completed, execution
474 * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
475 * needs to be redone.
476 */
477 ;;
478 adds r16=PT(R8)+16,r12
479 ;;
480 st8 [r16]=r8
481 ;;
482 //(pUStk) rsm psr.i
483 rsm psr.i
484 cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
485 //(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
486 ;;
487 br.call.sptk.many b0=leave_hypervisor_tail
488 .work_processed_syscall:
489 //clean up bank 1 registers
490 ;;
491 adds r16=PT(R8)+16,r12
492 ;;
493 ld8 r8=[r16]
494 ;;
495 mov r16=r0
496 mov r17=r0
497 mov r18=r0
498 mov r19=r0
499 mov r20=r0
500 mov r21=r0
501 mov r22=r0
502 mov r23=r0
503 mov r24=r0
504 mov r25=r0
505 mov r26=r0
506 mov r27=r0
507 mov r28=r0
508 mov r29=r0
509 mov r30=r0
510 mov r31=r0
511 bsw.0
512 ;;
513 adds r2=PT(LOADRS)+16,r12
514 adds r3=PT(AR_BSPSTORE)+16,r12
515 #ifndef XEN
516 adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
517 ;;
518 (p6) ld4 r31=[r18] // load current_thread_info()->flags
519 #endif
520 ;;
521 ld8 r20=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
522 nop.i 0
523 ;;
524 // mov r16=ar.bsp // M2 get existing backing store pointer
525 ld8 r18=[r2],PT(R9)-PT(B6) // load b6
526 #ifndef XEN
527 (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
528 #endif
529 ;;
530 ld8 r24=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage)
531 #ifndef XEN
532 (p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending?
533 (p6) br.cond.spnt .work_pending_syscall
534 #endif
535 ;;
536 // start restoring the state saved on the kernel stack (struct pt_regs):
537 ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
538 ld8 r11=[r3],PT(CR_IIP)-PT(R11)
539 //(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE!
540 ;;
541 invala // M0|1 invalidate ALAT
542 rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection
543 #ifndef XEN
544 cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs
545 #endif
547 ld8 r31=[r2],32 // M0|1 load cr.ipsr
548 ld8 r30=[r3],16 // M0|1 load cr.iip
549 ;;
550 // ld8 r29=[r2],16 // M0|1 load cr.ifs
551 ld8 r28=[r3],16 // M0|1 load ar.unat
552 //(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
553 ;;
554 ld8 r27=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
555 //(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
556 nop 0
557 ;;
558 ld8 r22=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
559 ld8 r26=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc
560 mov f6=f0 // F clear f6
561 ;;
562 ld8 r25=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage)
563 ld8 r23=[r3],PT(R1)-PT(PR) // M0|1 load predicates
564 mov f7=f0 // F clear f7
565 ;;
566 ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr
567 ld8.fill r1=[r3],16 // M0|1 load r1
568 //(pUStk) mov r17=1 // A
569 ;;
570 //(pUStk) st1 [r14]=r17 // M2|3
571 ld8.fill r13=[r3],16 // M0|1
572 mov f8=f0 // F clear f8
573 ;;
574 ld8.fill r12=[r2] // M0|1 restore r12 (sp)
575 #ifdef XEN
576 ld8.fill r2=[r3] // M0|1
577 #else
578 ld8.fill r15=[r3] // M0|1 restore r15
579 #endif
580 mov b6=r18 // I0 restore b6
581 mov ar.fpsr=r20
582 // addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A
583 mov f9=f0 // F clear f9
584 //(pKStk) br.cond.dpnt.many skip_rbs_switch // B
586 // srlz.d // M0 ensure interruption collection is off (for cover)
587 // shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
588 mov r3=r21
589 cover // B add current frame into dirty partition & set cr.ifs
590 ;;
591 //(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8
592 mov r19=ar.bsp // M2 get new backing store pointer
593 addl r18=IA64_RBS_OFFSET, r3
594 ;;
595 mov r3=r0
596 sub r18=r19,r18 // get byte size of existing "dirty" partition
597 ;;
598 shl r20=r18,16 // set rsc.load
599 mov f10=f0 // F clear f10
600 #ifdef XEN
601 mov r14=r0
602 #else
603 movl r14=__kernel_syscall_via_epc // X
604 #endif
605 ;;
606 mov.m ar.csd=r0 // M2 clear ar.csd
607 mov.m ar.ccv=r0 // M2 clear ar.ccv
608 mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc)
610 mov.m ar.ssd=r0 // M2 clear ar.ssd
611 mov f11=f0 // F clear f11
612 br.cond.sptk.many vmx_rbs_switch // B
613 END(ia64_leave_hypercall)
616 /*
617 * in0: new rr7
618 * in1: virtual address of guest_vhpt
619 * in2: virtual address of pal code segment
620 * r8: will contain old rid value
621 */
623 #define PSR_BITS_TO_CLEAR \
624 (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | \
625 IA64_PSR_RT | IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | \
626 IA64_PSR_ED | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_IC)
627 #define PSR_BITS_TO_SET IA64_PSR_BN
629 //extern void vmx_switch_rr7(unsigned long rid, void *guest_vhpt, void * pal_vaddr, void * shared_arch_info );
630 GLOBAL_ENTRY(vmx_switch_rr7)
631 // not sure this unwind statement is correct...
632 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1)
633 alloc loc1 = ar.pfs, 4, 8, 0, 0
634 1:{
635 mov r28 = in0 // copy procedure index
636 mov r8 = ip // save ip to compute branch
637 mov loc0 = rp // save rp
638 };;
639 .body
640 movl loc2=PERCPU_ADDR
641 ;;
642 tpa loc2 = loc2 // get physical address of per cpu date
643 tpa r3 = r8 // get physical address of ip
644 dep loc5 = 0,in1,60,4 // get physical address of guest_vhpt
645 dep loc6 = 0,in2,60,4 // get physical address of pal code
646 dep loc7 = 0,in3,60,4 // get physical address of privregs
647 ;;
648 dep loc6 = 0,loc6,0,IA64_GRANULE_SHIFT
649 // mask granule shift
650 dep loc7 = 0,loc7,0,IA64_GRANULE_SHIFT
651 // mask granule shift
652 mov loc4 = psr // save psr
653 ;;
654 mov loc3 = ar.rsc // save RSE configuration
655 ;;
656 mov ar.rsc = 0 // put RSE in enforced lazy, LE mode
657 movl r16=PSR_BITS_TO_CLEAR
658 movl r17=PSR_BITS_TO_SET
659 ;;
660 or loc4 = loc4,r17 // add in psr the bits to set
661 ;;
662 andcm r16=loc4,r16 // removes bits to clear from psr
663 br.call.sptk.many rp=ia64_switch_mode_phys
664 1:
665 // now in physical mode with psr.i/ic off so do rr7 switch
666 dep r16=-1,r0,61,3
667 ;;
668 mov rr[r16]=in0
669 ;;
670 srlz.d
671 ;;
673 // re-pin mappings for kernel text and data
674 mov r18=KERNEL_TR_PAGE_SHIFT<<2
675 movl r17=KERNEL_START
676 ;;
677 ptr.i r17,r18
678 ptr.d r17,r18
679 ;;
680 mov cr.itir=r18
681 mov cr.ifa=r17
682 mov r16=IA64_TR_KERNEL
683 movl r25 = PAGE_KERNEL
684 // r2=KERNEL_TR_PAGE_SHIFT truncated physicall address of ip
685 // = ia64_tpa(ip) & (KERNEL_TR_PAGE_SIZE - 1)
686 dep r2=0,r3,0,KERNEL_TR_PAGE_SHIFT
687 ;;
688 or r24=r2,r25
689 ;;
690 srlz.i
691 ;;
692 itr.i itr[r16]=r24
693 ;;
694 itr.d dtr[r16]=r24
695 ;;
697 // re-pin mapping for stack (current)
698 mov r26=IA64_GRANULE_SHIFT<<2
699 dep r21=0,r13,60,4 // physical address of "current"
700 ;;
701 ptr.d r13,r26
702 or r23=r21,r25 // construct PA | page properties
703 mov cr.itir=r26
704 mov cr.ifa=r13 // VA of next task...
705 mov r18=IA64_TR_CURRENT_STACK
706 ;;
707 itr.d dtr[r18]=r23 // wire in new mapping...
709 // re-pin mappings for per-cpu data
710 movl r22 = PERCPU_ADDR
711 ;;
712 mov r24=IA64_TR_PERCPU_DATA
713 or loc2 = r25,loc2 // construct PA | page properties
714 mov r23=PERCPU_PAGE_SHIFT<<2
715 ;;
716 ptr.d r22,r23
717 ;;
718 mov cr.itir=r23
719 mov cr.ifa=r22
720 ;;
721 itr.d dtr[r24]=loc2 // wire in new mapping...
722 ;;
724 // re-pin mappings for guest_vhpt
725 // unless overlaps with IA64_TR_CURRENT_STACK
726 // r21 = (current physical addr) & (IA64_GRANULE_SIZE - 1)
727 dep r21=0,r21,0,IA64_GRANULE_SHIFT
728 // r17 = (guest_vhpt physical addr) & (IA64_GRANULE_SIZE - 1)
729 dep r17=0,loc5,0,IA64_GRANULE_SHIFT
730 ;;
731 cmp.eq p7,p0=r17,r21 // check overlap with current stack
732 (p7) br.cond.sptk .vhpt_overlaps
733 mov r24=IA64_TR_VHPT
734 ;;
735 or loc5 = r25,loc5 // construct PA | page properties
736 mov r23 = IA64_GRANULE_SHIFT <<2
737 ;;
738 ptr.d in1,r23
739 ;;
740 mov cr.itir=r23
741 mov cr.ifa=in1
742 ;;
743 itr.d dtr[r24]=loc5 // wire in new mapping...
744 ;;
745 .vhpt_overlaps:
747 // re-pin mappings for PAL code section
748 mov r24=IA64_TR_PALCODE
749 or loc6 = r25,loc6 // construct PA | page properties
750 mov r23 = IA64_GRANULE_SHIFT<<2
751 ;;
752 ptr.i in2,r23
753 ;;
754 mov cr.itir=r23
755 mov cr.ifa=in2
756 ;;
757 itr.i itr[r24]=loc6 // wire in new mapping...
758 ;;
760 // r16, r19, r20 are used by
761 // ia64_switch_mode_phys()/ia64_switch_mode_virt()
762 // re-pin mappings for privregs
763 // r21 = (current physical addr) & (IA64_GRANULE_SIZE - 1)
764 // r17 = (guest_vhpt physical addr) & (IA64_GRANULE_SIZE - 1)
765 // loc6 = (((pal phys addr) & (IA64_GRANULE_SIZE - 1) << 2)) | PAGE_KERNEL
766 // loc7 = (privregs physical addr) & (IA64_GRANULE_SIZE - 1)
767 cmp.ne.unc p7,p0=r21,loc7 // check overlap with current stack
768 ;;
769 (p7) cmp.ne.unc p8,p0=r17,loc7 // check overlap with guest_vhpt
770 ;;
771 // loc7 = (((privregs phys) & (IA64_GRANULE_SIZE - 1)) << 2) | PAGE_KERNEL
772 or loc7 = r25,loc7 // construct PA | page properties
773 ;;
774 cmp.ne p9,p0=loc6,loc7
775 mov r22=IA64_TR_VPD
776 mov r24=IA64_TR_MAPPED_REGS
777 mov r23=IA64_GRANULE_SHIFT<<2
778 ;;
779 (p9) ptr.i in3,r23
780 (p8) ptr.d in3,r23
781 mov cr.itir=r23
782 mov cr.ifa=in3
783 ;;
784 (p9) itr.i itr[r22]=loc7 // wire in new mapping...
785 ;;
786 (p8) itr.d dtr[r24]=loc7 // wire in new mapping...
787 ;;
789 // done, switch back to virtual and return
790 mov r16=loc4 // r16= original psr
791 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
792 mov ar.pfs = loc1
793 mov rp = loc0
794 ;;
795 mov ar.rsc=loc3 // restore RSE configuration
796 srlz.d // seralize restoration of psr.l
797 br.ret.sptk.many rp
798 END(vmx_switch_rr7)