direct-io.hg

view xen/arch/x86/hvm/svm/svm.c @ 9462:48abab2ab719

SVM patch to update guest time with latest hvm modifications.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Mar 29 13:56:26 2006 +0100 (2006-03-29)
parents 8d59ff95046b
children f0e14b4e535c
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, unsigned long *crs)
205 {
206 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
208 if ( regs != NULL )
209 {
210 #if defined (__x86_64__)
211 regs->rip = vmcb->rip;
212 regs->rsp = vmcb->rsp;
213 regs->rflags = vmcb->rflags;
214 regs->cs = vmcb->cs.sel;
215 regs->ds = vmcb->ds.sel;
216 regs->es = vmcb->es.sel;
217 regs->ss = vmcb->ss.sel;
218 regs->gs = vmcb->gs.sel;
219 regs->fs = vmcb->fs.sel;
220 #elif defined (__i386__)
221 regs->eip = vmcb->rip;
222 regs->esp = vmcb->rsp;
223 regs->eflags = vmcb->rflags;
224 regs->cs = vmcb->cs.sel;
225 regs->ds = vmcb->ds.sel;
226 regs->es = vmcb->es.sel;
227 regs->ss = vmcb->ss.sel;
228 regs->gs = vmcb->gs.sel;
229 regs->fs = vmcb->fs.sel;
230 #endif
231 }
233 if ( crs != NULL )
234 {
235 crs[0] = vmcb->cr0;
236 crs[3] = vmcb->cr3;
237 crs[4] = vmcb->cr4;
238 }
239 }
241 static void svm_load_cpu_guest_regs(
242 struct vcpu *v, struct cpu_user_regs *regs)
243 {
244 svm_load_cpu_user_regs(v, regs);
245 }
247 #define IS_CANO_ADDRESS(add) 1
249 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
250 {
251 u64 msr_content = 0;
252 struct vcpu *vc = current;
253 // struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
254 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
256 switch (regs->ecx)
257 {
258 case MSR_EFER:
259 // msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
260 msr_content = vmcb->efer;
261 msr_content &= ~EFER_SVME;
262 break;
264 case MSR_FS_BASE:
265 msr_content = vmcb->fs.base;
266 break;
268 case MSR_GS_BASE:
269 msr_content = vmcb->gs.base;
270 break;
272 case MSR_SHADOW_GS_BASE:
273 msr_content = vmcb->kerngsbase;
274 break;
276 case MSR_STAR:
277 msr_content = vmcb->star;
278 break;
280 case MSR_LSTAR:
281 msr_content = vmcb->lstar;
282 break;
284 case MSR_CSTAR:
285 msr_content = vmcb->cstar;
286 break;
288 case MSR_SYSCALL_MASK:
289 msr_content = vmcb->sfmask;
290 break;
292 default:
293 return 0;
294 }
296 HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %"PRIx64"\n",
297 msr_content);
299 regs->eax = msr_content & 0xffffffff;
300 regs->edx = msr_content >> 32;
301 return 1;
302 }
304 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
305 {
306 u64 msr_content = regs->eax | ((u64)regs->edx << 32);
307 struct vcpu *vc = current;
308 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
310 HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx "
311 "msr_content %"PRIx64"\n",
312 (unsigned long)regs->ecx, msr_content);
314 switch (regs->ecx)
315 {
316 case MSR_EFER:
317 #ifdef __x86_64__
318 if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
319 &vc->arch.hvm_svm.cpu_state))
320 {
321 if (test_bit(SVM_CPU_STATE_PG_ENABLED, &vc->arch.hvm_svm.cpu_state)
322 || !test_bit(SVM_CPU_STATE_PAE_ENABLED,
323 &vc->arch.hvm_svm.cpu_state))
324 {
325 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
326 }
327 }
329 if (msr_content & EFER_LME)
330 set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
332 /* We have already recorded that we want LME, so it will be set
333 * next time CR0 gets updated. So we clear that bit and continue.
334 */
335 if ((msr_content ^ vmcb->efer) & EFER_LME)
336 msr_content &= ~EFER_LME;
337 /* No update for LME/LMA since it have no effect */
338 #endif
339 vmcb->efer = msr_content | EFER_SVME;
340 break;
342 case MSR_FS_BASE:
343 case MSR_GS_BASE:
344 if (!(SVM_LONG_GUEST(vc)))
345 domain_crash_synchronous();
347 if (!IS_CANO_ADDRESS(msr_content))
348 {
349 HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
350 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
351 }
353 if (regs->ecx == MSR_FS_BASE)
354 vmcb->fs.base = msr_content;
355 else
356 vmcb->gs.base = msr_content;
357 break;
359 case MSR_SHADOW_GS_BASE:
360 vmcb->kerngsbase = msr_content;
361 break;
363 case MSR_STAR:
364 vmcb->star = msr_content;
365 break;
367 case MSR_LSTAR:
368 vmcb->lstar = msr_content;
369 break;
371 case MSR_CSTAR:
372 vmcb->cstar = msr_content;
373 break;
375 case MSR_SYSCALL_MASK:
376 vmcb->sfmask = msr_content;
377 break;
379 default:
380 return 0;
381 }
382 return 1;
383 }
385 void svm_modify_guest_state(struct vcpu *v)
386 {
387 svm_modify_vmcb(v, &v->arch.guest_context.user_regs);
388 }
390 int svm_realmode(struct vcpu *v)
391 {
392 unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
393 unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
395 return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
396 }
398 int svm_instruction_length(struct vcpu *v)
399 {
400 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
401 unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
402 /* check which operating mode the guest is running */
403 if( vmcb->efer & EFER_LMA )
404 mode = vmcb->cs.attributes.fields.l ? 8 : 4;
405 else
406 mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
407 return svm_instrlen(guest_cpu_user_regs(), mode);
408 }
410 unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
411 {
412 switch ( num )
413 {
414 case 0:
415 return v->arch.hvm_svm.cpu_shadow_cr0;
416 case 2:
417 return v->arch.hvm_svm.cpu_cr2;
418 case 3:
419 return v->arch.hvm_svm.cpu_cr3;
420 default:
421 BUG();
422 }
423 return 0; /* dummy */
424 }
426 int start_svm(void)
427 {
428 u32 eax, ecx, edx;
430 /* Xen does not fill x86_capability words except 0. */
431 ecx = cpuid_ecx(0x80000001);
432 boot_cpu_data.x86_capability[5] = ecx;
434 if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
435 return 0;
437 rdmsr(MSR_EFER, eax, edx);
438 eax |= EFER_SVME;
439 wrmsr(MSR_EFER, eax, edx);
440 asidpool_init(smp_processor_id());
441 printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
443 /* Setup HVM interfaces */
444 hvm_funcs.disable = stop_svm;
446 hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
447 hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
449 hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
450 hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_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_freeze_time(struct vcpu *v)
674 {
675 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
677 if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
678 v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v);
679 stop_timer(&(vpit->pit_timer));
680 }
681 }
683 static void svm_ctxt_switch_from(struct vcpu *v)
684 {
685 svm_freeze_time(v);
686 }
688 static void svm_ctxt_switch_to(struct vcpu *v)
689 {
690 }
692 void svm_final_setup_guest(struct vcpu *v)
693 {
694 v->arch.schedule_tail = arch_svm_do_launch;
695 v->arch.ctxt_switch_from = svm_ctxt_switch_from;
696 v->arch.ctxt_switch_to = svm_ctxt_switch_to;
698 if (v == v->domain->vcpu[0])
699 {
700 struct domain *d = v->domain;
701 struct vcpu *vc;
703 /* Initialize monitor page table */
704 for_each_vcpu(d, vc)
705 vc->arch.monitor_table = mk_pagetable(0);
707 /*
708 * Required to do this once per domain
709 * TODO: add a seperate function to do these.
710 */
711 memset(&d->shared_info->evtchn_mask[0], 0xff,
712 sizeof(d->shared_info->evtchn_mask));
714 /*
715 * Put the domain in shadow mode even though we're going to be using
716 * the shared 1:1 page table initially. It shouldn't hurt
717 */
718 shadow_mode_enable(d,
719 SHM_enable|SHM_refcounts|
720 SHM_translate|SHM_external|SHM_wr_pt_pte);
721 }
722 }
725 static void svm_relinquish_guest_resources(struct domain *d)
726 {
727 extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
728 struct vcpu *v;
730 for_each_vcpu ( d, v )
731 {
732 if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
733 continue;
734 #if 0
735 /* Memory leak by not freeing this. XXXKAF: *Why* is not per core?? */
736 free_host_save_area(v->arch.hvm_svm.host_save_area);
737 #endif
739 destroy_vmcb(&v->arch.hvm_svm);
740 free_monitor_pagetable(v);
741 kill_timer(&v->arch.hvm_svm.hlt_timer);
742 if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
743 {
744 kill_timer( &(VLAPIC(v)->vlapic_timer) );
745 xfree(VLAPIC(v));
746 }
747 }
749 kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
751 if ( d->arch.hvm_domain.shared_page_va )
752 unmap_domain_page_global(
753 (void *)d->arch.hvm_domain.shared_page_va);
755 shadow_direct_map_clean(d);
756 }
759 void arch_svm_do_resume(struct vcpu *v)
760 {
761 /* pinning VCPU to a different core? */
762 if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
763 svm_do_resume( v );
764 reset_stack_and_jump( svm_asm_do_resume );
765 }
766 else {
767 printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() );
768 v->arch.hvm_svm.launch_core = smp_processor_id();
769 svm_migrate_timers( v );
770 svm_do_resume( v );
771 reset_stack_and_jump( svm_asm_do_resume );
772 }
773 }
776 void svm_migrate_timers(struct vcpu *v)
777 {
778 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
780 migrate_timer( &vpit->pit_timer, v->processor );
781 migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
782 if ( hvm_apic_support(v->domain) && VLAPIC( v ))
783 migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
784 }
787 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
788 {
789 struct vcpu *v = current;
790 unsigned long eip;
791 unsigned long gpa; /* FIXME: PAE */
792 int result;
793 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
795 ASSERT(vmcb);
797 //#if HVM_DEBUG
798 eip = vmcb->rip;
799 HVM_DBG_LOG(DBG_LEVEL_VMMU,
800 "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
801 va, eip, (unsigned long)regs->error_code);
802 //#endif
804 if ( !svm_paging_enabled(v) )
805 {
806 if ( shadow_direct_map_fault(va, regs) )
807 return 1;
809 handle_mmio(va, va);
810 TRACE_VMEXIT(2,2);
811 return 1;
812 }
815 gpa = gva_to_gpa(va);
817 /* Use 1:1 page table to identify MMIO address space */
818 if (mmio_space(gpa))
819 {
820 /* No support for APIC */
821 if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
822 {
823 int inst_len;
824 inst_len = svm_instruction_length(v);
825 if (inst_len == -1)
826 {
827 printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
828 domain_crash_synchronous();
829 }
831 __update_guest_eip(vmcb, inst_len);
833 return 1;
834 }
836 TRACE_VMEXIT (2,2);
837 handle_mmio(va, gpa);
839 return 1;
840 }
842 result = shadow_fault(va, regs);
844 if( result ) {
845 /* Let's make sure that the Guest TLB is flushed */
846 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
847 }
849 TRACE_VMEXIT (2,result);
851 return result;
852 }
855 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
856 {
857 struct vcpu *v = current;
859 setup_fpu(v);
860 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
862 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
863 vmcb->cr0 &= ~X86_CR0_TS;
864 }
867 static void svm_do_general_protection_fault(struct vcpu *v,
868 struct cpu_user_regs *regs)
869 {
870 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
871 unsigned long eip, error_code;
873 ASSERT(vmcb);
875 eip = vmcb->rip;
876 error_code = vmcb->exitinfo1;
878 if (vmcb->idtr.limit == 0) {
879 printf("Huh? We got a GP Fault with an invalid IDTR!\n");
880 svm_dump_vmcb(__func__, vmcb);
881 svm_dump_regs(__func__, regs);
882 svm_dump_inst(vmcb->rip);
883 __hvm_bug(regs);
884 }
886 HVM_DBG_LOG(DBG_LEVEL_1,
887 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
888 eip, error_code);
890 HVM_DBG_LOG(DBG_LEVEL_1,
891 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
892 (unsigned long)regs->eax, (unsigned long)regs->ebx,
893 (unsigned long)regs->ecx, (unsigned long)regs->edx,
894 (unsigned long)regs->esi, (unsigned long)regs->edi);
897 /* Reflect it back into the guest */
898 svm_inject_exception(vmcb, TRAP_gp_fault, 1, error_code);
899 }
901 /* Reserved bits: [31:14], [12:1] */
902 #define SVM_VCPU_CPUID_L1_RESERVED 0xffffdffe
904 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
905 struct cpu_user_regs *regs)
906 {
907 unsigned int eax, ebx, ecx, edx;
908 unsigned long eip;
909 struct vcpu *v = current;
910 int inst_len;
912 ASSERT(vmcb);
914 eip = vmcb->rip;
916 HVM_DBG_LOG(DBG_LEVEL_1,
917 "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
918 " (esi) %lx, (edi) %lx",
919 (unsigned long)regs->eax, (unsigned long)regs->ebx,
920 (unsigned long)regs->ecx, (unsigned long)regs->edx,
921 (unsigned long)regs->esi, (unsigned long)regs->edi);
923 cpuid(input, &eax, &ebx, &ecx, &edx);
925 if (input == 1)
926 {
927 if ( !hvm_apic_support(v->domain) ||
928 !vlapic_global_enabled((VLAPIC(v))) )
929 clear_bit(X86_FEATURE_APIC, &edx);
931 #if CONFIG_PAGING_LEVELS < 3
932 clear_bit(X86_FEATURE_PAE, &edx);
933 clear_bit(X86_FEATURE_PSE, &edx);
934 clear_bit(X86_FEATURE_PSE36, &edx);
935 #else
936 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
937 {
938 if ( !v->domain->arch.hvm_domain.pae_enabled )
939 clear_bit(X86_FEATURE_PAE, &edx);
940 clear_bit(X86_FEATURE_PSE, &edx);
941 clear_bit(X86_FEATURE_PSE36, &edx);
942 }
943 #endif
945 /* Clear out reserved bits. */
946 ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
947 clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
948 }
949 #ifdef __i386__
950 else if ( input == 0x80000001 )
951 {
952 /* Mask feature for Intel ia32e or AMD long mode. */
953 clear_bit(X86_FEATURE_LM & 31, &edx);
954 }
955 #endif
957 regs->eax = (unsigned long)eax;
958 regs->ebx = (unsigned long)ebx;
959 regs->ecx = (unsigned long)ecx;
960 regs->edx = (unsigned long)edx;
962 HVM_DBG_LOG(DBG_LEVEL_1,
963 "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
964 "ebx=%x, ecx=%x, edx=%x",
965 eip, input, eax, ebx, ecx, edx);
967 inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
968 ASSERT(inst_len > 0);
969 __update_guest_eip(vmcb, inst_len);
970 }
973 static inline unsigned long *get_reg_p(unsigned int gpreg,
974 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
975 {
976 unsigned long *reg_p = NULL;
977 switch (gpreg)
978 {
979 case SVM_REG_EAX:
980 reg_p = (unsigned long *)&regs->eax;
981 break;
982 case SVM_REG_EBX:
983 reg_p = (unsigned long *)&regs->ebx;
984 break;
985 case SVM_REG_ECX:
986 reg_p = (unsigned long *)&regs->ecx;
987 break;
988 case SVM_REG_EDX:
989 reg_p = (unsigned long *)&regs->edx;
990 break;
991 case SVM_REG_EDI:
992 reg_p = (unsigned long *)&regs->edi;
993 break;
994 case SVM_REG_ESI:
995 reg_p = (unsigned long *)&regs->esi;
996 break;
997 case SVM_REG_EBP:
998 reg_p = (unsigned long *)&regs->ebp;
999 break;
1000 case SVM_REG_ESP:
1001 reg_p = (unsigned long *)&vmcb->rsp;
1002 break;
1003 #if __x86_64__
1004 case SVM_REG_R8:
1005 reg_p = (unsigned long *)&regs->r8;
1006 break;
1007 case SVM_REG_R9:
1008 reg_p = (unsigned long *)&regs->r9;
1009 break;
1010 case SVM_REG_R10:
1011 reg_p = (unsigned long *)&regs->r10;
1012 break;
1013 case SVM_REG_R11:
1014 reg_p = (unsigned long *)&regs->r11;
1015 break;
1016 case SVM_REG_R12:
1017 reg_p = (unsigned long *)&regs->r12;
1018 break;
1019 case SVM_REG_R13:
1020 reg_p = (unsigned long *)&regs->r13;
1021 break;
1022 case SVM_REG_R14:
1023 reg_p = (unsigned long *)&regs->r14;
1024 break;
1025 case SVM_REG_R15:
1026 reg_p = (unsigned long *)&regs->r15;
1027 break;
1028 #endif
1029 default:
1030 BUG();
1033 return reg_p;
1037 static inline unsigned long get_reg(unsigned int gpreg,
1038 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1040 unsigned long *gp;
1041 gp = get_reg_p(gpreg, regs, vmcb);
1042 return *gp;
1046 static inline void set_reg(unsigned int gpreg, unsigned long value,
1047 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1049 unsigned long *gp;
1050 gp = get_reg_p(gpreg, regs, vmcb);
1051 *gp = value;
1055 static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
1056 struct cpu_user_regs *regs)
1058 unsigned long *reg_p = 0;
1059 unsigned int gpreg = 0;
1060 unsigned long eip;
1061 int inst_len;
1062 int index;
1063 struct vmcb_struct *vmcb;
1064 u8 buffer[MAX_INST_LEN];
1065 u8 prefix = 0;
1067 vmcb = v->arch.hvm_svm.vmcb;
1069 ASSERT(vmcb);
1071 eip = vmcb->rip;
1072 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1073 index = skip_prefix_bytes(buffer, sizeof(buffer));
1075 ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
1077 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
1078 prefix = buffer[index-1];
1080 gpreg = decode_src_reg(prefix, buffer[index + 2]);
1081 ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
1083 HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
1084 eip, reg, gpreg);
1086 reg_p = get_reg_p(gpreg, regs, vmcb);
1088 switch (type)
1090 case TYPE_MOV_TO_DR:
1091 inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
1092 v->arch.guest_context.debugreg[reg] = *reg_p;
1093 break;
1094 case TYPE_MOV_FROM_DR:
1095 inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
1096 *reg_p = v->arch.guest_context.debugreg[reg];
1097 break;
1098 default:
1099 __hvm_bug(regs);
1100 break;
1102 ASSERT(inst_len > 0);
1103 __update_guest_eip(vmcb, inst_len);
1107 static unsigned int check_for_null_selector(struct vmcb_struct *vmcb,
1108 unsigned int dir, unsigned long *base, unsigned int real)
1111 unsigned char inst[MAX_INST_LEN];
1112 segment_selector_t seg;
1113 int i;
1115 memset(inst, 0, MAX_INST_LEN);
1116 if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
1117 != MAX_INST_LEN)
1119 printk("check_for_null_selector: get guest instruction failed\n");
1120 domain_crash_synchronous();
1123 for (i = 0; i < MAX_INST_LEN; i++)
1125 switch (inst[i])
1127 case 0xf3: /* REPZ */
1128 case 0xf2: /* REPNZ */
1129 case 0xf0: /* LOCK */
1130 case 0x66: /* data32 */
1131 case 0x67: /* addr32 */
1132 #if __x86_64__
1133 /* REX prefixes */
1134 case 0x40:
1135 case 0x41:
1136 case 0x42:
1137 case 0x43:
1138 case 0x44:
1139 case 0x45:
1140 case 0x46:
1141 case 0x47:
1143 case 0x48:
1144 case 0x49:
1145 case 0x4a:
1146 case 0x4b:
1147 case 0x4c:
1148 case 0x4d:
1149 case 0x4e:
1150 case 0x4f:
1151 #endif
1152 continue;
1153 case 0x2e: /* CS */
1154 seg = vmcb->cs;
1155 break;
1156 case 0x36: /* SS */
1157 seg = vmcb->ss;
1158 break;
1159 case 0x26: /* ES */
1160 seg = vmcb->es;
1161 break;
1162 case 0x64: /* FS */
1163 seg = vmcb->fs;
1164 break;
1165 case 0x65: /* GS */
1166 seg = vmcb->gs;
1167 break;
1168 case 0x3e: /* DS */
1169 /* FALLTHROUGH */
1170 seg = vmcb->ds;
1171 break;
1172 default:
1173 if (dir == IOREQ_READ)
1174 seg = vmcb->es;
1175 else
1176 seg = vmcb->ds;
1179 /* In real Mode */
1180 if (real)
1181 seg.base = seg.sel << 4;
1183 if (base)
1184 *base = seg.base;
1186 return seg.attributes.fields.p;
1189 ASSERT(0);
1190 return 0;
1194 /* Get the address of INS/OUTS instruction */
1195 static inline unsigned long svm_get_io_address(struct vmcb_struct *vmcb,
1196 struct cpu_user_regs *regs, unsigned int dir, unsigned int real)
1198 unsigned long addr = 0;
1199 unsigned long base = 0;
1201 check_for_null_selector(vmcb, dir, &base, real);
1203 if (dir == IOREQ_WRITE)
1205 if (real)
1206 addr = (regs->esi & 0xFFFF) + base;
1207 else
1208 addr = regs->esi + base;
1210 else
1212 if (real)
1213 addr = (regs->edi & 0xFFFF) + base;
1214 else
1215 addr = regs->edi + base;
1218 return addr;
1222 static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs)
1224 struct mmio_op *mmio_opp;
1225 unsigned long eip, cs, eflags, cr0;
1226 unsigned long port;
1227 unsigned int real, size, dir;
1228 ioio_info_t info;
1230 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1232 ASSERT(vmcb);
1233 mmio_opp = &current->arch.hvm_vcpu.mmio_op;
1234 mmio_opp->instr = INSTR_PIO;
1235 mmio_opp->flags = 0;
1237 eip = vmcb->rip;
1238 cs = vmcb->cs.sel;
1239 eflags = vmcb->rflags;
1241 info.bytes = vmcb->exitinfo1;
1243 port = info.fields.port; /* port used to be addr */
1244 dir = info.fields.type; /* direction */
1245 if (info.fields.sz32)
1246 size = 4;
1247 else if (info.fields.sz16)
1248 size = 2;
1249 else
1250 size = 1;
1252 cr0 = vmcb->cr0;
1253 real = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
1255 HVM_DBG_LOG(DBG_LEVEL_IO,
1256 "svm_io_instruction: port 0x%lx real %d, eip=%lx:%lx, "
1257 "exit_qualification = %lx",
1258 (unsigned long) port, real, cs, eip, (unsigned long)info.bytes);
1259 /* string instruction */
1260 if (info.fields.str)
1262 unsigned long addr, count = 1;
1263 int sign = regs->eflags & EF_DF ? -1 : 1;
1265 /* Need the original rip, here. */
1266 addr = svm_get_io_address(vmcb, regs, dir, real);
1268 /* "rep" prefix */
1269 if (info.fields.rep)
1271 mmio_opp->flags |= REPZ;
1272 count = real ? regs->ecx & 0xFFFF : regs->ecx;
1275 /*
1276 * Handle string pio instructions that cross pages or that
1277 * are unaligned. See the comments in hvm_platform.c/handle_mmio()
1278 */
1279 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
1281 unsigned long value = 0;
1283 mmio_opp->flags |= OVERLAP;
1285 if (dir == IOREQ_WRITE)
1286 hvm_copy(&value, addr, size, HVM_COPY_IN);
1288 send_pio_req(regs, port, 1, size, value, dir, 0);
1290 else
1292 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
1294 if (sign > 0)
1295 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
1296 else
1297 count = (addr & ~PAGE_MASK) / size;
1299 else
1300 vmcb->rip = vmcb->exitinfo2;
1302 send_pio_req(regs, port, count, size, addr, dir, 1);
1305 else
1307 /*
1308 * On SVM, the RIP of the intruction following the IN/OUT is saved in
1309 * ExitInfo2
1310 */
1311 vmcb->rip = vmcb->exitinfo2;
1313 if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
1314 hvm_print_line(v, regs->eax); /* guest debug output */
1316 send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
1320 static int svm_set_cr0(unsigned long value)
1322 struct vcpu *v = current;
1323 unsigned long mfn;
1324 int paging_enabled;
1325 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1326 unsigned long crn;
1328 ASSERT(vmcb);
1330 /* We don't want to lose PG. ET is reserved and should be always be 1*/
1331 paging_enabled = svm_paging_enabled(v);
1332 value |= X86_CR0_ET;
1333 vmcb->cr0 = value | X86_CR0_PG;
1334 v->arch.hvm_svm.cpu_shadow_cr0 = value;
1336 /* TS cleared? Then initialise FPU now. */
1337 if ( !(value & X86_CR0_TS) )
1339 setup_fpu(v);
1340 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1343 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
1345 if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
1347 /* The guest CR3 must be pointing to the guest physical. */
1348 if (!VALID_MFN(mfn =
1349 get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
1350 || !get_page(mfn_to_page(mfn), v->domain))
1352 printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
1353 domain_crash_synchronous(); /* need to take a clean path */
1356 #if defined(__x86_64__)
1357 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
1358 && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
1359 &v->arch.hvm_svm.cpu_state))
1361 HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
1362 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1365 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
1367 /* Here the PAE is should to be opened */
1368 HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
1369 set_bit(SVM_CPU_STATE_LMA_ENABLED,
1370 &v->arch.hvm_svm.cpu_state);
1371 vmcb->efer |= (EFER_LMA | EFER_LME);
1373 #if CONFIG_PAGING_LEVELS >= 4
1374 if (!shadow_set_guest_paging_levels(v->domain, 4))
1376 printk("Unsupported guest paging levels\n");
1377 domain_crash_synchronous(); /* need to take a clean path */
1379 #endif
1381 else
1382 #endif /* __x86_64__ */
1384 #if CONFIG_PAGING_LEVELS >= 3
1385 if (!shadow_set_guest_paging_levels(v->domain, 2))
1387 printk("Unsupported guest paging levels\n");
1388 domain_crash_synchronous(); /* need to take a clean path */
1390 #endif
1393 /* update CR4's PAE if needed */
1394 crn = vmcb->cr4;
1395 if ((!(crn & X86_CR4_PAE))
1396 && test_bit(SVM_CPU_STATE_PAE_ENABLED,
1397 &v->arch.hvm_svm.cpu_state))
1399 HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
1400 vmcb->cr4 |= X86_CR4_PAE;
1403 /* Now arch.guest_table points to machine physical. */
1404 v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
1405 update_pagetables(v);
1407 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
1408 (unsigned long) (mfn << PAGE_SHIFT));
1410 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1411 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1413 /* arch->shadow_table should hold the next CR3 for shadow */
1414 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
1415 v->arch.hvm_svm.cpu_cr3, mfn);
1418 /*
1419 * SVM implements paged real-mode and when we return to real-mode
1420 * we revert back to the physical mappings that the domain builder
1421 * created.
1422 */
1423 if ((value & X86_CR0_PE) == 0) {
1424 if (value & X86_CR0_PG) {
1425 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1426 return 0;
1429 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1430 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
1433 return 1;
1436 /*
1437 * Read from control registers. CR0 and CR4 are read from the shadow.
1438 */
1439 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
1441 unsigned long value = 0;
1442 struct vcpu *v = current;
1443 struct vmcb_struct *vmcb;
1445 vmcb = v->arch.hvm_svm.vmcb;
1446 ASSERT(vmcb);
1448 switch (cr)
1450 case 0:
1451 value = v->arch.hvm_svm.cpu_shadow_cr0;
1452 break;
1453 case 2:
1454 value = vmcb->cr2;
1455 break;
1456 case 3:
1457 value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
1458 break;
1459 case 4:
1460 value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
1461 break;
1462 case 8:
1463 #if 0
1464 value = vmcb->m_cr8;
1465 #else
1466 ASSERT(0);
1467 #endif
1468 break;
1470 default:
1471 __hvm_bug(regs);
1474 set_reg(gp, value, regs, vmcb);
1476 HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
1480 /*
1481 * Write to control registers
1482 */
1483 static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
1485 unsigned long value;
1486 unsigned long old_cr;
1487 struct vcpu *v = current;
1488 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1490 ASSERT(vmcb);
1492 value = get_reg(gpreg, regs, vmcb);
1494 HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
1495 HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
1497 switch (cr)
1499 case 0:
1500 return svm_set_cr0(value);
1502 case 3:
1504 unsigned long old_base_mfn, mfn;
1506 /* If paging is not enabled yet, simply copy the value to CR3. */
1507 if (!svm_paging_enabled(v)) {
1508 v->arch.hvm_svm.cpu_cr3 = value;
1509 break;
1511 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1513 /* We make a new one if the shadow does not exist. */
1514 if (value == v->arch.hvm_svm.cpu_cr3)
1516 /*
1517 * This is simple TLB flush, implying the guest has
1518 * removed some translation or changed page attributes.
1519 * We simply invalidate the shadow.
1520 */
1521 mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
1522 if (mfn != pagetable_get_pfn(v->arch.guest_table))
1523 __hvm_bug(regs);
1524 shadow_sync_all(v->domain);
1526 else
1528 /*
1529 * If different, make a shadow. Check if the PDBR is valid
1530 * first.
1531 */
1532 HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
1533 if (((value >> PAGE_SHIFT) > v->domain->max_pages)
1534 || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
1535 || !get_page(mfn_to_page(mfn), v->domain))
1537 printk("Invalid CR3 value=%lx\n", value);
1538 domain_crash_synchronous(); /* need to take a clean path */
1541 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1542 v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
1544 if (old_base_mfn)
1545 put_page(mfn_to_page(old_base_mfn));
1547 update_pagetables(v);
1549 /* arch.shadow_table should now hold the next CR3 for shadow*/
1550 v->arch.hvm_svm.cpu_cr3 = value;
1551 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
1552 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1554 break;
1557 case 4:
1558 /* CR4 */
1559 if (value & X86_CR4_PAE) {
1560 set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
1561 } else {
1562 if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
1563 &v->arch.hvm_svm.cpu_state)) {
1564 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1566 clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
1569 old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
1570 v->arch.hvm_svm.cpu_shadow_cr4 = value;
1571 vmcb->cr4 = value | SVM_CR4_HOST_MASK;
1573 /*
1574 * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
1575 * all TLB entries except global entries.
1576 */
1577 if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
1579 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1580 shadow_sync_all(v->domain);
1582 break;
1584 default:
1585 printk("invalid cr: %d\n", cr);
1586 __hvm_bug(regs);
1589 return 1;
1593 #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
1596 static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
1597 struct cpu_user_regs *regs)
1599 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1600 int inst_len = 0;
1601 int index;
1602 unsigned int gpreg;
1603 unsigned long value;
1604 u8 buffer[MAX_INST_LEN];
1605 u8 prefix = 0;
1606 int result = 1;
1607 enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
1608 enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
1609 enum instruction_index match;
1611 ASSERT(vmcb);
1613 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1614 /* get index to first actual instruction byte - as we will need to know where the
1615 * prefix lives later on
1616 */
1617 index = skip_prefix_bytes(buffer, sizeof(buffer));
1619 if (type == TYPE_MOV_TO_CR)
1621 inst_len = __get_instruction_length_from_list(vmcb, list_a,
1622 ARR_SIZE(list_a), &buffer[index], &match);
1624 else
1626 inst_len = __get_instruction_length_from_list(vmcb, list_b,
1627 ARR_SIZE(list_b), &buffer[index], &match);
1630 ASSERT(inst_len > 0);
1632 inst_len += index;
1634 /* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */
1635 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
1636 prefix = buffer[index-1];
1638 HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
1640 switch (match)
1642 case INSTR_MOV2CR:
1643 gpreg = decode_src_reg(prefix, buffer[index+2]);
1644 result = mov_to_cr(gpreg, cr, regs);
1645 break;
1647 case INSTR_MOVCR2:
1648 gpreg = decode_src_reg(prefix, buffer[index+2]);
1649 mov_from_cr(cr, gpreg, regs);
1650 break;
1652 case INSTR_CLTS:
1653 /* TS being cleared means that it's time to restore fpu state. */
1654 setup_fpu(current);
1655 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1656 vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
1657 v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
1658 break;
1660 case INSTR_LMSW:
1661 if (svm_dbg_on)
1662 svm_dump_inst(svm_rip2pointer(vmcb));
1664 gpreg = decode_src_reg(prefix, buffer[index+2]);
1665 value = get_reg(gpreg, regs, vmcb) & 0xF;
1667 if (svm_dbg_on)
1668 printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1669 inst_len);
1671 value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
1673 if (svm_dbg_on)
1674 printk("CR0-LMSW CR0 - New value=%lx\n", value);
1676 result = svm_set_cr0(value);
1677 break;
1679 case INSTR_SMSW:
1680 svm_dump_inst(svm_rip2pointer(vmcb));
1681 value = v->arch.hvm_svm.cpu_shadow_cr0;
1682 gpreg = decode_src_reg(prefix, buffer[index+2]);
1683 set_reg(gpreg, value, regs, vmcb);
1685 if (svm_dbg_on)
1686 printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1687 inst_len);
1688 break;
1690 default:
1691 __hvm_bug(regs);
1692 break;
1695 ASSERT(inst_len);
1697 __update_guest_eip(vmcb, inst_len);
1699 return result;
1702 static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
1704 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1705 int inst_len;
1706 u64 msr_content=0;
1708 ASSERT(vmcb);
1710 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
1711 "exitinfo = %lx", (unsigned long)regs->ecx,
1712 (unsigned long)regs->eax, (unsigned long)regs->edx,
1713 (unsigned long)vmcb->exitinfo1);
1715 /* is it a read? */
1716 if (vmcb->exitinfo1 == 0)
1718 inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
1720 regs->edx = 0;
1721 switch (regs->ecx) {
1722 case MSR_IA32_TIME_STAMP_COUNTER:
1724 struct hvm_virpit *vpit;
1726 rdtscll(msr_content);
1727 vpit = &(v->domain->arch.hvm_domain.vpit);
1728 msr_content += vpit->cache_tsc_offset;
1729 break;
1731 case MSR_IA32_SYSENTER_CS:
1732 msr_content = vmcb->sysenter_cs;
1733 break;
1734 case MSR_IA32_SYSENTER_ESP:
1735 msr_content = vmcb->sysenter_esp;
1736 break;
1737 case MSR_IA32_SYSENTER_EIP:
1738 msr_content = vmcb->sysenter_eip;
1739 break;
1740 case MSR_IA32_APICBASE:
1741 msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
1742 break;
1743 default:
1744 if (long_mode_do_msr_read(regs))
1745 goto done;
1746 rdmsr_safe(regs->ecx, regs->eax, regs->edx);
1747 break;
1749 regs->eax = msr_content & 0xFFFFFFFF;
1750 regs->edx = msr_content >> 32;
1752 else
1754 inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
1755 msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32);
1757 switch (regs->ecx)
1759 case MSR_IA32_TIME_STAMP_COUNTER:
1760 svm_set_guest_time(v, msr_content);
1761 break;
1762 case MSR_IA32_SYSENTER_CS:
1763 vmcb->sysenter_cs = msr_content;
1764 break;
1765 case MSR_IA32_SYSENTER_ESP:
1766 vmcb->sysenter_esp = msr_content;
1767 break;
1768 case MSR_IA32_SYSENTER_EIP:
1769 vmcb->sysenter_eip = msr_content;
1770 break;
1771 case MSR_IA32_APICBASE:
1772 vlapic_msr_set(VLAPIC(v), msr_content);
1773 break;
1774 default:
1775 long_mode_do_msr_write(regs);
1776 break;
1780 done:
1782 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
1783 "ecx=%lx, eax=%lx, edx=%lx",
1784 (unsigned long)regs->ecx, (unsigned long)regs->eax,
1785 (unsigned long)regs->edx);
1787 __update_guest_eip(vmcb, inst_len);
1791 /*
1792 * Need to use this exit to reschedule
1793 */
1794 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
1796 struct vcpu *v = current;
1797 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
1798 s_time_t next_pit = -1, next_wakeup;
1800 __update_guest_eip(vmcb, 1);
1802 /* check for interrupt not handled or new interrupt */
1803 if ( vmcb->vintr.fields.irq || cpu_has_pending_irq(v) )
1804 return;
1806 if ( !v->vcpu_id )
1807 next_pit = get_pit_scheduled(v, vpit);
1808 next_wakeup = get_apictime_scheduled(v);
1809 if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
1810 next_wakeup = next_pit;
1811 if ( next_wakeup != - 1 )
1812 set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
1813 hvm_safe_block();
1817 static inline void svm_vmexit_do_mwait(void)
1822 #ifdef XEN_DEBUGGER
1823 static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
1824 struct cpu_user_regs *regs)
1826 regs->eip = vmcb->rip;
1827 regs->esp = vmcb->rsp;
1828 regs->eflags = vmcb->rflags;
1830 regs->xcs = vmcb->cs.sel;
1831 regs->xds = vmcb->ds.sel;
1832 regs->xes = vmcb->es.sel;
1833 regs->xfs = vmcb->fs.sel;
1834 regs->xgs = vmcb->gs.sel;
1835 regs->xss = vmcb->ss.sel;
1839 static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
1841 vmcb->ss.sel = regs->xss;
1842 vmcb->rsp = regs->esp;
1843 vmcb->rflags = regs->eflags;
1844 vmcb->cs.sel = regs->xcs;
1845 vmcb->rip = regs->eip;
1847 vmcb->gs.sel = regs->xgs;
1848 vmcb->fs.sel = regs->xfs;
1849 vmcb->es.sel = regs->xes;
1850 vmcb->ds.sel = regs->xds;
1852 #endif
1855 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
1857 struct vcpu *v = current;
1858 u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
1859 unsigned long g_vaddr;
1860 int inst_len;
1861 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1863 ASSERT(vmcb);
1864 /*
1865 * Unknown how many bytes the invlpg instruction will take. Use the
1866 * maximum instruction length here
1867 */
1868 if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
1870 printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
1871 __hvm_bug(regs);
1874 if (invlpga)
1876 inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
1877 ASSERT(inst_len > 0);
1878 __update_guest_eip(vmcb, inst_len);
1880 /*
1881 * The address is implicit on this instruction At the moment, we don't
1882 * use ecx (ASID) to identify individual guests pages
1883 */
1884 g_vaddr = regs->eax;
1886 else
1888 /* What about multiple prefix codes? */
1889 prefix = (is_prefix(opcode[0])?opcode[0]:0);
1890 inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
1891 ASSERT(inst_len > 0);
1893 inst_len--;
1894 length -= inst_len;
1896 /*
1897 * Decode memory operand of the instruction including ModRM, SIB, and
1898 * displacement to get effecticve address and length in bytes. Assume
1899 * the system in either 32- or 64-bit mode.
1900 */
1901 g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
1902 &opcode[inst_len], &length);
1904 inst_len += length;
1905 __update_guest_eip (vmcb, inst_len);
1908 /* Overkill, we may not this */
1909 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1910 shadow_invlpg(v, g_vaddr);
1914 /*
1915 * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
1916 * 16-bit realmode. Basically, this mimics a processor reset.
1918 * returns 0 on success, non-zero otherwise
1919 */
1920 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
1921 struct cpu_user_regs *regs)
1923 struct vmcb_struct *vmcb;
1925 ASSERT(v);
1926 ASSERT(regs);
1928 vmcb = v->arch.hvm_svm.vmcb;
1930 ASSERT(vmcb);
1932 /* clear the vmcb and user regs */
1933 memset(regs, 0, sizeof(struct cpu_user_regs));
1935 /* VMCB Control */
1936 vmcb->tsc_offset = 0;
1938 /* VMCB State */
1939 vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
1940 v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
1942 vmcb->cr2 = 0;
1943 vmcb->efer = EFER_SVME;
1945 vmcb->cr4 = SVM_CR4_HOST_MASK;
1946 v->arch.hvm_svm.cpu_shadow_cr4 = 0;
1948 /* This will jump to ROMBIOS */
1949 vmcb->rip = 0xFFF0;
1951 /* setup the segment registers and all their hidden states */
1952 vmcb->cs.sel = 0xF000;
1953 vmcb->cs.attributes.bytes = 0x089b;
1954 vmcb->cs.limit = 0xffff;
1955 vmcb->cs.base = 0x000F0000;
1957 vmcb->ss.sel = 0x00;
1958 vmcb->ss.attributes.bytes = 0x0893;
1959 vmcb->ss.limit = 0xffff;
1960 vmcb->ss.base = 0x00;
1962 vmcb->ds.sel = 0x00;
1963 vmcb->ds.attributes.bytes = 0x0893;
1964 vmcb->ds.limit = 0xffff;
1965 vmcb->ds.base = 0x00;
1967 vmcb->es.sel = 0x00;
1968 vmcb->es.attributes.bytes = 0x0893;
1969 vmcb->es.limit = 0xffff;
1970 vmcb->es.base = 0x00;
1972 vmcb->fs.sel = 0x00;
1973 vmcb->fs.attributes.bytes = 0x0893;
1974 vmcb->fs.limit = 0xffff;
1975 vmcb->fs.base = 0x00;
1977 vmcb->gs.sel = 0x00;
1978 vmcb->gs.attributes.bytes = 0x0893;
1979 vmcb->gs.limit = 0xffff;
1980 vmcb->gs.base = 0x00;
1982 vmcb->ldtr.sel = 0x00;
1983 vmcb->ldtr.attributes.bytes = 0x0000;
1984 vmcb->ldtr.limit = 0x0;
1985 vmcb->ldtr.base = 0x00;
1987 vmcb->gdtr.sel = 0x00;
1988 vmcb->gdtr.attributes.bytes = 0x0000;
1989 vmcb->gdtr.limit = 0x0;
1990 vmcb->gdtr.base = 0x00;
1992 vmcb->tr.sel = 0;
1993 vmcb->tr.attributes.bytes = 0;
1994 vmcb->tr.limit = 0x0;
1995 vmcb->tr.base = 0;
1997 vmcb->idtr.sel = 0x00;
1998 vmcb->idtr.attributes.bytes = 0x0000;
1999 vmcb->idtr.limit = 0x3ff;
2000 vmcb->idtr.base = 0x00;
2002 vmcb->rax = 0;
2004 return 0;
2008 /*
2009 * svm_do_vmmcall - SVM VMMCALL handler
2011 * returns 0 on success, non-zero otherwise
2012 */
2013 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
2015 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2016 int inst_len;
2018 ASSERT(vmcb);
2019 ASSERT(regs);
2021 inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
2022 ASSERT(inst_len > 0);
2024 /* VMMCALL sanity check */
2025 if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
2027 printf("VMMCALL CPL check failed\n");
2028 return -1;
2031 /* handle the request */
2032 switch (regs->edi)
2034 case VMMCALL_RESET_TO_REALMODE:
2035 if (svm_do_vmmcall_reset_to_realmode(v, regs))
2037 printf("svm_do_vmmcall_reset_to_realmode() failed\n");
2038 return -1;
2041 /* since we just reset the VMCB, return without adjusting the eip */
2042 return 0;
2043 case VMMCALL_DEBUG:
2044 printf("DEBUG features not implemented yet\n");
2045 break;
2046 default:
2047 break;
2050 hvm_print_line(v, regs->eax); /* provides the current domain */
2052 __update_guest_eip(vmcb, inst_len);
2053 return 0;
2057 void svm_dump_inst(unsigned long eip)
2059 u8 opcode[256];
2060 unsigned long ptr;
2061 int len;
2062 int i;
2064 ptr = eip & ~0xff;
2065 len = 0;
2067 if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
2068 len = sizeof(opcode);
2070 printf("Code bytes around(len=%d) %lx:", len, eip);
2071 for (i = 0; i < len; i++)
2073 if ((i & 0x0f) == 0)
2074 printf("\n%08lx:", ptr+i);
2076 printf("%02x ", opcode[i]);
2079 printf("\n");
2083 void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
2085 struct vcpu *v = current;
2086 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2087 unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
2089 printf("%s: guest registers from %s:\n", __func__, from);
2090 #if defined (__x86_64__)
2091 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
2092 regs->rax, regs->rbx, regs->rcx);
2093 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
2094 regs->rdx, regs->rsi, regs->rdi);
2095 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
2096 regs->rbp, regs->rsp, regs->r8);
2097 printk("r9: %016lx r10: %016lx r11: %016lx\n",
2098 regs->r9, regs->r10, regs->r11);
2099 printk("r12: %016lx r13: %016lx r14: %016lx\n",
2100 regs->r12, regs->r13, regs->r14);
2101 printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
2102 regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
2103 #else
2104 printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
2105 regs->eax, regs->ebx, regs->ecx, regs->edx);
2106 printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
2107 regs->edi, regs->esi, regs->ebp, regs->esp);
2108 printf("%s: guest cr0: %lx\n", __func__,
2109 v->arch.hvm_svm.cpu_shadow_cr0);
2110 printf("guest CR3 = %llx\n", vmcb->cr3);
2111 #endif
2112 printf("%s: pt = %lx\n", __func__, pt);
2116 void svm_dump_host_regs(const char *from)
2118 struct vcpu *v = current;
2119 unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
2120 unsigned long cr3, cr0;
2121 printf("Host registers at %s\n", from);
2123 __asm__ __volatile__ ("\tmov %%cr0,%0\n"
2124 "\tmov %%cr3,%1\n"
2125 : "=r" (cr0), "=r"(cr3));
2126 printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
2129 #ifdef SVM_EXTRA_DEBUG
2130 static char *exit_reasons[] = {
2131 [VMEXIT_CR0_READ] = "CR0_READ",
2132 [VMEXIT_CR1_READ] = "CR1_READ",
2133 [VMEXIT_CR2_READ] = "CR2_READ",
2134 [VMEXIT_CR3_READ] = "CR3_READ",
2135 [VMEXIT_CR4_READ] = "CR4_READ",
2136 [VMEXIT_CR5_READ] = "CR5_READ",
2137 [VMEXIT_CR6_READ] = "CR6_READ",
2138 [VMEXIT_CR7_READ] = "CR7_READ",
2139 [VMEXIT_CR8_READ] = "CR8_READ",
2140 [VMEXIT_CR9_READ] = "CR9_READ",
2141 [VMEXIT_CR10_READ] = "CR10_READ",
2142 [VMEXIT_CR11_READ] = "CR11_READ",
2143 [VMEXIT_CR12_READ] = "CR12_READ",
2144 [VMEXIT_CR13_READ] = "CR13_READ",
2145 [VMEXIT_CR14_READ] = "CR14_READ",
2146 [VMEXIT_CR15_READ] = "CR15_READ",
2147 [VMEXIT_CR0_WRITE] = "CR0_WRITE",
2148 [VMEXIT_CR1_WRITE] = "CR1_WRITE",
2149 [VMEXIT_CR2_WRITE] = "CR2_WRITE",
2150 [VMEXIT_CR3_WRITE] = "CR3_WRITE",
2151 [VMEXIT_CR4_WRITE] = "CR4_WRITE",
2152 [VMEXIT_CR5_WRITE] = "CR5_WRITE",
2153 [VMEXIT_CR6_WRITE] = "CR6_WRITE",
2154 [VMEXIT_CR7_WRITE] = "CR7_WRITE",
2155 [VMEXIT_CR8_WRITE] = "CR8_WRITE",
2156 [VMEXIT_CR9_WRITE] = "CR9_WRITE",
2157 [VMEXIT_CR10_WRITE] = "CR10_WRITE",
2158 [VMEXIT_CR11_WRITE] = "CR11_WRITE",
2159 [VMEXIT_CR12_WRITE] = "CR12_WRITE",
2160 [VMEXIT_CR13_WRITE] = "CR13_WRITE",
2161 [VMEXIT_CR14_WRITE] = "CR14_WRITE",
2162 [VMEXIT_CR15_WRITE] = "CR15_WRITE",
2163 [VMEXIT_DR0_READ] = "DR0_READ",
2164 [VMEXIT_DR1_READ] = "DR1_READ",
2165 [VMEXIT_DR2_READ] = "DR2_READ",
2166 [VMEXIT_DR3_READ] = "DR3_READ",
2167 [VMEXIT_DR4_READ] = "DR4_READ",
2168 [VMEXIT_DR5_READ] = "DR5_READ",
2169 [VMEXIT_DR6_READ] = "DR6_READ",
2170 [VMEXIT_DR7_READ] = "DR7_READ",
2171 [VMEXIT_DR8_READ] = "DR8_READ",
2172 [VMEXIT_DR9_READ] = "DR9_READ",
2173 [VMEXIT_DR10_READ] = "DR10_READ",
2174 [VMEXIT_DR11_READ] = "DR11_READ",
2175 [VMEXIT_DR12_READ] = "DR12_READ",
2176 [VMEXIT_DR13_READ] = "DR13_READ",
2177 [VMEXIT_DR14_READ] = "DR14_READ",
2178 [VMEXIT_DR15_READ] = "DR15_READ",
2179 [VMEXIT_DR0_WRITE] = "DR0_WRITE",
2180 [VMEXIT_DR1_WRITE] = "DR1_WRITE",
2181 [VMEXIT_DR2_WRITE] = "DR2_WRITE",
2182 [VMEXIT_DR3_WRITE] = "DR3_WRITE",
2183 [VMEXIT_DR4_WRITE] = "DR4_WRITE",
2184 [VMEXIT_DR5_WRITE] = "DR5_WRITE",
2185 [VMEXIT_DR6_WRITE] = "DR6_WRITE",
2186 [VMEXIT_DR7_WRITE] = "DR7_WRITE",
2187 [VMEXIT_DR8_WRITE] = "DR8_WRITE",
2188 [VMEXIT_DR9_WRITE] = "DR9_WRITE",
2189 [VMEXIT_DR10_WRITE] = "DR10_WRITE",
2190 [VMEXIT_DR11_WRITE] = "DR11_WRITE",
2191 [VMEXIT_DR12_WRITE] = "DR12_WRITE",
2192 [VMEXIT_DR13_WRITE] = "DR13_WRITE",
2193 [VMEXIT_DR14_WRITE] = "DR14_WRITE",
2194 [VMEXIT_DR15_WRITE] = "DR15_WRITE",
2195 [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
2196 [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
2197 [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
2198 [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
2199 [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
2200 [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
2201 [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
2202 [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
2203 [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
2204 [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
2205 [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
2206 [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
2207 [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
2208 [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
2209 [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
2210 [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
2211 [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
2212 [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
2213 [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
2214 [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
2215 [VMEXIT_INTR] = "INTR",
2216 [VMEXIT_NMI] = "NMI",
2217 [VMEXIT_SMI] = "SMI",
2218 [VMEXIT_INIT] = "INIT",
2219 [VMEXIT_VINTR] = "VINTR",
2220 [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
2221 [VMEXIT_IDTR_READ] = "IDTR_READ",
2222 [VMEXIT_GDTR_READ] = "GDTR_READ",
2223 [VMEXIT_LDTR_READ] = "LDTR_READ",
2224 [VMEXIT_TR_READ] = "TR_READ",
2225 [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
2226 [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
2227 [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
2228 [VMEXIT_TR_WRITE] = "TR_WRITE",
2229 [VMEXIT_RDTSC] = "RDTSC",
2230 [VMEXIT_RDPMC] = "RDPMC",
2231 [VMEXIT_PUSHF] = "PUSHF",
2232 [VMEXIT_POPF] = "POPF",
2233 [VMEXIT_CPUID] = "CPUID",
2234 [VMEXIT_RSM] = "RSM",
2235 [VMEXIT_IRET] = "IRET",
2236 [VMEXIT_SWINT] = "SWINT",
2237 [VMEXIT_INVD] = "INVD",
2238 [VMEXIT_PAUSE] = "PAUSE",
2239 [VMEXIT_HLT] = "HLT",
2240 [VMEXIT_INVLPG] = "INVLPG",
2241 [VMEXIT_INVLPGA] = "INVLPGA",
2242 [VMEXIT_IOIO] = "IOIO",
2243 [VMEXIT_MSR] = "MSR",
2244 [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
2245 [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
2246 [VMEXIT_SHUTDOWN] = "SHUTDOWN",
2247 [VMEXIT_VMRUN] = "VMRUN",
2248 [VMEXIT_VMMCALL] = "VMMCALL",
2249 [VMEXIT_VMLOAD] = "VMLOAD",
2250 [VMEXIT_VMSAVE] = "VMSAVE",
2251 [VMEXIT_STGI] = "STGI",
2252 [VMEXIT_CLGI] = "CLGI",
2253 [VMEXIT_SKINIT] = "SKINIT",
2254 [VMEXIT_RDTSCP] = "RDTSCP",
2255 [VMEXIT_ICEBP] = "ICEBP",
2256 [VMEXIT_NPF] = "NPF"
2257 };
2258 #endif /* SVM_EXTRA_DEBUG */
2260 #ifdef SVM_WALK_GUEST_PAGES
2261 void walk_shadow_and_guest_pt(unsigned long gva)
2263 l2_pgentry_t gpde;
2264 l2_pgentry_t spde;
2265 l1_pgentry_t gpte;
2266 l1_pgentry_t spte;
2267 struct vcpu *v = current;
2268 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2269 unsigned long gpa;
2271 gpa = gva_to_gpa( gva );
2272 printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
2273 if( !svm_paging_enabled(v) || mmio_space(gpa) )
2274 return;
2276 /* let's dump the guest and shadow page info */
2278 __guest_get_l2e(v, gva, &gpde);
2279 printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
2280 __shadow_get_l2e( v, gva, &spde );
2281 printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
2283 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
2284 return;
2286 spte = l1e_empty();
2288 // This is actually overkill - we only need to make sure the hl2 is in-sync.
2289 shadow_sync_va(v, gva);
2291 gpte.l1 = 0;
2292 __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
2293 printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
2294 __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
2295 printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
2297 #endif /* SVM_WALK_GUEST_PAGES */
2299 asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
2301 unsigned int exit_reason;
2302 unsigned long eip;
2303 struct vcpu *v = current;
2304 int error;
2305 int do_debug = 0;
2306 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2308 ASSERT(vmcb);
2310 exit_reason = vmcb->exitcode;
2311 save_svm_cpu_user_regs(v, &regs);
2312 v->arch.hvm_svm.injecting_event = 0;
2314 vmcb->tlb_control = 1;
2316 #ifdef SVM_EXTRA_DEBUG
2318 #if defined(__i386__)
2319 #define rip eip
2320 #endif
2322 static unsigned long intercepts_counter = 0;
2324 if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
2326 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2328 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2329 intercepts_counter,
2330 exit_reasons[exit_reason], exit_reason, regs.cs,
2331 (unsigned long long) regs.rip,
2332 (unsigned long long) vmcb->exitinfo1,
2333 (unsigned long long) vmcb->exitinfo2,
2334 (unsigned long long) vmcb->exitintinfo.bytes);
2337 else if (svm_dbg_on
2338 && exit_reason != VMEXIT_IOIO
2339 && exit_reason != VMEXIT_INTR)
2342 if (exit_reasons[exit_reason])
2344 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2345 intercepts_counter,
2346 exit_reasons[exit_reason], exit_reason, regs.cs,
2347 (unsigned long long) regs.rip,
2348 (unsigned long long) vmcb->exitinfo1,
2349 (unsigned long long) vmcb->exitinfo2,
2350 (unsigned long long) vmcb->exitintinfo.bytes);
2352 else
2354 printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2355 intercepts_counter, exit_reason, exit_reason, regs.cs,
2356 (unsigned long long) regs.rip,
2357 (unsigned long long) vmcb->exitinfo1,
2358 (unsigned long long) vmcb->exitinfo2,
2359 (unsigned long long) vmcb->exitintinfo.bytes);
2363 #ifdef SVM_WALK_GUEST_PAGES
2364 if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
2366 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2367 walk_shadow_and_guest_pt( vmcb->exitinfo2 );
2369 #endif
2371 intercepts_counter++;
2373 #if 0
2374 if (svm_dbg_on)
2375 do_debug = svm_do_debugout(exit_reason);
2376 #endif
2378 if (do_debug)
2380 printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
2381 "shadow_table = 0x%08x\n",
2382 __func__,
2383 (int) v->arch.guest_table.pfn,
2384 (int) v->arch.monitor_table.pfn,
2385 (int) v->arch.shadow_table.pfn);
2387 svm_dump_vmcb(__func__, vmcb);
2388 svm_dump_regs(__func__, &regs);
2389 svm_dump_inst(svm_rip2pointer(vmcb));
2392 #if defined(__i386__)
2393 #undef rip
2394 #endif
2397 #endif /* SVM_EXTRA_DEBUG */
2399 if (exit_reason == -1)
2401 printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
2402 __func__);
2403 BUG();
2404 domain_crash_synchronous();
2407 perfc_incra(vmexits, exit_reason);
2408 eip = vmcb->rip;
2410 #ifdef SVM_EXTRA_DEBUG
2411 if (do_debug)
2413 printk("eip = %lx, exit_reason = %d (0x%x)\n",
2414 eip, exit_reason, exit_reason);
2416 #endif /* SVM_EXTRA_DEBUG */
2418 TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
2420 switch (exit_reason)
2422 case VMEXIT_EXCEPTION_DB:
2424 #ifdef XEN_DEBUGGER
2425 svm_debug_save_cpu_user_regs(&regs);
2426 pdb_handle_exception(1, &regs, 1);
2427 svm_debug_restore_cpu_user_regs(&regs);
2428 #else
2429 svm_store_cpu_user_regs(&regs, v);
2430 domain_pause_for_debugger();
2431 #endif
2433 break;
2435 case VMEXIT_NMI:
2436 do_nmi(&regs, 0);
2437 break;
2439 case VMEXIT_SMI:
2440 /*
2441 * For asynchronous SMI's, we just need to allow global interrupts
2442 * so that the SMI is taken properly in the context of the host. The
2443 * standard code does a STGI after the VMEXIT which should accomplish
2444 * this task. Continue as normal and restart the guest.
2445 */
2446 break;
2448 #ifdef XEN_DEBUGGER
2449 case VMEXIT_EXCEPTION_BP:
2450 svm_debug_save_cpu_user_regs(&regs);
2451 pdb_handle_exception(3, &regs, 1);
2452 svm_debug_restore_cpu_user_regs(&regs);
2453 break;
2454 #endif
2456 case VMEXIT_EXCEPTION_NM:
2457 svm_do_no_device_fault(vmcb);
2458 break;
2460 case VMEXIT_EXCEPTION_GP:
2461 /* This should probably not be trapped in the future */
2462 regs.error_code = vmcb->exitinfo1;
2463 v->arch.hvm_svm.injecting_event = 1;
2464 svm_do_general_protection_fault(v, &regs);
2465 break;
2467 case VMEXIT_EXCEPTION_PF:
2469 unsigned long va;
2470 va = vmcb->exitinfo2;
2471 regs.error_code = vmcb->exitinfo1;
2472 HVM_DBG_LOG(DBG_LEVEL_VMMU,
2473 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
2474 (unsigned long)regs.eax, (unsigned long)regs.ebx,
2475 (unsigned long)regs.ecx, (unsigned long)regs.edx,
2476 (unsigned long)regs.esi, (unsigned long)regs.edi);
2478 v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
2480 //printk("PF1\n");
2481 if (!(error = svm_do_page_fault(va, &regs)))
2483 v->arch.hvm_svm.injecting_event = 1;
2484 /* Inject #PG using Interruption-Information Fields */
2485 svm_inject_exception(vmcb, TRAP_page_fault, 1, regs.error_code);
2487 v->arch.hvm_svm.cpu_cr2 = va;
2488 vmcb->cr2 = va;
2489 TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
2490 VMEXIT_EXCEPTION_PF, va);
2492 break;
2495 case VMEXIT_EXCEPTION_DF:
2496 printk("Guest double fault");
2497 BUG();
2498 break;
2500 case VMEXIT_INTR:
2501 raise_softirq(SCHEDULE_SOFTIRQ);
2502 break;
2504 case VMEXIT_GDTR_WRITE:
2505 printk("WRITE to GDTR\n");
2506 break;
2508 case VMEXIT_TASK_SWITCH:
2509 __hvm_bug(&regs);
2510 break;
2512 case VMEXIT_CPUID:
2513 svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
2514 break;
2516 case VMEXIT_HLT:
2517 svm_vmexit_do_hlt(vmcb);
2518 break;
2520 case VMEXIT_INVLPG:
2521 svm_handle_invlpg(0, &regs);
2522 break;
2524 case VMEXIT_INVLPGA:
2525 svm_handle_invlpg(1, &regs);
2526 break;
2528 case VMEXIT_VMMCALL:
2529 svm_do_vmmcall(v, &regs);
2530 break;
2532 case VMEXIT_CR0_READ:
2533 svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
2534 break;
2536 case VMEXIT_CR2_READ:
2537 svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
2538 break;
2540 case VMEXIT_CR3_READ:
2541 svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
2542 break;
2544 case VMEXIT_CR4_READ:
2545 svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
2546 break;
2548 case VMEXIT_CR8_READ:
2549 svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
2550 break;
2552 case VMEXIT_CR0_WRITE:
2553 svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
2554 break;
2556 case VMEXIT_CR2_WRITE:
2557 svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
2558 break;
2560 case VMEXIT_CR3_WRITE:
2561 svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
2562 local_flush_tlb();
2563 break;
2565 case VMEXIT_CR4_WRITE:
2566 svm_cr_access(v, 4, TYPE_MOV_TO_CR, &regs);
2567 break;
2569 case VMEXIT_CR8_WRITE:
2570 svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
2571 break;
2573 case VMEXIT_DR0_READ:
2574 svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
2575 break;
2577 case VMEXIT_DR1_READ:
2578 svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
2579 break;
2581 case VMEXIT_DR2_READ:
2582 svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
2583 break;
2585 case VMEXIT_DR3_READ:
2586 svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
2587 break;
2589 case VMEXIT_DR6_READ:
2590 svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
2591 break;
2593 case VMEXIT_DR7_READ:
2594 svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
2595 break;
2597 case VMEXIT_DR0_WRITE:
2598 svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
2599 break;
2601 case VMEXIT_DR1_WRITE:
2602 svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
2603 break;
2605 case VMEXIT_DR2_WRITE:
2606 svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
2607 break;
2609 case VMEXIT_DR3_WRITE:
2610 svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
2611 break;
2613 case VMEXIT_DR6_WRITE:
2614 svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
2615 break;
2617 case VMEXIT_DR7_WRITE:
2618 svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
2619 break;
2621 case VMEXIT_IOIO:
2622 svm_io_instruction(v, &regs);
2623 break;
2625 case VMEXIT_MSR:
2626 svm_do_msr_access(v, &regs);
2627 break;
2629 case VMEXIT_SHUTDOWN:
2630 printk("Guest shutdown exit\n");
2631 domain_crash_synchronous();
2632 break;
2634 default:
2635 printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, "
2636 "exitinfo2 = %llx\n", exit_reason,
2637 (unsigned long long)vmcb->exitinfo1,
2638 (unsigned long long)vmcb->exitinfo2);
2639 __hvm_bug(&regs); /* should not happen */
2640 break;
2643 #ifdef SVM_EXTRA_DEBUG
2644 if (do_debug)
2646 printk("%s: Done switch on vmexit_code\n", __func__);
2647 svm_dump_regs(__func__, &regs);
2650 if (do_debug)
2652 printk("vmexit_handler():- guest_table = 0x%08x, "
2653 "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
2654 (int)v->arch.guest_table.pfn,
2655 (int)v->arch.monitor_table.pfn,
2656 (int)v->arch.shadow_table.pfn);
2657 printk("svm_vmexit_handler: Returning\n");
2659 #endif
2661 return;
2664 asmlinkage void svm_load_cr2(void)
2666 struct vcpu *v = current;
2668 local_irq_disable();
2669 #ifdef __i386__
2670 asm volatile("movl %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2671 #else
2672 asm volatile("movq %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2673 #endif
2676 asmlinkage void svm_asid(void)
2678 struct vcpu *v = current;
2679 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2681 /*
2682 * if need to assign new asid, or if switching cores,
2683 * retire asid for the old core, and assign a new asid to the current core.
2684 */
2685 if ( test_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ) ||
2686 ( v->arch.hvm_svm.asid_core != v->arch.hvm_svm.launch_core )) {
2687 /* recycle asid */
2688 if ( !asidpool_assign_next( vmcb, 1,
2689 v->arch.hvm_svm.asid_core, v->arch.hvm_svm.launch_core )) {
2690 /* If we get here, we have a major problem */
2691 domain_crash_synchronous();
2694 v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core;
2695 clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
2699 /*
2700 * Local variables:
2701 * mode: C
2702 * c-set-style: "BSD"
2703 * c-basic-offset: 4
2704 * tab-width: 4
2705 * indent-tabs-mode: nil
2706 * End:
2707 */