ia64/xen-unstable

view xen/arch/x86/hvm/svm/svm.c @ 9382:e995d090bba9

SVM patch to fix problem with instruction decode.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Mar 22 10:35:35 2006 +0100 (2006-03-22)
parents 760f9149dbaa
children b4769816a409
line source
1 /*
2 * svm.c: handling SVM architecture-related VM exits
3 * Copyright (c) 2004, Intel Corporation.
4 * Copyright (c) 2005, AMD 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 */
21 #include <xen/config.h>
22 #include <xen/init.h>
23 #include <xen/lib.h>
24 #include <xen/trace.h>
25 #include <xen/sched.h>
26 #include <xen/irq.h>
27 #include <xen/softirq.h>
28 #include <asm/current.h>
29 #include <asm/io.h>
30 #include <asm/shadow.h>
31 #include <asm/regs.h>
32 #include <asm/cpufeature.h>
33 #include <asm/processor.h>
34 #include <asm/types.h>
35 #include <asm/msr.h>
36 #include <asm/spinlock.h>
37 #include <asm/hvm/hvm.h>
38 #include <asm/hvm/support.h>
39 #include <asm/hvm/io.h>
40 #include <asm/hvm/svm/svm.h>
41 #include <asm/hvm/svm/vmcb.h>
42 #include <asm/hvm/svm/emulate.h>
43 #include <asm/hvm/svm/vmmcall.h>
44 #include <asm/hvm/svm/intr.h>
45 #include <asm/shadow.h>
46 #if CONFIG_PAGING_LEVELS >= 3
47 #include <asm/shadow_64.h>
48 #endif
49 #include <public/sched.h>
50 #include <public/hvm/ioreq.h>
52 #define SVM_EXTRA_DEBUG
54 #ifdef TRACE_BUFFER
55 static unsigned long trace_values[NR_CPUS][4];
56 #define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
57 #else
58 #define TRACE_VMEXIT(index,value) ((void)0)
59 #endif
61 /* Useful define */
62 #define MAX_INST_SIZE 15
64 /*
65 * External functions, etc. We should move these to some suitable header file(s) */
67 extern void do_nmi(struct cpu_user_regs *, unsigned long);
68 extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
69 int inst_len);
70 extern asmlinkage void do_IRQ(struct cpu_user_regs *);
71 extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
72 unsigned long count, int size, long value, int dir, int pvalid);
73 extern int svm_instrlen(struct cpu_user_regs *regs, int mode);
74 extern void svm_dump_inst(unsigned long eip);
75 extern int svm_dbg_on;
76 void svm_manual_event_injection32(struct vcpu *v, struct cpu_user_regs *regs,
77 int vector, int has_code);
78 void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
80 static void svm_relinquish_guest_resources(struct domain *d);
82 static struct asid_pool ASIDpool[NR_CPUS];
84 /*
85 * Initializes the POOL of ASID used by the guests per core.
86 */
87 void asidpool_init( int core )
88 {
89 int i;
90 ASIDpool[core].asid_lock = SPIN_LOCK_UNLOCKED;
91 spin_lock(&ASIDpool[core].asid_lock);
92 /* Host ASID is always in use */
93 ASIDpool[core].asid[INITIAL_ASID] = ASID_INUSE;
94 for( i=1; i<ASID_MAX; i++ )
95 {
96 ASIDpool[core].asid[i] = ASID_AVAILABLE;
97 }
98 spin_unlock(&ASIDpool[core].asid_lock);
99 }
102 /* internal function to get the next available ASID */
103 static int asidpool_fetch_next( struct vmcb_struct *vmcb, int core )
104 {
105 int i;
106 for( i = 1; i < ASID_MAX; i++ )
107 {
108 if( ASIDpool[core].asid[i] == ASID_AVAILABLE )
109 {
110 vmcb->guest_asid = i;
111 ASIDpool[core].asid[i] = ASID_INUSE;
112 return i;
113 }
114 }
115 return -1;
116 }
119 /*
120 * This functions assigns on the passed VMCB, the next
121 * available ASID number. If none are available, the
122 * TLB flush flag is set, and all retireds ASID
123 * are made available.
124 *
125 * Returns: 1 -- sucess;
126 * 0 -- failure -- no more ASID numbers
127 * available.
128 */
129 int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
130 int oldcore, int newcore )
131 {
132 int i;
133 int res = 1;
134 static unsigned long cnt=0;
136 spin_lock(&ASIDpool[oldcore].asid_lock);
137 if( retire_current && vmcb->guest_asid ) {
138 ASIDpool[oldcore].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
139 }
140 spin_unlock(&ASIDpool[oldcore].asid_lock);
141 spin_lock(&ASIDpool[newcore].asid_lock);
142 if( asidpool_fetch_next( vmcb, newcore ) < 0 ) {
143 if (svm_dbg_on)
144 printk( "SVM: tlb(%ld)\n", cnt++ );
145 /* FLUSH the TLB and all retired slots are made available */
146 vmcb->tlb_control = 1;
147 for( i = 1; i < ASID_MAX; i++ ) {
148 if( ASIDpool[newcore].asid[i] == ASID_RETIRED ) {
149 ASIDpool[newcore].asid[i] = ASID_AVAILABLE;
150 }
151 }
152 /* Get the First slot available */
153 res = asidpool_fetch_next( vmcb, newcore ) > 0;
154 }
155 spin_unlock(&ASIDpool[newcore].asid_lock);
156 return res;
157 }
159 void asidpool_retire( struct vmcb_struct *vmcb, int core )
160 {
161 spin_lock(&ASIDpool[core].asid_lock);
162 if( vmcb->guest_asid ) {
163 ASIDpool[core].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
164 }
165 spin_unlock(&ASIDpool[core].asid_lock);
166 }
168 static inline void svm_inject_exception(struct vmcb_struct *vmcb,
169 int trap, int ev, int error_code)
170 {
171 eventinj_t event;
173 event.bytes = 0;
174 event.fields.v = 1;
175 event.fields.type = EVENTTYPE_EXCEPTION;
176 event.fields.vector = trap;
177 event.fields.ev = ev;
178 event.fields.errorcode = error_code;
180 ASSERT(vmcb->eventinj.fields.v == 0);
182 vmcb->eventinj = event;
183 }
185 void stop_svm(void)
186 {
187 u32 eax, edx;
189 /* We turn off the EFER_SVME bit. */
190 rdmsr(MSR_EFER, eax, edx);
191 eax &= ~EFER_SVME;
192 wrmsr(MSR_EFER, eax, edx);
194 printk("AMD SVM Extension is disabled.\n");
195 }
197 int svm_initialize_guest_resources(struct vcpu *v)
198 {
199 svm_final_setup_guest(v);
200 return 1;
201 }
203 static void svm_store_cpu_guest_regs(
204 struct vcpu *v, struct cpu_user_regs *regs)
205 {
206 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
208 #if defined (__x86_64__)
209 regs->rip = vmcb->rip;
210 regs->rsp = vmcb->rsp;
211 regs->rflags = vmcb->rflags;
212 regs->cs = vmcb->cs.sel;
213 regs->ds = vmcb->ds.sel;
214 regs->es = vmcb->es.sel;
215 regs->ss = vmcb->ss.sel;
216 regs->gs = vmcb->gs.sel;
217 regs->fs = vmcb->fs.sel;
218 #elif defined (__i386__)
219 regs->eip = vmcb->rip;
220 regs->esp = vmcb->rsp;
221 regs->eflags = vmcb->rflags;
222 regs->cs = vmcb->cs.sel;
223 regs->ds = vmcb->ds.sel;
224 regs->es = vmcb->es.sel;
225 regs->ss = vmcb->ss.sel;
226 regs->gs = vmcb->gs.sel;
227 regs->fs = vmcb->fs.sel;
228 #endif
229 }
231 static void svm_load_cpu_guest_regs(
232 struct vcpu *v, struct cpu_user_regs *regs)
233 {
234 svm_load_cpu_user_regs(v, regs);
235 }
237 #define IS_CANO_ADDRESS(add) 1
239 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
240 {
241 u64 msr_content = 0;
242 struct vcpu *vc = current;
243 // struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
244 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
246 switch (regs->ecx)
247 {
248 case MSR_EFER:
249 // msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
250 msr_content = vmcb->efer;
251 msr_content &= ~EFER_SVME;
252 break;
254 case MSR_FS_BASE:
255 msr_content = vmcb->fs.base;
256 break;
258 case MSR_GS_BASE:
259 msr_content = vmcb->gs.base;
260 break;
262 case MSR_SHADOW_GS_BASE:
263 msr_content = vmcb->kerngsbase;
264 break;
266 case MSR_STAR:
267 msr_content = vmcb->star;
268 break;
270 case MSR_LSTAR:
271 msr_content = vmcb->lstar;
272 break;
274 case MSR_CSTAR:
275 msr_content = vmcb->cstar;
276 break;
278 case MSR_SYSCALL_MASK:
279 msr_content = vmcb->sfmask;
280 break;
282 default:
283 return 0;
284 }
286 HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %"PRIx64"\n",
287 msr_content);
289 regs->eax = msr_content & 0xffffffff;
290 regs->edx = msr_content >> 32;
291 return 1;
292 }
294 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
295 {
296 u64 msr_content = regs->eax | ((u64)regs->edx << 32);
297 struct vcpu *vc = current;
298 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
300 HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx "
301 "msr_content %"PRIx64"\n",
302 (unsigned long)regs->ecx, msr_content);
304 switch (regs->ecx)
305 {
306 case MSR_EFER:
307 #ifdef __x86_64__
308 if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
309 &vc->arch.hvm_svm.cpu_state))
310 {
311 if (test_bit(SVM_CPU_STATE_PG_ENABLED, &vc->arch.hvm_svm.cpu_state)
312 || !test_bit(SVM_CPU_STATE_PAE_ENABLED,
313 &vc->arch.hvm_svm.cpu_state))
314 {
315 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
316 }
317 }
319 if (msr_content & EFER_LME)
320 set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
322 /* We have already recorded that we want LME, so it will be set
323 * next time CR0 gets updated. So we clear that bit and continue.
324 */
325 if ((msr_content ^ vmcb->efer) & EFER_LME)
326 msr_content &= ~EFER_LME;
327 /* No update for LME/LMA since it have no effect */
328 #endif
329 vmcb->efer = msr_content | EFER_SVME;
330 break;
332 case MSR_FS_BASE:
333 case MSR_GS_BASE:
334 if (!(SVM_LONG_GUEST(vc)))
335 domain_crash_synchronous();
337 if (!IS_CANO_ADDRESS(msr_content))
338 {
339 HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
340 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
341 }
343 if (regs->ecx == MSR_FS_BASE)
344 vmcb->fs.base = msr_content;
345 else
346 vmcb->gs.base = msr_content;
347 break;
349 case MSR_SHADOW_GS_BASE:
350 vmcb->kerngsbase = msr_content;
351 break;
353 case MSR_STAR:
354 vmcb->star = msr_content;
355 break;
357 case MSR_LSTAR:
358 vmcb->lstar = msr_content;
359 break;
361 case MSR_CSTAR:
362 vmcb->cstar = msr_content;
363 break;
365 case MSR_SYSCALL_MASK:
366 vmcb->sfmask = msr_content;
367 break;
369 default:
370 return 0;
371 }
372 return 1;
373 }
375 void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
376 {
377 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
379 crs[0] = vmcb->cr0;
380 crs[3] = vmcb->cr3;
381 crs[4] = vmcb->cr4;
382 }
384 void svm_modify_guest_state(struct vcpu *v)
385 {
386 svm_modify_vmcb(v, &v->arch.guest_context.user_regs);
387 }
389 int svm_realmode(struct vcpu *v)
390 {
391 unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
392 unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
394 return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
395 }
397 int svm_instruction_length(struct vcpu *v)
398 {
399 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
400 unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
401 /* check which operating mode the guest is running */
402 if( vmcb->efer & EFER_LMA )
403 mode = vmcb->cs.attributes.fields.l ? 8 : 4;
404 else
405 mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
406 return svm_instrlen(guest_cpu_user_regs(), mode);
407 }
409 unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
410 {
411 switch ( num )
412 {
413 case 0:
414 return v->arch.hvm_svm.cpu_shadow_cr0;
415 case 2:
416 return v->arch.hvm_svm.cpu_cr2;
417 case 3:
418 return v->arch.hvm_svm.cpu_cr3;
419 default:
420 BUG();
421 }
422 return 0; /* dummy */
423 }
425 int start_svm(void)
426 {
427 u32 eax, ecx, edx;
429 /* Xen does not fill x86_capability words except 0. */
430 ecx = cpuid_ecx(0x80000001);
431 boot_cpu_data.x86_capability[5] = ecx;
433 if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
434 return 0;
436 rdmsr(MSR_EFER, eax, edx);
437 eax |= EFER_SVME;
438 wrmsr(MSR_EFER, eax, edx);
439 asidpool_init(smp_processor_id());
440 printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
442 /* Setup HVM interfaces */
443 hvm_funcs.disable = stop_svm;
445 hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
446 hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
448 hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
449 hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
451 hvm_funcs.store_cpu_guest_ctrl_regs = svm_store_cpu_guest_ctrl_regs;
452 hvm_funcs.modify_guest_state = svm_modify_guest_state;
454 hvm_funcs.realmode = svm_realmode;
455 hvm_funcs.paging_enabled = svm_paging_enabled;
456 hvm_funcs.instruction_length = svm_instruction_length;
457 hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
459 hvm_enabled = 1;
461 return 1;
462 }
464 int svm_dbg_on = 0;
466 static inline int svm_do_debugout(unsigned long exit_code)
467 {
468 int i;
470 static unsigned long counter = 0;
471 static unsigned long works[] =
472 {
473 VMEXIT_IOIO,
474 VMEXIT_HLT,
475 VMEXIT_CPUID,
476 VMEXIT_DR0_READ,
477 VMEXIT_DR1_READ,
478 VMEXIT_DR2_READ,
479 VMEXIT_DR3_READ,
480 VMEXIT_DR6_READ,
481 VMEXIT_DR7_READ,
482 VMEXIT_DR0_WRITE,
483 VMEXIT_DR1_WRITE,
484 VMEXIT_DR2_WRITE,
485 VMEXIT_DR3_WRITE,
486 VMEXIT_CR0_READ,
487 VMEXIT_CR0_WRITE,
488 VMEXIT_CR3_READ,
489 VMEXIT_CR4_READ,
490 VMEXIT_MSR,
491 VMEXIT_CR0_WRITE,
492 VMEXIT_CR3_WRITE,
493 VMEXIT_CR4_WRITE,
494 VMEXIT_EXCEPTION_PF,
495 VMEXIT_INTR,
496 VMEXIT_INVLPG,
497 VMEXIT_EXCEPTION_NM
498 };
501 #if 0
502 if (svm_dbg_on && exit_code != 0x7B)
503 return 1;
504 #endif
506 counter++;
508 #if 0
509 if ((exit_code == 0x4E
510 || exit_code == VMEXIT_CR0_READ
511 || exit_code == VMEXIT_CR0_WRITE)
512 && counter < 200000)
513 return 0;
515 if ((exit_code == 0x4E) && counter < 500000)
516 return 0;
517 #endif
519 for (i = 0; i < sizeof(works) / sizeof(works[0]); i++)
520 if (exit_code == works[i])
521 return 0;
523 return 1;
524 }
527 void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
528 {
529 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
531 ASSERT(vmcb);
533 ctxt->eax = vmcb->rax;
534 ctxt->ss = vmcb->ss.sel;
535 ctxt->esp = vmcb->rsp;
536 ctxt->eflags = vmcb->rflags;
537 ctxt->cs = vmcb->cs.sel;
538 ctxt->eip = vmcb->rip;
540 ctxt->gs = vmcb->gs.sel;
541 ctxt->fs = vmcb->fs.sel;
542 ctxt->es = vmcb->es.sel;
543 ctxt->ds = vmcb->ds.sel;
544 }
546 #if defined (__x86_64__)
547 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v )
548 {
549 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
551 regs->rip = vmcb->rip;
552 regs->rsp = vmcb->rsp;
553 regs->rflags = vmcb->rflags;
554 regs->cs = vmcb->cs.sel;
555 regs->ds = vmcb->ds.sel;
556 regs->es = vmcb->es.sel;
557 regs->ss = vmcb->ss.sel;
558 }
559 #elif defined (__i386__)
560 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
561 {
562 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
564 regs->eip = vmcb->rip;
565 regs->esp = vmcb->rsp;
566 regs->eflags = vmcb->rflags;
567 regs->cs = vmcb->cs.sel;
568 regs->ds = vmcb->ds.sel;
569 regs->es = vmcb->es.sel;
570 regs->ss = vmcb->ss.sel;
571 }
572 #endif
574 /* XXX Use svm_load_cpu_guest_regs instead */
575 #if defined (__i386__)
576 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
577 {
578 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
579 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
581 /* Write the guest register value into VMCB */
582 vmcb->rax = regs->eax;
583 vmcb->ss.sel = regs->ss;
584 vmcb->rsp = regs->esp;
585 vmcb->rflags = regs->eflags;
586 vmcb->cs.sel = regs->cs;
587 vmcb->rip = regs->eip;
588 if (regs->eflags & EF_TF)
589 *intercepts |= EXCEPTION_BITMAP_DB;
590 else
591 *intercepts &= ~EXCEPTION_BITMAP_DB;
592 }
593 #else /* (__i386__) */
594 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
595 {
596 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
597 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
599 /* Write the guest register value into VMCB */
600 vmcb->rax = regs->rax;
601 vmcb->ss.sel = regs->ss;
602 vmcb->rsp = regs->rsp;
603 vmcb->rflags = regs->rflags;
604 vmcb->cs.sel = regs->cs;
605 vmcb->rip = regs->rip;
606 if (regs->rflags & EF_TF)
607 *intercepts |= EXCEPTION_BITMAP_DB;
608 else
609 *intercepts &= ~EXCEPTION_BITMAP_DB;
610 }
611 #endif /* !(__i386__) */
613 int svm_paging_enabled(struct vcpu *v)
614 {
615 unsigned long cr0;
617 cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
619 return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
620 }
623 /* Make sure that xen intercepts any FP accesses from current */
624 void svm_stts(struct vcpu *v)
625 {
626 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
628 /* FPU state already dirty? Then no need to setup_fpu() lazily. */
629 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
630 return;
632 /*
633 * If the guest does not have TS enabled then we must cause and handle an
634 * exception on first use of the FPU. If the guest *does* have TS enabled
635 * then this is not necessary: no FPU activity can occur until the guest
636 * clears CR0.TS, and we will initialise the FPU when that happens.
637 */
638 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
639 {
640 v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
641 vmcb->cr0 |= X86_CR0_TS;
642 }
643 }
645 static void arch_svm_do_launch(struct vcpu *v)
646 {
647 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
648 int error;
650 #if 0
651 if (svm_dbg_on)
652 printk("Do launch\n");
653 #endif
654 error = construct_vmcb(&v->arch.hvm_svm, regs);
655 if ( error < 0 )
656 {
657 if (v->vcpu_id == 0) {
658 printk("Failed to construct a new VMCB for BSP.\n");
659 } else {
660 printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
661 }
662 domain_crash_synchronous();
663 }
665 svm_do_launch(v);
666 #if 0
667 if (svm_dbg_on)
668 svm_dump_host_regs(__func__);
669 #endif
670 reset_stack_and_jump(svm_asm_do_launch);
671 }
673 static void svm_ctxt_switch_from(struct vcpu *v)
674 {
675 }
677 static void svm_ctxt_switch_to(struct vcpu *v)
678 {
679 }
681 void svm_final_setup_guest(struct vcpu *v)
682 {
683 v->arch.schedule_tail = arch_svm_do_launch;
684 v->arch.ctxt_switch_from = svm_ctxt_switch_from;
685 v->arch.ctxt_switch_to = svm_ctxt_switch_to;
687 if (v == v->domain->vcpu[0])
688 {
689 struct domain *d = v->domain;
690 struct vcpu *vc;
692 /* Initialize monitor page table */
693 for_each_vcpu(d, vc)
694 vc->arch.monitor_table = mk_pagetable(0);
696 /*
697 * Required to do this once per domain
698 * TODO: add a seperate function to do these.
699 */
700 memset(&d->shared_info->evtchn_mask[0], 0xff,
701 sizeof(d->shared_info->evtchn_mask));
703 /*
704 * Put the domain in shadow mode even though we're going to be using
705 * the shared 1:1 page table initially. It shouldn't hurt
706 */
707 shadow_mode_enable(d,
708 SHM_enable|SHM_refcounts|
709 SHM_translate|SHM_external|SHM_wr_pt_pte);
710 }
711 }
714 static void svm_relinquish_guest_resources(struct domain *d)
715 {
716 extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
717 struct vcpu *v;
719 for_each_vcpu ( d, v )
720 {
721 #if 0
722 /* Memory leak by not freeing this. XXXKAF: *Why* is not per core?? */
723 free_host_save_area(v->arch.hvm_svm.host_save_area);
724 #endif
726 destroy_vmcb(&v->arch.hvm_svm);
727 free_monitor_pagetable(v);
728 kill_timer(&v->arch.hvm_svm.hlt_timer);
729 if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
730 {
731 kill_timer( &(VLAPIC(v)->vlapic_timer) );
732 xfree(VLAPIC(v));
733 }
734 }
736 kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
738 if ( d->arch.hvm_domain.shared_page_va )
739 unmap_domain_page_global(
740 (void *)d->arch.hvm_domain.shared_page_va);
742 shadow_direct_map_clean(d);
743 }
746 void arch_svm_do_resume(struct vcpu *v)
747 {
748 /* pinning VCPU to a different core? */
749 if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
750 svm_do_resume( v );
751 reset_stack_and_jump( svm_asm_do_resume );
752 }
753 else {
754 printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() );
755 v->arch.hvm_svm.launch_core = smp_processor_id();
756 svm_migrate_timers( v );
757 svm_do_resume( v );
758 reset_stack_and_jump( svm_asm_do_resume );
759 }
760 }
763 void svm_migrate_timers(struct vcpu *v)
764 {
765 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
767 migrate_timer( &vpit->pit_timer, v->processor );
768 migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
769 if ( hvm_apic_support(v->domain) && VLAPIC( v ))
770 migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
771 }
774 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
775 {
776 struct vcpu *v = current;
777 unsigned long eip;
778 unsigned long gpa; /* FIXME: PAE */
779 int result;
780 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
782 ASSERT(vmcb);
784 //#if HVM_DEBUG
785 eip = vmcb->rip;
786 HVM_DBG_LOG(DBG_LEVEL_VMMU,
787 "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
788 va, eip, (unsigned long)regs->error_code);
789 //#endif
791 if ( !svm_paging_enabled(v) )
792 {
793 if ( shadow_direct_map_fault(va, regs) )
794 return 1;
796 handle_mmio(va, va);
797 TRACE_VMEXIT(2,2);
798 return 1;
799 }
802 gpa = gva_to_gpa(va);
804 /* Use 1:1 page table to identify MMIO address space */
805 if (mmio_space(gpa))
806 {
807 /* No support for APIC */
808 if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
809 {
810 int inst_len;
811 inst_len = svm_instruction_length(v);
812 if (inst_len == -1)
813 {
814 printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
815 domain_crash_synchronous();
816 }
818 __update_guest_eip(vmcb, inst_len);
820 return 1;
821 }
823 TRACE_VMEXIT (2,2);
824 handle_mmio(va, gpa);
826 return 1;
827 }
829 result = shadow_fault(va, regs);
831 if( result ) {
832 /* Let's make sure that the Guest TLB is flushed */
833 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
834 }
836 TRACE_VMEXIT (2,result);
838 return result;
839 }
842 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
843 {
844 struct vcpu *v = current;
846 setup_fpu(v);
847 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
849 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
850 vmcb->cr0 &= ~X86_CR0_TS;
851 }
854 static void svm_do_general_protection_fault(struct vcpu *v,
855 struct cpu_user_regs *regs)
856 {
857 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
858 unsigned long eip, error_code;
860 ASSERT(vmcb);
862 eip = vmcb->rip;
863 error_code = vmcb->exitinfo1;
865 if (vmcb->idtr.limit == 0) {
866 printf("Huh? We got a GP Fault with an invalid IDTR!\n");
867 svm_dump_vmcb(__func__, vmcb);
868 svm_dump_regs(__func__, regs);
869 svm_dump_inst(vmcb->rip);
870 __hvm_bug(regs);
871 }
873 HVM_DBG_LOG(DBG_LEVEL_1,
874 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
875 eip, error_code);
877 HVM_DBG_LOG(DBG_LEVEL_1,
878 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
879 (unsigned long)regs->eax, (unsigned long)regs->ebx,
880 (unsigned long)regs->ecx, (unsigned long)regs->edx,
881 (unsigned long)regs->esi, (unsigned long)regs->edi);
884 /* Reflect it back into the guest */
885 svm_inject_exception(vmcb, TRAP_gp_fault, 1, error_code);
886 }
888 /* Reserved bits: [31:14], [12:1] */
889 #define SVM_VCPU_CPUID_L1_RESERVED 0xffffdffe
891 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
892 struct cpu_user_regs *regs)
893 {
894 unsigned int eax, ebx, ecx, edx;
895 unsigned long eip;
896 struct vcpu *v = current;
897 int inst_len;
899 ASSERT(vmcb);
901 eip = vmcb->rip;
903 HVM_DBG_LOG(DBG_LEVEL_1,
904 "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
905 " (esi) %lx, (edi) %lx",
906 (unsigned long)regs->eax, (unsigned long)regs->ebx,
907 (unsigned long)regs->ecx, (unsigned long)regs->edx,
908 (unsigned long)regs->esi, (unsigned long)regs->edi);
910 cpuid(input, &eax, &ebx, &ecx, &edx);
912 if (input == 1)
913 {
914 if ( hvm_apic_support(v->domain) &&
915 !vlapic_global_enabled((VLAPIC(v))) )
916 clear_bit(X86_FEATURE_APIC, &edx);
918 #if CONFIG_PAGING_LEVELS < 3
919 clear_bit(X86_FEATURE_PAE, &edx);
920 clear_bit(X86_FEATURE_PSE, &edx);
921 clear_bit(X86_FEATURE_PSE36, &edx);
922 #else
923 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
924 {
925 if ( !v->domain->arch.hvm_domain.pae_enabled )
926 clear_bit(X86_FEATURE_PAE, &edx);
927 clear_bit(X86_FEATURE_PSE, &edx);
928 clear_bit(X86_FEATURE_PSE36, &edx);
929 }
930 #endif
932 /* Clear out reserved bits. */
933 ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
934 clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
935 }
936 #ifdef __i386__
937 else if ( input == 0x80000001 )
938 {
939 /* Mask feature for Intel ia32e or AMD long mode. */
940 clear_bit(X86_FEATURE_LM & 31, &edx);
941 }
942 #endif
944 regs->eax = (unsigned long)eax;
945 regs->ebx = (unsigned long)ebx;
946 regs->ecx = (unsigned long)ecx;
947 regs->edx = (unsigned long)edx;
949 HVM_DBG_LOG(DBG_LEVEL_1,
950 "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
951 "ebx=%x, ecx=%x, edx=%x",
952 eip, input, eax, ebx, ecx, edx);
954 inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
955 ASSERT(inst_len > 0);
956 __update_guest_eip(vmcb, inst_len);
957 }
960 static inline unsigned long *get_reg_p(unsigned int gpreg,
961 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
962 {
963 unsigned long *reg_p = NULL;
964 switch (gpreg)
965 {
966 case SVM_REG_EAX:
967 reg_p = (unsigned long *)&regs->eax;
968 break;
969 case SVM_REG_EBX:
970 reg_p = (unsigned long *)&regs->ebx;
971 break;
972 case SVM_REG_ECX:
973 reg_p = (unsigned long *)&regs->ecx;
974 break;
975 case SVM_REG_EDX:
976 reg_p = (unsigned long *)&regs->edx;
977 break;
978 case SVM_REG_EDI:
979 reg_p = (unsigned long *)&regs->edi;
980 break;
981 case SVM_REG_ESI:
982 reg_p = (unsigned long *)&regs->esi;
983 break;
984 case SVM_REG_EBP:
985 reg_p = (unsigned long *)&regs->ebp;
986 break;
987 case SVM_REG_ESP:
988 reg_p = (unsigned long *)&vmcb->rsp;
989 break;
990 #if __x86_64__
991 case SVM_REG_R8:
992 reg_p = (unsigned long *)&regs->r8;
993 break;
994 case SVM_REG_R9:
995 reg_p = (unsigned long *)&regs->r9;
996 break;
997 case SVM_REG_R10:
998 reg_p = (unsigned long *)&regs->r10;
999 break;
1000 case SVM_REG_R11:
1001 reg_p = (unsigned long *)&regs->r11;
1002 break;
1003 case SVM_REG_R12:
1004 reg_p = (unsigned long *)&regs->r12;
1005 break;
1006 case SVM_REG_R13:
1007 reg_p = (unsigned long *)&regs->r13;
1008 break;
1009 case SVM_REG_R14:
1010 reg_p = (unsigned long *)&regs->r14;
1011 break;
1012 case SVM_REG_R15:
1013 reg_p = (unsigned long *)&regs->r15;
1014 break;
1015 #endif
1016 default:
1017 BUG();
1020 return reg_p;
1024 static inline unsigned long get_reg(unsigned int gpreg,
1025 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1027 unsigned long *gp;
1028 gp = get_reg_p(gpreg, regs, vmcb);
1029 return *gp;
1033 static inline void set_reg(unsigned int gpreg, unsigned long value,
1034 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1036 unsigned long *gp;
1037 gp = get_reg_p(gpreg, regs, vmcb);
1038 *gp = value;
1042 static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
1043 struct cpu_user_regs *regs)
1045 unsigned long *reg_p = 0;
1046 unsigned int gpreg = 0;
1047 unsigned long eip;
1048 int inst_len;
1049 int index;
1050 struct vmcb_struct *vmcb;
1051 u8 buffer[MAX_INST_LEN];
1052 u8 prefix = 0;
1054 vmcb = v->arch.hvm_svm.vmcb;
1056 ASSERT(vmcb);
1058 eip = vmcb->rip;
1059 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1060 index = skip_prefix_bytes(buffer, sizeof(buffer));
1062 ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
1064 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
1065 prefix = buffer[index-1];
1067 gpreg = decode_src_reg(prefix, buffer[index + 2]);
1068 ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
1070 HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
1071 eip, reg, gpreg);
1073 reg_p = get_reg_p(gpreg, regs, vmcb);
1075 switch (type)
1077 case TYPE_MOV_TO_DR:
1078 inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
1079 v->arch.guest_context.debugreg[reg] = *reg_p;
1080 break;
1081 case TYPE_MOV_FROM_DR:
1082 inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
1083 *reg_p = v->arch.guest_context.debugreg[reg];
1084 break;
1085 default:
1086 __hvm_bug(regs);
1087 break;
1089 ASSERT(inst_len > 0);
1090 __update_guest_eip(vmcb, inst_len);
1094 static unsigned int check_for_null_selector(struct vmcb_struct *vmcb,
1095 unsigned int dir, unsigned long *base, unsigned int real)
1098 unsigned char inst[MAX_INST_LEN];
1099 segment_selector_t seg;
1100 int i;
1102 memset(inst, 0, MAX_INST_LEN);
1103 if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
1104 != MAX_INST_LEN)
1106 printk("check_for_null_selector: get guest instruction failed\n");
1107 domain_crash_synchronous();
1110 for (i = 0; i < MAX_INST_LEN; i++)
1112 switch (inst[i])
1114 case 0xf3: /* REPZ */
1115 case 0xf2: /* REPNZ */
1116 case 0xf0: /* LOCK */
1117 case 0x66: /* data32 */
1118 case 0x67: /* addr32 */
1119 #if __x86_64__
1120 /* REX prefixes */
1121 case 0x40:
1122 case 0x41:
1123 case 0x42:
1124 case 0x43:
1125 case 0x44:
1126 case 0x45:
1127 case 0x46:
1128 case 0x47:
1130 case 0x48:
1131 case 0x49:
1132 case 0x4a:
1133 case 0x4b:
1134 case 0x4c:
1135 case 0x4d:
1136 case 0x4e:
1137 case 0x4f:
1138 #endif
1139 continue;
1140 case 0x2e: /* CS */
1141 seg = vmcb->cs;
1142 break;
1143 case 0x36: /* SS */
1144 seg = vmcb->ss;
1145 break;
1146 case 0x26: /* ES */
1147 seg = vmcb->es;
1148 break;
1149 case 0x64: /* FS */
1150 seg = vmcb->fs;
1151 break;
1152 case 0x65: /* GS */
1153 seg = vmcb->gs;
1154 break;
1155 case 0x3e: /* DS */
1156 /* FALLTHROUGH */
1157 seg = vmcb->ds;
1158 break;
1159 default:
1160 if (dir == IOREQ_READ)
1161 seg = vmcb->es;
1162 else
1163 seg = vmcb->ds;
1166 /* In real Mode */
1167 if (real)
1168 seg.base = seg.sel << 4;
1170 if (base)
1171 *base = seg.base;
1173 return seg.attributes.fields.p;
1176 ASSERT(0);
1177 return 0;
1181 /* Get the address of INS/OUTS instruction */
1182 static inline unsigned long svm_get_io_address(struct vmcb_struct *vmcb,
1183 struct cpu_user_regs *regs, unsigned int dir, unsigned int real)
1185 unsigned long addr = 0;
1186 unsigned long base = 0;
1188 check_for_null_selector(vmcb, dir, &base, real);
1190 if (dir == IOREQ_WRITE)
1192 if (real)
1193 addr = (regs->esi & 0xFFFF) + base;
1194 else
1195 addr = regs->esi + base;
1197 else
1199 if (real)
1200 addr = (regs->edi & 0xFFFF) + base;
1201 else
1202 addr = regs->edi + base;
1205 return addr;
1209 static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs)
1211 struct mmio_op *mmio_opp;
1212 unsigned long eip, cs, eflags, cr0;
1213 unsigned long port;
1214 unsigned int real, size, dir;
1215 ioio_info_t info;
1217 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1219 ASSERT(vmcb);
1220 mmio_opp = &current->arch.hvm_vcpu.mmio_op;
1221 mmio_opp->instr = INSTR_PIO;
1222 mmio_opp->flags = 0;
1224 eip = vmcb->rip;
1225 cs = vmcb->cs.sel;
1226 eflags = vmcb->rflags;
1228 info.bytes = vmcb->exitinfo1;
1230 port = info.fields.port; /* port used to be addr */
1231 dir = info.fields.type; /* direction */
1232 if (info.fields.sz32)
1233 size = 4;
1234 else if (info.fields.sz16)
1235 size = 2;
1236 else
1237 size = 1;
1239 cr0 = vmcb->cr0;
1240 real = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
1242 HVM_DBG_LOG(DBG_LEVEL_IO,
1243 "svm_io_instruction: port 0x%lx real %d, eip=%lx:%lx, "
1244 "exit_qualification = %lx",
1245 (unsigned long) port, real, cs, eip, (unsigned long)info.bytes);
1246 /* string instruction */
1247 if (info.fields.str)
1249 unsigned long addr, count = 1;
1250 int sign = regs->eflags & EF_DF ? -1 : 1;
1252 /* Need the original rip, here. */
1253 addr = svm_get_io_address(vmcb, regs, dir, real);
1254 /*
1255 * On SVM, the RIP of the intruction following the IN/OUT is saved in
1256 * ExitInfo2
1257 */
1258 vmcb->rip = vmcb->exitinfo2;
1260 /* "rep" prefix */
1261 if (info.fields.rep)
1263 mmio_opp->flags |= REPZ;
1264 count = real ? regs->ecx & 0xFFFF : regs->ecx;
1267 /*
1268 * Handle string pio instructions that cross pages or that
1269 * are unaligned. See the comments in hvm_platform.c/handle_mmio()
1270 */
1271 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
1273 unsigned long value = 0;
1275 mmio_opp->flags |= OVERLAP;
1277 if (dir == IOREQ_WRITE)
1278 hvm_copy(&value, addr, size, HVM_COPY_IN);
1280 send_pio_req(regs, port, 1, size, value, dir, 0);
1282 else
1284 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
1286 if (sign > 0)
1287 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
1288 else
1289 count = (addr & ~PAGE_MASK) / size;
1292 send_pio_req(regs, port, count, size, addr, dir, 1);
1295 else
1297 /*
1298 * On SVM, the RIP of the intruction following the IN/OUT is saved in
1299 * ExitInfo2
1300 */
1301 vmcb->rip = vmcb->exitinfo2;
1303 if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
1304 hvm_print_line(v, regs->eax); /* guest debug output */
1306 send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
1310 static int svm_set_cr0(unsigned long value)
1312 struct vcpu *v = current;
1313 unsigned long mfn;
1314 int paging_enabled;
1315 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1316 unsigned long crn;
1318 ASSERT(vmcb);
1320 /* We don't want to lose PG. ET is reserved and should be always be 1*/
1321 paging_enabled = svm_paging_enabled(v);
1322 value |= X86_CR0_ET;
1323 vmcb->cr0 = value | X86_CR0_PG;
1324 v->arch.hvm_svm.cpu_shadow_cr0 = value;
1326 /* TS cleared? Then initialise FPU now. */
1327 if ( !(value & X86_CR0_TS) )
1329 setup_fpu(v);
1330 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1333 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
1335 if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
1337 /* The guest CR3 must be pointing to the guest physical. */
1338 if (!VALID_MFN(mfn =
1339 get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
1340 || !get_page(mfn_to_page(mfn), v->domain))
1342 printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
1343 domain_crash_synchronous(); /* need to take a clean path */
1346 #if defined(__x86_64__)
1347 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
1348 && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
1349 &v->arch.hvm_svm.cpu_state))
1351 HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
1352 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1355 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
1357 /* Here the PAE is should to be opened */
1358 HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
1359 set_bit(SVM_CPU_STATE_LMA_ENABLED,
1360 &v->arch.hvm_svm.cpu_state);
1361 vmcb->efer |= (EFER_LMA | EFER_LME);
1363 #if CONFIG_PAGING_LEVELS >= 4
1364 if (!shadow_set_guest_paging_levels(v->domain, 4))
1366 printk("Unsupported guest paging levels\n");
1367 domain_crash_synchronous(); /* need to take a clean path */
1369 #endif
1371 else
1372 #endif /* __x86_64__ */
1374 #if CONFIG_PAGING_LEVELS >= 3
1375 if (!shadow_set_guest_paging_levels(v->domain, 2))
1377 printk("Unsupported guest paging levels\n");
1378 domain_crash_synchronous(); /* need to take a clean path */
1380 #endif
1383 /* update CR4's PAE if needed */
1384 crn = vmcb->cr4;
1385 if ((!(crn & X86_CR4_PAE))
1386 && test_bit(SVM_CPU_STATE_PAE_ENABLED,
1387 &v->arch.hvm_svm.cpu_state))
1389 HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
1390 vmcb->cr4 |= X86_CR4_PAE;
1393 /* Now arch.guest_table points to machine physical. */
1394 v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
1395 update_pagetables(v);
1397 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
1398 (unsigned long) (mfn << PAGE_SHIFT));
1400 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1401 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1403 /* arch->shadow_table should hold the next CR3 for shadow */
1404 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
1405 v->arch.hvm_svm.cpu_cr3, mfn);
1408 /*
1409 * SVM implements paged real-mode and when we return to real-mode
1410 * we revert back to the physical mappings that the domain builder
1411 * created.
1412 */
1413 if ((value & X86_CR0_PE) == 0) {
1414 if (value & X86_CR0_PG) {
1415 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1416 return 0;
1419 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1420 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
1423 return 1;
1426 /*
1427 * Read from control registers. CR0 and CR4 are read from the shadow.
1428 */
1429 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
1431 unsigned long value = 0;
1432 struct vcpu *v = current;
1433 struct vmcb_struct *vmcb;
1435 vmcb = v->arch.hvm_svm.vmcb;
1436 ASSERT(vmcb);
1438 switch (cr)
1440 case 0:
1441 value = v->arch.hvm_svm.cpu_shadow_cr0;
1442 break;
1443 case 2:
1444 value = vmcb->cr2;
1445 break;
1446 case 3:
1447 value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
1448 break;
1449 case 4:
1450 value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
1451 break;
1452 case 8:
1453 #if 0
1454 value = vmcb->m_cr8;
1455 #else
1456 ASSERT(0);
1457 #endif
1458 break;
1460 default:
1461 __hvm_bug(regs);
1464 set_reg(gp, value, regs, vmcb);
1466 HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
1470 /*
1471 * Write to control registers
1472 */
1473 static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
1475 unsigned long value;
1476 unsigned long old_cr;
1477 struct vcpu *v = current;
1478 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1480 ASSERT(vmcb);
1482 value = get_reg(gpreg, regs, vmcb);
1484 HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
1485 HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
1487 switch (cr)
1489 case 0:
1490 return svm_set_cr0(value);
1492 case 3:
1494 unsigned long old_base_mfn, mfn;
1496 /* If paging is not enabled yet, simply copy the value to CR3. */
1497 if (!svm_paging_enabled(v)) {
1498 v->arch.hvm_svm.cpu_cr3 = value;
1499 break;
1501 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1503 /* We make a new one if the shadow does not exist. */
1504 if (value == v->arch.hvm_svm.cpu_cr3)
1506 /*
1507 * This is simple TLB flush, implying the guest has
1508 * removed some translation or changed page attributes.
1509 * We simply invalidate the shadow.
1510 */
1511 mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
1512 if (mfn != pagetable_get_pfn(v->arch.guest_table))
1513 __hvm_bug(regs);
1514 shadow_sync_all(v->domain);
1516 else
1518 /*
1519 * If different, make a shadow. Check if the PDBR is valid
1520 * first.
1521 */
1522 HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
1523 if (((value >> PAGE_SHIFT) > v->domain->max_pages)
1524 || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
1525 || !get_page(mfn_to_page(mfn), v->domain))
1527 printk("Invalid CR3 value=%lx\n", value);
1528 domain_crash_synchronous(); /* need to take a clean path */
1531 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1532 v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
1534 if (old_base_mfn)
1535 put_page(mfn_to_page(old_base_mfn));
1537 update_pagetables(v);
1539 /* arch.shadow_table should now hold the next CR3 for shadow*/
1540 v->arch.hvm_svm.cpu_cr3 = value;
1541 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
1542 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1544 break;
1547 case 4:
1548 /* CR4 */
1549 if (value & X86_CR4_PAE) {
1550 set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
1551 } else {
1552 if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
1553 &v->arch.hvm_svm.cpu_state)) {
1554 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1556 clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
1559 old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
1560 v->arch.hvm_svm.cpu_shadow_cr4 = value;
1561 vmcb->cr4 = value | SVM_CR4_HOST_MASK;
1563 /*
1564 * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
1565 * all TLB entries except global entries.
1566 */
1567 if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
1569 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1570 shadow_sync_all(v->domain);
1572 break;
1574 default:
1575 printk("invalid cr: %d\n", cr);
1576 __hvm_bug(regs);
1579 return 1;
1583 #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
1586 static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
1587 struct cpu_user_regs *regs)
1589 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1590 int inst_len = 0;
1591 int index;
1592 unsigned int gpreg;
1593 unsigned long value;
1594 u8 buffer[MAX_INST_LEN];
1595 u8 prefix = 0;
1596 int result = 1;
1597 enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
1598 enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
1599 enum instruction_index match;
1601 ASSERT(vmcb);
1603 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1604 /* get index to first actual instruction byte - as we will need to know where the
1605 * prefix lives later on
1606 */
1607 index = skip_prefix_bytes(buffer, sizeof(buffer));
1609 if (type == TYPE_MOV_TO_CR)
1611 inst_len = __get_instruction_length_from_list(vmcb, list_a,
1612 ARR_SIZE(list_a), &buffer[index], &match);
1614 else
1616 inst_len = __get_instruction_length_from_list(vmcb, list_b,
1617 ARR_SIZE(list_b), &buffer[index], &match);
1620 ASSERT(inst_len > 0);
1622 inst_len += index;
1624 /* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */
1625 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
1626 prefix = buffer[index-1];
1628 HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
1630 switch (match)
1632 case INSTR_MOV2CR:
1633 gpreg = decode_src_reg(prefix, buffer[index+2]);
1634 result = mov_to_cr(gpreg, cr, regs);
1635 break;
1637 case INSTR_MOVCR2:
1638 gpreg = decode_src_reg(prefix, buffer[index+2]);
1639 mov_from_cr(cr, gpreg, regs);
1640 break;
1642 case INSTR_CLTS:
1643 /* TS being cleared means that it's time to restore fpu state. */
1644 setup_fpu(current);
1645 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1646 vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
1647 v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
1648 break;
1650 case INSTR_LMSW:
1651 if (svm_dbg_on)
1652 svm_dump_inst(svm_rip2pointer(vmcb));
1654 gpreg = decode_src_reg(prefix, buffer[index+2]);
1655 value = get_reg(gpreg, regs, vmcb) & 0xF;
1657 if (svm_dbg_on)
1658 printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1659 inst_len);
1661 value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
1663 if (svm_dbg_on)
1664 printk("CR0-LMSW CR0 - New value=%lx\n", value);
1666 result = svm_set_cr0(value);
1667 break;
1669 case INSTR_SMSW:
1670 svm_dump_inst(svm_rip2pointer(vmcb));
1671 value = v->arch.hvm_svm.cpu_shadow_cr0;
1672 gpreg = decode_src_reg(prefix, buffer[index+2]);
1673 set_reg(gpreg, value, regs, vmcb);
1675 if (svm_dbg_on)
1676 printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1677 inst_len);
1678 break;
1680 default:
1681 __hvm_bug(regs);
1682 break;
1685 ASSERT(inst_len);
1687 __update_guest_eip(vmcb, inst_len);
1689 return result;
1692 static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
1694 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1695 int inst_len;
1696 int64_t tsc_sum;
1698 ASSERT(vmcb);
1700 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
1701 "exitinfo = %lx", (unsigned long)regs->ecx,
1702 (unsigned long)regs->eax, (unsigned long)regs->edx,
1703 (unsigned long)vmcb->exitinfo1);
1705 /* is it a read? */
1706 if (vmcb->exitinfo1 == 0)
1708 inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
1710 regs->edx = 0;
1711 switch (regs->ecx)
1713 case MSR_IA32_SYSENTER_CS:
1714 regs->eax = vmcb->sysenter_cs;
1715 break;
1716 case MSR_IA32_SYSENTER_ESP:
1717 regs->eax = vmcb->sysenter_esp;
1718 break;
1719 case MSR_IA32_SYSENTER_EIP:
1720 regs->eax = vmcb->sysenter_eip;
1721 break;
1722 case MSR_IA32_TIME_STAMP_COUNTER:
1723 __asm__ __volatile__("rdtsc" : "=a" (regs->eax), "=d" (regs->edx));
1724 tsc_sum = regs->edx;
1725 tsc_sum = (tsc_sum << 32) + regs->eax;
1726 tsc_sum += (int64_t) vmcb->tsc_offset;
1727 regs->eax = tsc_sum & 0xFFFFFFFF;
1728 regs->edx = (tsc_sum >> 32) & 0xFFFFFFFF;
1729 break;
1730 default:
1731 if (long_mode_do_msr_read(regs))
1732 goto done;
1733 rdmsr_safe(regs->ecx, regs->eax, regs->edx);
1734 break;
1737 else
1739 inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
1741 switch (regs->ecx)
1743 case MSR_IA32_SYSENTER_CS:
1744 vmcb->sysenter_cs = regs->eax;
1745 break;
1746 case MSR_IA32_SYSENTER_ESP:
1747 vmcb->sysenter_esp = regs->eax;
1748 break;
1749 case MSR_IA32_SYSENTER_EIP:
1750 vmcb->sysenter_eip = regs->eax;
1751 break;
1752 default:
1753 long_mode_do_msr_write(regs);
1754 break;
1758 done:
1760 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
1761 "ecx=%lx, eax=%lx, edx=%lx",
1762 (unsigned long)regs->ecx, (unsigned long)regs->eax,
1763 (unsigned long)regs->edx);
1765 __update_guest_eip(vmcb, inst_len);
1769 /*
1770 * Need to use this exit to reschedule
1771 */
1772 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
1774 struct vcpu *v = current;
1775 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
1776 s_time_t next_pit = -1, next_wakeup;
1778 __update_guest_eip(vmcb, 1);
1780 if ( !v->vcpu_id )
1781 next_pit = get_pit_scheduled(v, vpit);
1782 next_wakeup = get_apictime_scheduled(v);
1783 if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
1784 next_wakeup = next_pit;
1785 if ( next_wakeup != - 1 )
1786 set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
1787 /* temporary workaround for 8828/8822 evtchn patches causing SVM failure.
1788 hvm_safe_block();
1789 */
1793 static inline void svm_vmexit_do_mwait(void)
1798 #ifdef XEN_DEBUGGER
1799 static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
1800 struct cpu_user_regs *regs)
1802 regs->eip = vmcb->rip;
1803 regs->esp = vmcb->rsp;
1804 regs->eflags = vmcb->rflags;
1806 regs->xcs = vmcb->cs.sel;
1807 regs->xds = vmcb->ds.sel;
1808 regs->xes = vmcb->es.sel;
1809 regs->xfs = vmcb->fs.sel;
1810 regs->xgs = vmcb->gs.sel;
1811 regs->xss = vmcb->ss.sel;
1815 static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
1817 vmcb->ss.sel = regs->xss;
1818 vmcb->rsp = regs->esp;
1819 vmcb->rflags = regs->eflags;
1820 vmcb->cs.sel = regs->xcs;
1821 vmcb->rip = regs->eip;
1823 vmcb->gs.sel = regs->xgs;
1824 vmcb->fs.sel = regs->xfs;
1825 vmcb->es.sel = regs->xes;
1826 vmcb->ds.sel = regs->xds;
1828 #endif
1831 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
1833 struct vcpu *v = current;
1834 u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
1835 unsigned long g_vaddr;
1836 int inst_len;
1837 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1839 ASSERT(vmcb);
1840 /*
1841 * Unknown how many bytes the invlpg instruction will take. Use the
1842 * maximum instruction length here
1843 */
1844 if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
1846 printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
1847 __hvm_bug(regs);
1850 if (invlpga)
1852 inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
1853 ASSERT(inst_len > 0);
1854 __update_guest_eip(vmcb, inst_len);
1856 /*
1857 * The address is implicit on this instruction At the moment, we don't
1858 * use ecx (ASID) to identify individual guests pages
1859 */
1860 g_vaddr = regs->eax;
1862 else
1864 /* What about multiple prefix codes? */
1865 prefix = (is_prefix(opcode[0])?opcode[0]:0);
1866 inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
1867 ASSERT(inst_len > 0);
1869 inst_len--;
1870 length -= inst_len;
1872 /*
1873 * Decode memory operand of the instruction including ModRM, SIB, and
1874 * displacement to get effecticve address and length in bytes. Assume
1875 * the system in either 32- or 64-bit mode.
1876 */
1877 g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
1878 &opcode[inst_len], &length);
1880 inst_len += length;
1881 __update_guest_eip (vmcb, inst_len);
1884 /* Overkill, we may not this */
1885 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1886 shadow_invlpg(v, g_vaddr);
1890 /*
1891 * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
1892 * 16-bit realmode. Basically, this mimics a processor reset.
1894 * returns 0 on success, non-zero otherwise
1895 */
1896 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
1897 struct cpu_user_regs *regs)
1899 struct vmcb_struct *vmcb;
1901 ASSERT(v);
1902 ASSERT(regs);
1904 vmcb = v->arch.hvm_svm.vmcb;
1906 ASSERT(vmcb);
1908 /* clear the vmcb and user regs */
1909 memset(regs, 0, sizeof(struct cpu_user_regs));
1911 /* VMCB Control */
1912 vmcb->tsc_offset = 0;
1914 /* VMCB State */
1915 vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
1916 v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
1918 vmcb->cr2 = 0;
1919 vmcb->efer = EFER_SVME;
1921 vmcb->cr4 = SVM_CR4_HOST_MASK;
1922 v->arch.hvm_svm.cpu_shadow_cr4 = 0;
1924 /* This will jump to ROMBIOS */
1925 vmcb->rip = 0xFFF0;
1927 /* setup the segment registers and all their hidden states */
1928 vmcb->cs.sel = 0xF000;
1929 vmcb->cs.attributes.bytes = 0x089b;
1930 vmcb->cs.limit = 0xffff;
1931 vmcb->cs.base = 0x000F0000;
1933 vmcb->ss.sel = 0x00;
1934 vmcb->ss.attributes.bytes = 0x0893;
1935 vmcb->ss.limit = 0xffff;
1936 vmcb->ss.base = 0x00;
1938 vmcb->ds.sel = 0x00;
1939 vmcb->ds.attributes.bytes = 0x0893;
1940 vmcb->ds.limit = 0xffff;
1941 vmcb->ds.base = 0x00;
1943 vmcb->es.sel = 0x00;
1944 vmcb->es.attributes.bytes = 0x0893;
1945 vmcb->es.limit = 0xffff;
1946 vmcb->es.base = 0x00;
1948 vmcb->fs.sel = 0x00;
1949 vmcb->fs.attributes.bytes = 0x0893;
1950 vmcb->fs.limit = 0xffff;
1951 vmcb->fs.base = 0x00;
1953 vmcb->gs.sel = 0x00;
1954 vmcb->gs.attributes.bytes = 0x0893;
1955 vmcb->gs.limit = 0xffff;
1956 vmcb->gs.base = 0x00;
1958 vmcb->ldtr.sel = 0x00;
1959 vmcb->ldtr.attributes.bytes = 0x0000;
1960 vmcb->ldtr.limit = 0x0;
1961 vmcb->ldtr.base = 0x00;
1963 vmcb->gdtr.sel = 0x00;
1964 vmcb->gdtr.attributes.bytes = 0x0000;
1965 vmcb->gdtr.limit = 0x0;
1966 vmcb->gdtr.base = 0x00;
1968 vmcb->tr.sel = 0;
1969 vmcb->tr.attributes.bytes = 0;
1970 vmcb->tr.limit = 0x0;
1971 vmcb->tr.base = 0;
1973 vmcb->idtr.sel = 0x00;
1974 vmcb->idtr.attributes.bytes = 0x0000;
1975 vmcb->idtr.limit = 0x3ff;
1976 vmcb->idtr.base = 0x00;
1978 vmcb->rax = 0;
1980 return 0;
1984 /*
1985 * svm_do_vmmcall - SVM VMMCALL handler
1987 * returns 0 on success, non-zero otherwise
1988 */
1989 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
1991 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1992 int inst_len;
1994 ASSERT(vmcb);
1995 ASSERT(regs);
1997 inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
1998 ASSERT(inst_len > 0);
2000 /* VMMCALL sanity check */
2001 if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
2003 printf("VMMCALL CPL check failed\n");
2004 return -1;
2007 /* handle the request */
2008 switch (regs->edi)
2010 case VMMCALL_RESET_TO_REALMODE:
2011 if (svm_do_vmmcall_reset_to_realmode(v, regs))
2013 printf("svm_do_vmmcall_reset_to_realmode() failed\n");
2014 return -1;
2017 /* since we just reset the VMCB, return without adjusting the eip */
2018 return 0;
2019 case VMMCALL_DEBUG:
2020 printf("DEBUG features not implemented yet\n");
2021 break;
2022 default:
2023 break;
2026 hvm_print_line(v, regs->eax); /* provides the current domain */
2028 __update_guest_eip(vmcb, inst_len);
2029 return 0;
2033 void svm_dump_inst(unsigned long eip)
2035 u8 opcode[256];
2036 unsigned long ptr;
2037 int len;
2038 int i;
2040 ptr = eip & ~0xff;
2041 len = 0;
2043 if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
2044 len = sizeof(opcode);
2046 printf("Code bytes around(len=%d) %lx:", len, eip);
2047 for (i = 0; i < len; i++)
2049 if ((i & 0x0f) == 0)
2050 printf("\n%08lx:", ptr+i);
2052 printf("%02x ", opcode[i]);
2055 printf("\n");
2059 void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
2061 struct vcpu *v = current;
2062 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2063 unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
2065 printf("%s: guest registers from %s:\n", __func__, from);
2066 #if defined (__x86_64__)
2067 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
2068 regs->rax, regs->rbx, regs->rcx);
2069 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
2070 regs->rdx, regs->rsi, regs->rdi);
2071 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
2072 regs->rbp, regs->rsp, regs->r8);
2073 printk("r9: %016lx r10: %016lx r11: %016lx\n",
2074 regs->r9, regs->r10, regs->r11);
2075 printk("r12: %016lx r13: %016lx r14: %016lx\n",
2076 regs->r12, regs->r13, regs->r14);
2077 printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
2078 regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
2079 #else
2080 printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
2081 regs->eax, regs->ebx, regs->ecx, regs->edx);
2082 printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
2083 regs->edi, regs->esi, regs->ebp, regs->esp);
2084 printf("%s: guest cr0: %lx\n", __func__,
2085 v->arch.hvm_svm.cpu_shadow_cr0);
2086 printf("guest CR3 = %llx\n", vmcb->cr3);
2087 #endif
2088 printf("%s: pt = %lx\n", __func__, pt);
2092 void svm_dump_host_regs(const char *from)
2094 struct vcpu *v = current;
2095 unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
2096 unsigned long cr3, cr0;
2097 printf("Host registers at %s\n", from);
2099 __asm__ __volatile__ ("\tmov %%cr0,%0\n"
2100 "\tmov %%cr3,%1\n"
2101 : "=r" (cr0), "=r"(cr3));
2102 printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
2105 #ifdef SVM_EXTRA_DEBUG
2106 static char *exit_reasons[] = {
2107 [VMEXIT_CR0_READ] = "CR0_READ",
2108 [VMEXIT_CR1_READ] = "CR1_READ",
2109 [VMEXIT_CR2_READ] = "CR2_READ",
2110 [VMEXIT_CR3_READ] = "CR3_READ",
2111 [VMEXIT_CR4_READ] = "CR4_READ",
2112 [VMEXIT_CR5_READ] = "CR5_READ",
2113 [VMEXIT_CR6_READ] = "CR6_READ",
2114 [VMEXIT_CR7_READ] = "CR7_READ",
2115 [VMEXIT_CR8_READ] = "CR8_READ",
2116 [VMEXIT_CR9_READ] = "CR9_READ",
2117 [VMEXIT_CR10_READ] = "CR10_READ",
2118 [VMEXIT_CR11_READ] = "CR11_READ",
2119 [VMEXIT_CR12_READ] = "CR12_READ",
2120 [VMEXIT_CR13_READ] = "CR13_READ",
2121 [VMEXIT_CR14_READ] = "CR14_READ",
2122 [VMEXIT_CR15_READ] = "CR15_READ",
2123 [VMEXIT_CR0_WRITE] = "CR0_WRITE",
2124 [VMEXIT_CR1_WRITE] = "CR1_WRITE",
2125 [VMEXIT_CR2_WRITE] = "CR2_WRITE",
2126 [VMEXIT_CR3_WRITE] = "CR3_WRITE",
2127 [VMEXIT_CR4_WRITE] = "CR4_WRITE",
2128 [VMEXIT_CR5_WRITE] = "CR5_WRITE",
2129 [VMEXIT_CR6_WRITE] = "CR6_WRITE",
2130 [VMEXIT_CR7_WRITE] = "CR7_WRITE",
2131 [VMEXIT_CR8_WRITE] = "CR8_WRITE",
2132 [VMEXIT_CR9_WRITE] = "CR9_WRITE",
2133 [VMEXIT_CR10_WRITE] = "CR10_WRITE",
2134 [VMEXIT_CR11_WRITE] = "CR11_WRITE",
2135 [VMEXIT_CR12_WRITE] = "CR12_WRITE",
2136 [VMEXIT_CR13_WRITE] = "CR13_WRITE",
2137 [VMEXIT_CR14_WRITE] = "CR14_WRITE",
2138 [VMEXIT_CR15_WRITE] = "CR15_WRITE",
2139 [VMEXIT_DR0_READ] = "DR0_READ",
2140 [VMEXIT_DR1_READ] = "DR1_READ",
2141 [VMEXIT_DR2_READ] = "DR2_READ",
2142 [VMEXIT_DR3_READ] = "DR3_READ",
2143 [VMEXIT_DR4_READ] = "DR4_READ",
2144 [VMEXIT_DR5_READ] = "DR5_READ",
2145 [VMEXIT_DR6_READ] = "DR6_READ",
2146 [VMEXIT_DR7_READ] = "DR7_READ",
2147 [VMEXIT_DR8_READ] = "DR8_READ",
2148 [VMEXIT_DR9_READ] = "DR9_READ",
2149 [VMEXIT_DR10_READ] = "DR10_READ",
2150 [VMEXIT_DR11_READ] = "DR11_READ",
2151 [VMEXIT_DR12_READ] = "DR12_READ",
2152 [VMEXIT_DR13_READ] = "DR13_READ",
2153 [VMEXIT_DR14_READ] = "DR14_READ",
2154 [VMEXIT_DR15_READ] = "DR15_READ",
2155 [VMEXIT_DR0_WRITE] = "DR0_WRITE",
2156 [VMEXIT_DR1_WRITE] = "DR1_WRITE",
2157 [VMEXIT_DR2_WRITE] = "DR2_WRITE",
2158 [VMEXIT_DR3_WRITE] = "DR3_WRITE",
2159 [VMEXIT_DR4_WRITE] = "DR4_WRITE",
2160 [VMEXIT_DR5_WRITE] = "DR5_WRITE",
2161 [VMEXIT_DR6_WRITE] = "DR6_WRITE",
2162 [VMEXIT_DR7_WRITE] = "DR7_WRITE",
2163 [VMEXIT_DR8_WRITE] = "DR8_WRITE",
2164 [VMEXIT_DR9_WRITE] = "DR9_WRITE",
2165 [VMEXIT_DR10_WRITE] = "DR10_WRITE",
2166 [VMEXIT_DR11_WRITE] = "DR11_WRITE",
2167 [VMEXIT_DR12_WRITE] = "DR12_WRITE",
2168 [VMEXIT_DR13_WRITE] = "DR13_WRITE",
2169 [VMEXIT_DR14_WRITE] = "DR14_WRITE",
2170 [VMEXIT_DR15_WRITE] = "DR15_WRITE",
2171 [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
2172 [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
2173 [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
2174 [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
2175 [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
2176 [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
2177 [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
2178 [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
2179 [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
2180 [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
2181 [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
2182 [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
2183 [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
2184 [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
2185 [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
2186 [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
2187 [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
2188 [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
2189 [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
2190 [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
2191 [VMEXIT_INTR] = "INTR",
2192 [VMEXIT_NMI] = "NMI",
2193 [VMEXIT_SMI] = "SMI",
2194 [VMEXIT_INIT] = "INIT",
2195 [VMEXIT_VINTR] = "VINTR",
2196 [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
2197 [VMEXIT_IDTR_READ] = "IDTR_READ",
2198 [VMEXIT_GDTR_READ] = "GDTR_READ",
2199 [VMEXIT_LDTR_READ] = "LDTR_READ",
2200 [VMEXIT_TR_READ] = "TR_READ",
2201 [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
2202 [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
2203 [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
2204 [VMEXIT_TR_WRITE] = "TR_WRITE",
2205 [VMEXIT_RDTSC] = "RDTSC",
2206 [VMEXIT_RDPMC] = "RDPMC",
2207 [VMEXIT_PUSHF] = "PUSHF",
2208 [VMEXIT_POPF] = "POPF",
2209 [VMEXIT_CPUID] = "CPUID",
2210 [VMEXIT_RSM] = "RSM",
2211 [VMEXIT_IRET] = "IRET",
2212 [VMEXIT_SWINT] = "SWINT",
2213 [VMEXIT_INVD] = "INVD",
2214 [VMEXIT_PAUSE] = "PAUSE",
2215 [VMEXIT_HLT] = "HLT",
2216 [VMEXIT_INVLPG] = "INVLPG",
2217 [VMEXIT_INVLPGA] = "INVLPGA",
2218 [VMEXIT_IOIO] = "IOIO",
2219 [VMEXIT_MSR] = "MSR",
2220 [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
2221 [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
2222 [VMEXIT_SHUTDOWN] = "SHUTDOWN",
2223 [VMEXIT_VMRUN] = "VMRUN",
2224 [VMEXIT_VMMCALL] = "VMMCALL",
2225 [VMEXIT_VMLOAD] = "VMLOAD",
2226 [VMEXIT_VMSAVE] = "VMSAVE",
2227 [VMEXIT_STGI] = "STGI",
2228 [VMEXIT_CLGI] = "CLGI",
2229 [VMEXIT_SKINIT] = "SKINIT",
2230 [VMEXIT_RDTSCP] = "RDTSCP",
2231 [VMEXIT_ICEBP] = "ICEBP",
2232 [VMEXIT_NPF] = "NPF"
2233 };
2234 #endif /* SVM_EXTRA_DEBUG */
2236 #ifdef SVM_WALK_GUEST_PAGES
2237 void walk_shadow_and_guest_pt(unsigned long gva)
2239 l2_pgentry_t gpde;
2240 l2_pgentry_t spde;
2241 l1_pgentry_t gpte;
2242 l1_pgentry_t spte;
2243 struct vcpu *v = current;
2244 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2245 unsigned long gpa;
2247 gpa = gva_to_gpa( gva );
2248 printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
2249 if( !svm_paging_enabled(v) || mmio_space(gpa) )
2250 return;
2252 /* let's dump the guest and shadow page info */
2254 __guest_get_l2e(v, gva, &gpde);
2255 printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
2256 __shadow_get_l2e( v, gva, &spde );
2257 printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
2259 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
2260 return;
2262 spte = l1e_empty();
2264 // This is actually overkill - we only need to make sure the hl2 is in-sync.
2265 shadow_sync_va(v, gva);
2267 gpte.l1 = 0;
2268 __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
2269 printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
2270 __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
2271 printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
2273 #endif /* SVM_WALK_GUEST_PAGES */
2275 asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
2277 unsigned int exit_reason;
2278 unsigned long eip;
2279 struct vcpu *v = current;
2280 int error;
2281 int do_debug = 0;
2282 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2284 ASSERT(vmcb);
2286 exit_reason = vmcb->exitcode;
2287 save_svm_cpu_user_regs(v, &regs);
2288 v->arch.hvm_svm.injecting_event = 0;
2290 vmcb->tlb_control = 1;
2292 #ifdef SVM_EXTRA_DEBUG
2294 #if defined(__i386__)
2295 #define rip eip
2296 #endif
2298 static unsigned long intercepts_counter = 0;
2300 if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
2302 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2304 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2305 intercepts_counter,
2306 exit_reasons[exit_reason], exit_reason, regs.cs,
2307 (unsigned long long) regs.rip,
2308 (unsigned long long) vmcb->exitinfo1,
2309 (unsigned long long) vmcb->exitinfo2,
2310 (unsigned long long) vmcb->exitintinfo.bytes);
2313 else if (svm_dbg_on
2314 && exit_reason != VMEXIT_IOIO
2315 && exit_reason != VMEXIT_INTR)
2318 if (exit_reasons[exit_reason])
2320 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2321 intercepts_counter,
2322 exit_reasons[exit_reason], exit_reason, regs.cs,
2323 (unsigned long long) regs.rip,
2324 (unsigned long long) vmcb->exitinfo1,
2325 (unsigned long long) vmcb->exitinfo2,
2326 (unsigned long long) vmcb->exitintinfo.bytes);
2328 else
2330 printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2331 intercepts_counter, exit_reason, exit_reason, regs.cs,
2332 (unsigned long long) regs.rip,
2333 (unsigned long long) vmcb->exitinfo1,
2334 (unsigned long long) vmcb->exitinfo2,
2335 (unsigned long long) vmcb->exitintinfo.bytes);
2339 #ifdef SVM_WALK_GUEST_PAGES
2340 if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
2342 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2343 walk_shadow_and_guest_pt( vmcb->exitinfo2 );
2345 #endif
2347 intercepts_counter++;
2349 #if 0
2350 if (svm_dbg_on)
2351 do_debug = svm_do_debugout(exit_reason);
2352 #endif
2354 if (do_debug)
2356 printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
2357 "shadow_table = 0x%08x\n",
2358 __func__,
2359 (int) v->arch.guest_table.pfn,
2360 (int) v->arch.monitor_table.pfn,
2361 (int) v->arch.shadow_table.pfn);
2363 svm_dump_vmcb(__func__, vmcb);
2364 svm_dump_regs(__func__, &regs);
2365 svm_dump_inst(svm_rip2pointer(vmcb));
2368 #if defined(__i386__)
2369 #undef rip
2370 #endif
2373 #endif /* SVM_EXTRA_DEBUG */
2375 if (exit_reason == -1)
2377 printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
2378 __func__);
2379 BUG();
2380 domain_crash_synchronous();
2383 perfc_incra(vmexits, exit_reason);
2384 eip = vmcb->rip;
2386 #ifdef SVM_EXTRA_DEBUG
2387 if (do_debug)
2389 printk("eip = %lx, exit_reason = %d (0x%x)\n",
2390 eip, exit_reason, exit_reason);
2392 #endif /* SVM_EXTRA_DEBUG */
2394 TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
2396 switch (exit_reason)
2398 case VMEXIT_EXCEPTION_DB:
2400 #ifdef XEN_DEBUGGER
2401 svm_debug_save_cpu_user_regs(&regs);
2402 pdb_handle_exception(1, &regs, 1);
2403 svm_debug_restore_cpu_user_regs(&regs);
2404 #else
2405 svm_store_cpu_user_regs(&regs, v);
2406 domain_pause_for_debugger();
2407 #endif
2409 break;
2411 case VMEXIT_NMI:
2412 do_nmi(&regs, 0);
2413 break;
2415 #ifdef XEN_DEBUGGER
2416 case VMEXIT_EXCEPTION_BP:
2417 svm_debug_save_cpu_user_regs(&regs);
2418 pdb_handle_exception(3, &regs, 1);
2419 svm_debug_restore_cpu_user_regs(&regs);
2420 break;
2421 #endif
2423 case VMEXIT_EXCEPTION_NM:
2424 svm_do_no_device_fault(vmcb);
2425 break;
2427 case VMEXIT_EXCEPTION_GP:
2428 /* This should probably not be trapped in the future */
2429 regs.error_code = vmcb->exitinfo1;
2430 v->arch.hvm_svm.injecting_event = 1;
2431 svm_do_general_protection_fault(v, &regs);
2432 break;
2434 case VMEXIT_EXCEPTION_PF:
2436 unsigned long va;
2437 va = vmcb->exitinfo2;
2438 regs.error_code = vmcb->exitinfo1;
2439 HVM_DBG_LOG(DBG_LEVEL_VMMU,
2440 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
2441 (unsigned long)regs.eax, (unsigned long)regs.ebx,
2442 (unsigned long)regs.ecx, (unsigned long)regs.edx,
2443 (unsigned long)regs.esi, (unsigned long)regs.edi);
2445 v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
2447 //printk("PF1\n");
2448 if (!(error = svm_do_page_fault(va, &regs)))
2450 v->arch.hvm_svm.injecting_event = 1;
2451 /* Inject #PG using Interruption-Information Fields */
2452 svm_inject_exception(vmcb, TRAP_page_fault, 1, regs.error_code);
2454 v->arch.hvm_svm.cpu_cr2 = va;
2455 vmcb->cr2 = va;
2456 TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
2457 VMEXIT_EXCEPTION_PF, va);
2459 break;
2462 case VMEXIT_EXCEPTION_DF:
2463 printk("Guest double fault");
2464 BUG();
2465 break;
2467 case VMEXIT_INTR:
2468 raise_softirq(SCHEDULE_SOFTIRQ);
2469 break;
2471 case VMEXIT_GDTR_WRITE:
2472 printk("WRITE to GDTR\n");
2473 break;
2475 case VMEXIT_TASK_SWITCH:
2476 __hvm_bug(&regs);
2477 break;
2479 case VMEXIT_CPUID:
2480 svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
2481 break;
2483 case VMEXIT_HLT:
2484 svm_vmexit_do_hlt(vmcb);
2485 break;
2487 case VMEXIT_INVLPG:
2488 svm_handle_invlpg(0, &regs);
2489 break;
2491 case VMEXIT_INVLPGA:
2492 svm_handle_invlpg(1, &regs);
2493 break;
2495 case VMEXIT_VMMCALL:
2496 svm_do_vmmcall(v, &regs);
2497 break;
2499 case VMEXIT_CR0_READ:
2500 svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
2501 break;
2503 case VMEXIT_CR2_READ:
2504 svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
2505 break;
2507 case VMEXIT_CR3_READ:
2508 svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
2509 break;
2511 case VMEXIT_CR4_READ:
2512 svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
2513 break;
2515 case VMEXIT_CR8_READ:
2516 svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
2517 break;
2519 case VMEXIT_CR0_WRITE:
2520 svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
2521 break;
2523 case VMEXIT_CR2_WRITE:
2524 svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
2525 break;
2527 case VMEXIT_CR3_WRITE:
2528 svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
2529 local_flush_tlb();
2530 break;
2532 case VMEXIT_CR4_WRITE:
2533 svm_cr_access(v, 4, TYPE_MOV_TO_CR, &regs);
2534 break;
2536 case VMEXIT_CR8_WRITE:
2537 svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
2538 break;
2540 case VMEXIT_DR0_READ:
2541 svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
2542 break;
2544 case VMEXIT_DR1_READ:
2545 svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
2546 break;
2548 case VMEXIT_DR2_READ:
2549 svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
2550 break;
2552 case VMEXIT_DR3_READ:
2553 svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
2554 break;
2556 case VMEXIT_DR6_READ:
2557 svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
2558 break;
2560 case VMEXIT_DR7_READ:
2561 svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
2562 break;
2564 case VMEXIT_DR0_WRITE:
2565 svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
2566 break;
2568 case VMEXIT_DR1_WRITE:
2569 svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
2570 break;
2572 case VMEXIT_DR2_WRITE:
2573 svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
2574 break;
2576 case VMEXIT_DR3_WRITE:
2577 svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
2578 break;
2580 case VMEXIT_DR6_WRITE:
2581 svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
2582 break;
2584 case VMEXIT_DR7_WRITE:
2585 svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
2586 break;
2588 case VMEXIT_IOIO:
2589 svm_io_instruction(v, &regs);
2590 break;
2592 case VMEXIT_MSR:
2593 svm_do_msr_access(v, &regs);
2594 break;
2596 case VMEXIT_SHUTDOWN:
2597 printk("Guest shutdown exit\n");
2598 domain_crash_synchronous();
2599 break;
2601 default:
2602 printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, "
2603 "exitinfo2 = %llx\n", exit_reason,
2604 (unsigned long long)vmcb->exitinfo1,
2605 (unsigned long long)vmcb->exitinfo2);
2606 __hvm_bug(&regs); /* should not happen */
2607 break;
2610 #ifdef SVM_EXTRA_DEBUG
2611 if (do_debug)
2613 printk("%s: Done switch on vmexit_code\n", __func__);
2614 svm_dump_regs(__func__, &regs);
2617 if (do_debug)
2619 printk("vmexit_handler():- guest_table = 0x%08x, "
2620 "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
2621 (int)v->arch.guest_table.pfn,
2622 (int)v->arch.monitor_table.pfn,
2623 (int)v->arch.shadow_table.pfn);
2624 printk("svm_vmexit_handler: Returning\n");
2626 #endif
2628 return;
2631 asmlinkage void svm_load_cr2(void)
2633 struct vcpu *v = current;
2635 local_irq_disable();
2636 #ifdef __i386__
2637 asm volatile("movl %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2638 #else
2639 asm volatile("movq %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2640 #endif
2643 asmlinkage void svm_asid(void)
2645 struct vcpu *v = current;
2646 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2648 /*
2649 * if need to assign new asid, or if switching cores,
2650 * retire asid for the old core, and assign a new asid to the current core.
2651 */
2652 if ( test_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ) ||
2653 ( v->arch.hvm_svm.asid_core != v->arch.hvm_svm.launch_core )) {
2654 /* recycle asid */
2655 if ( !asidpool_assign_next( vmcb, 1,
2656 v->arch.hvm_svm.asid_core, v->arch.hvm_svm.launch_core )) {
2657 /* If we get here, we have a major problem */
2658 domain_crash_synchronous();
2661 v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core;
2662 clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
2666 /*
2667 * Local variables:
2668 * mode: C
2669 * c-set-style: "BSD"
2670 * c-basic-offset: 4
2671 * tab-width: 4
2672 * indent-tabs-mode: nil
2673 * End:
2674 */