ia64/xen-unstable

view xen/arch/ia64/vmx/vmx_entry.S @ 19848:5839491bbf20

[IA64] replace MAX_VCPUS with d->max_vcpus where necessary.

don't use MAX_VCPUS, and use vcpu::max_vcpus.
The changeset of 2f9e1348aa98 introduced max_vcpus to allow more vcpus
per guest. This patch is ia64 counter part.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jun 29 11:26:05 2009 +0900 (2009-06-29)
parents 7da7b53b2139
children
line source
1 /* -*- Mode:ASM; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
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 ;;
374 //vsa_sync_write_start
375 movl r24=ia64_vmm_entry // calculate return address
376 mov r25=r18
377 br.sptk.many vmx_vps_sync_write // call the service
378 ;;
379 END(ia64_leave_hypervisor)
380 // fall through
383 GLOBAL_ENTRY(ia64_vmm_entry)
384 /*
385 * must be at bank 0
386 * parameter:
387 * r17:cr.isr
388 * r18:vpd
389 * r19:vpsr
390 * r22:b0
391 * r23:predicate
392 */
393 mov r24=r22
394 mov r25=r18
395 tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
396 (p1) br.cond.sptk.few vmx_vps_resume_normal
397 (p2) br.cond.sptk.many vmx_vps_resume_handler
398 ;;
399 END(ia64_vmm_entry)
402 /*
403 * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
404 * need to switch to bank 0 and doesn't restore the scratch registers.
405 * To avoid leaking kernel bits, the scratch registers are set to
406 * the following known-to-be-safe values:
407 *
408 * r1: restored (global pointer)
409 * r2: cleared
410 * r3: 1 (when returning to user-level)
411 * r8-r11: restored (syscall return value(s))
412 * r12: restored (user-level stack pointer)
413 * r13: restored (user-level thread pointer)
414 * r14: set to __kernel_syscall_via_epc
415 * r15: restored (syscall #)
416 * r16-r17: cleared
417 * r18: user-level b6
418 * r19: cleared
419 * r20: user-level ar.fpsr
420 * r21: user-level b0
421 * r22: cleared
422 * r23: user-level ar.bspstore
423 * r24: user-level ar.rnat
424 * r25: user-level ar.unat
425 * r26: user-level ar.pfs
426 * r27: user-level ar.rsc
427 * r28: user-level ip
428 * r29: user-level psr
429 * r30: user-level cfm
430 * r31: user-level pr
431 * f6-f11: cleared
432 * pr: restored (user-level pr)
433 * b0: restored (user-level rp)
434 * b6: restored
435 * b7: set to __kernel_syscall_via_epc
436 * ar.unat: restored (user-level ar.unat)
437 * ar.pfs: restored (user-level ar.pfs)
438 * ar.rsc: restored (user-level ar.rsc)
439 * ar.rnat: restored (user-level ar.rnat)
440 * ar.bspstore: restored (user-level ar.bspstore)
441 * ar.fpsr: restored (user-level ar.fpsr)
442 * ar.ccv: cleared
443 * ar.csd: cleared
444 * ar.ssd: cleared
445 */
446 GLOBAL_ENTRY(ia64_leave_hypercall)
447 PT_REGS_UNWIND_INFO(0)
448 /*
449 * work.need_resched etc. mustn't get changed by this CPU before it returns to
450 * user- or fsys-mode, hence we disable interrupts early on.
451 *
452 * p6 controls whether current_thread_info()->flags needs to be check for
453 * extra work. We always check for extra work when returning to user-level.
454 * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
455 * is 0. After extra work processing has been completed, execution
456 * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
457 * needs to be redone.
458 */
459 ;;
460 adds r16=PT(R8)+16,r12
461 ;;
462 st8 [r16]=r8
463 ;;
464 //(pUStk) rsm psr.i
465 rsm psr.i
466 cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
467 //(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
468 ;;
469 br.call.sptk.many b0=leave_hypervisor_tail
470 .work_processed_syscall:
471 //clean up bank 1 registers
472 ;;
473 adds r16=PT(R8)+16,r12
474 ;;
475 ld8 r8=[r16]
476 ;;
477 mov r16=r0
478 mov r17=r0
479 mov r18=r0
480 mov r19=r0
481 mov r20=r0
482 mov r21=r0
483 mov r22=r0
484 mov r23=r0
485 mov r24=r0
486 mov r25=r0
487 mov r26=r0
488 mov r27=r0
489 mov r28=r0
490 mov r29=r0
491 mov r30=r0
492 mov r31=r0
493 bsw.0
494 ;;
495 adds r2=PT(LOADRS)+16,r12
496 adds r3=PT(AR_BSPSTORE)+16,r12
497 #ifndef XEN
498 adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
499 ;;
500 (p6) ld4 r31=[r18] // load current_thread_info()->flags
501 #endif
502 ;;
503 ld8 r20=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
504 nop.i 0
505 ;;
506 // mov r16=ar.bsp // M2 get existing backing store pointer
507 ld8 r18=[r2],PT(R9)-PT(B6) // load b6
508 #ifndef XEN
509 (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
510 #endif
511 ;;
512 ld8 r24=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage)
513 #ifndef XEN
514 (p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending?
515 (p6) br.cond.spnt .work_pending_syscall
516 #endif
517 ;;
518 // start restoring the state saved on the kernel stack (struct pt_regs):
519 ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
520 ld8 r11=[r3],PT(CR_IIP)-PT(R11)
521 //(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE!
522 ;;
523 invala // M0|1 invalidate ALAT
524 rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection
525 #ifndef XEN
526 cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs
527 #endif
529 ld8 r31=[r2],32 // M0|1 load cr.ipsr
530 ld8 r30=[r3],16 // M0|1 load cr.iip
531 ;;
532 // ld8 r29=[r2],16 // M0|1 load cr.ifs
533 ld8 r28=[r3],16 // M0|1 load ar.unat
534 //(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
535 ;;
536 ld8 r27=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
537 //(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
538 nop 0
539 ;;
540 ld8 r22=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
541 ld8 r26=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc
542 mov f6=f0 // F clear f6
543 ;;
544 ld8 r25=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage)
545 ld8 r23=[r3],PT(R1)-PT(PR) // M0|1 load predicates
546 mov f7=f0 // F clear f7
547 ;;
548 ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr
549 ld8.fill r1=[r3],16 // M0|1 load r1
550 //(pUStk) mov r17=1 // A
551 ;;
552 //(pUStk) st1 [r14]=r17 // M2|3
553 ld8.fill r13=[r3],16 // M0|1
554 mov f8=f0 // F clear f8
555 ;;
556 ld8.fill r12=[r2] // M0|1 restore r12 (sp)
557 #ifdef XEN
558 ld8.fill r2=[r3] // M0|1
559 #else
560 ld8.fill r15=[r3] // M0|1 restore r15
561 #endif
562 mov b6=r18 // I0 restore b6
563 mov ar.fpsr=r20
564 // addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A
565 mov f9=f0 // F clear f9
566 //(pKStk) br.cond.dpnt.many skip_rbs_switch // B
568 // srlz.d // M0 ensure interruption collection is off (for cover)
569 // shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
570 mov r3=r21
571 cover // B add current frame into dirty partition & set cr.ifs
572 ;;
573 //(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8
574 mov r19=ar.bsp // M2 get new backing store pointer
575 addl r18=IA64_RBS_OFFSET, r3
576 ;;
577 mov r3=r0
578 sub r18=r19,r18 // get byte size of existing "dirty" partition
579 ;;
580 shl r20=r18,16 // set rsc.load
581 mov f10=f0 // F clear f10
582 #ifdef XEN
583 mov r14=r0
584 #else
585 movl r14=__kernel_syscall_via_epc // X
586 #endif
587 ;;
588 mov.m ar.csd=r0 // M2 clear ar.csd
589 mov.m ar.ccv=r0 // M2 clear ar.ccv
590 mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc)
592 mov.m ar.ssd=r0 // M2 clear ar.ssd
593 mov f11=f0 // F clear f11
594 br.cond.sptk.many vmx_rbs_switch // B
595 END(ia64_leave_hypercall)
598 /*
599 * in0: new rr7
600 * in1: virtual address of guest_vhpt
601 * in2: virtual addres of guest shared_info
602 * r8: will contain old rid value
603 */
605 #define PSR_BITS_TO_CLEAR \
606 (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | \
607 IA64_PSR_RT | IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | \
608 IA64_PSR_ED | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_IC)
609 #define PSR_BITS_TO_SET IA64_PSR_BN
611 GLOBAL_ENTRY(__vmx_switch_rr7)
612 // not sure this unwind statement is correct...
613 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1)
614 alloc loc1 = ar.pfs, 4, 7, 0, 0
615 1:{
616 mov r28 = in0 // copy procedure index
617 mov r8 = ip // save ip to compute branch
618 mov loc0 = rp // save rp
619 };;
620 .body
621 movl loc2=PERCPU_ADDR
622 ;;
623 tpa loc2 = loc2 // get physical address of per cpu date
624 tpa r3 = r8 // get physical address of ip
625 dep loc5 = 0,in1,60,4 // get physical address of guest_vhpt
626 dep loc6 = 0,in2,60,4 // get physical address of privregs
627 ;;
628 dep loc6 = 0,loc6,0,IA64_GRANULE_SHIFT
629 // mask granule shift
630 mov loc4 = psr // save psr
631 ;;
632 mov loc3 = ar.rsc // save RSE configuration
633 ;;
634 mov ar.rsc = 0 // put RSE in enforced lazy, LE mode
635 movl r16=PSR_BITS_TO_CLEAR
636 movl r17=PSR_BITS_TO_SET
637 ;;
638 or loc4 = loc4,r17 // add in psr the bits to set
639 ;;
640 andcm r16=loc4,r16 // removes bits to clear from psr
641 br.call.sptk.many rp=ia64_switch_mode_phys
642 1:
643 // now in physical mode with psr.i/ic off so do rr7 switch
644 dep r16=-1,r0,61,3
645 ;;
646 mov rr[r16]=in0
647 ;;
648 srlz.d
649 ;;
651 // re-pin mappings for kernel text and data
652 mov r18=KERNEL_TR_PAGE_SHIFT<<2
653 movl r17=KERNEL_START
654 ;;
655 ptr.i r17,r18
656 ptr.d r17,r18
657 ;;
658 mov cr.itir=r18
659 mov cr.ifa=r17
660 mov r16=IA64_TR_KERNEL
661 movl r25 = PAGE_KERNEL
662 // r2=KERNEL_TR_PAGE_SHIFT truncated physicall address of ip
663 // = ia64_tpa(ip) & (KERNEL_TR_PAGE_SIZE - 1)
664 dep r2=0,r3,0,KERNEL_TR_PAGE_SHIFT
665 ;;
666 or r24=r2,r25
667 ;;
668 srlz.i
669 ;;
670 itr.i itr[r16]=r24
671 ;;
672 itr.d dtr[r16]=r24
673 ;;
675 // re-pin mapping for stack (current)
676 mov r26=IA64_GRANULE_SHIFT<<2
677 dep r21=0,r13,60,4 // physical address of "current"
678 ;;
679 ptr.d r13,r26
680 or r23=r21,r25 // construct PA | page properties
681 mov cr.itir=r26
682 mov cr.ifa=r13 // VA of next task...
683 mov r18=IA64_TR_CURRENT_STACK
684 ;;
685 itr.d dtr[r18]=r23 // wire in new mapping...
687 // re-pin mappings for per-cpu data
688 movl r22 = PERCPU_ADDR
689 ;;
690 mov r24=IA64_TR_PERCPU_DATA
691 or loc2 = r25,loc2 // construct PA | page properties
692 mov r23=PERCPU_PAGE_SHIFT<<2
693 ;;
694 ptr.d r22,r23
695 ;;
696 mov cr.itir=r23
697 mov cr.ifa=r22
698 ;;
699 itr.d dtr[r24]=loc2 // wire in new mapping...
700 ;;
702 // re-pin mappings for guest_vhpt
703 // unless overlaps with IA64_TR_CURRENT_STACK
704 // r21 = (current physical addr) & (IA64_GRANULE_SIZE - 1)
705 dep r21=0,r21,0,IA64_GRANULE_SHIFT
706 // r17 = (guest_vhpt physical addr) & (IA64_GRANULE_SIZE - 1)
707 dep r17=0,loc5,0,IA64_GRANULE_SHIFT
708 ;;
709 cmp.eq p7,p0=r17,r21 // check overlap with current stack
710 (p7) br.cond.sptk .vhpt_overlaps
711 mov r24=IA64_TR_VHPT
712 ;;
713 or loc5 = r25,loc5 // construct PA | page properties
714 mov r23 = IA64_GRANULE_SHIFT <<2
715 ;;
716 ptr.d in1,r23
717 ;;
718 mov cr.itir=r23
719 mov cr.ifa=in1
720 ;;
721 itr.d dtr[r24]=loc5 // wire in new mapping...
722 ;;
723 .vhpt_overlaps:
725 // r16, r19, r20 are used by
726 // ia64_switch_mode_phys()/ia64_switch_mode_virt()
727 // re-pin mappings for privregs
728 // r21 = (current physical addr) & (IA64_GRANULE_SIZE - 1)
729 // r17 = (guest_vhpt physical addr) & (IA64_GRANULE_SIZE - 1)
730 // loc6 = (privregs physical addr) & (IA64_GRANULE_SIZE - 1)
731 cmp.ne.unc p7,p0=r21,loc6 // check overlap with current stack
732 ;;
733 (p7) cmp.ne.unc p8,p0=r17,loc6 // check overlap with guest_vhpt
734 ;;
735 // loc6 = (((privregs phys) & (IA64_GRANULE_SIZE - 1)) << 2) | PAGE_KERNEL
736 or loc6 = r25,loc6 // construct PA | page properties
737 ;;
738 mov r22=IA64_TR_VPD
739 mov r24=IA64_TR_MAPPED_REGS
740 mov r23=IA64_GRANULE_SHIFT<<2
741 ;;
742 ptr.i in2,r23
743 (p8) ptr.d in2,r23
744 mov cr.itir=r23
745 mov cr.ifa=in2
746 ;;
747 itr.i itr[r22]=loc6 // wire in new mapping...
748 ;;
749 (p8) itr.d dtr[r24]=loc6 // wire in new mapping...
750 ;;
752 // done, switch back to virtual and return
753 mov r16=loc4 // r16= original psr
754 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
755 mov ar.pfs = loc1
756 mov rp = loc0
757 ;;
758 mov ar.rsc=loc3 // restore RSE configuration
759 srlz.d // seralize restoration of psr.l
760 br.ret.sptk.many rp
761 END(__vmx_switch_rr7)