ia64/xen-unstable

view xen/arch/x86/hvm/svm/svm.c @ 9702:cff23e96eae7

SVM patch to add add init intercept handler.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Apr 13 11:00:54 2006 +0100 (2006-04-13)
parents aa13ac536dec
children 9849bd4a86dd
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 int svm_realmode(struct vcpu *v)
386 {
387 unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
388 unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
390 return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
391 }
393 int svm_instruction_length(struct vcpu *v)
394 {
395 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
396 unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
397 /* check which operating mode the guest is running */
398 if( vmcb->efer & EFER_LMA )
399 mode = vmcb->cs.attributes.fields.l ? 8 : 4;
400 else
401 mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
402 return svm_instrlen(guest_cpu_user_regs(), mode);
403 }
405 unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
406 {
407 switch ( num )
408 {
409 case 0:
410 return v->arch.hvm_svm.cpu_shadow_cr0;
411 case 2:
412 return v->arch.hvm_svm.cpu_cr2;
413 case 3:
414 return v->arch.hvm_svm.cpu_cr3;
415 default:
416 BUG();
417 }
418 return 0; /* dummy */
419 }
421 int start_svm(void)
422 {
423 u32 eax, ecx, edx;
425 /* Xen does not fill x86_capability words except 0. */
426 ecx = cpuid_ecx(0x80000001);
427 boot_cpu_data.x86_capability[5] = ecx;
429 if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
430 return 0;
432 rdmsr(MSR_EFER, eax, edx);
433 eax |= EFER_SVME;
434 wrmsr(MSR_EFER, eax, edx);
435 asidpool_init(smp_processor_id());
436 printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
438 /* Setup HVM interfaces */
439 hvm_funcs.disable = stop_svm;
441 hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
442 hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
444 hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
445 hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
447 hvm_funcs.realmode = svm_realmode;
448 hvm_funcs.paging_enabled = svm_paging_enabled;
449 hvm_funcs.instruction_length = svm_instruction_length;
450 hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
452 hvm_enabled = 1;
454 return 1;
455 }
457 int svm_dbg_on = 0;
459 static inline int svm_do_debugout(unsigned long exit_code)
460 {
461 int i;
463 static unsigned long counter = 0;
464 static unsigned long works[] =
465 {
466 VMEXIT_IOIO,
467 VMEXIT_HLT,
468 VMEXIT_CPUID,
469 VMEXIT_DR0_READ,
470 VMEXIT_DR1_READ,
471 VMEXIT_DR2_READ,
472 VMEXIT_DR3_READ,
473 VMEXIT_DR6_READ,
474 VMEXIT_DR7_READ,
475 VMEXIT_DR0_WRITE,
476 VMEXIT_DR1_WRITE,
477 VMEXIT_DR2_WRITE,
478 VMEXIT_DR3_WRITE,
479 VMEXIT_CR0_READ,
480 VMEXIT_CR0_WRITE,
481 VMEXIT_CR3_READ,
482 VMEXIT_CR4_READ,
483 VMEXIT_MSR,
484 VMEXIT_CR0_WRITE,
485 VMEXIT_CR3_WRITE,
486 VMEXIT_CR4_WRITE,
487 VMEXIT_EXCEPTION_PF,
488 VMEXIT_INTR,
489 VMEXIT_INVLPG,
490 VMEXIT_EXCEPTION_NM
491 };
494 #if 0
495 if (svm_dbg_on && exit_code != 0x7B)
496 return 1;
497 #endif
499 counter++;
501 #if 0
502 if ((exit_code == 0x4E
503 || exit_code == VMEXIT_CR0_READ
504 || exit_code == VMEXIT_CR0_WRITE)
505 && counter < 200000)
506 return 0;
508 if ((exit_code == 0x4E) && counter < 500000)
509 return 0;
510 #endif
512 for (i = 0; i < sizeof(works) / sizeof(works[0]); i++)
513 if (exit_code == works[i])
514 return 0;
516 return 1;
517 }
520 void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
521 {
522 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
524 ASSERT(vmcb);
526 ctxt->eax = vmcb->rax;
527 ctxt->ss = vmcb->ss.sel;
528 ctxt->esp = vmcb->rsp;
529 ctxt->eflags = vmcb->rflags;
530 ctxt->cs = vmcb->cs.sel;
531 ctxt->eip = vmcb->rip;
533 ctxt->gs = vmcb->gs.sel;
534 ctxt->fs = vmcb->fs.sel;
535 ctxt->es = vmcb->es.sel;
536 ctxt->ds = vmcb->ds.sel;
537 }
539 #if defined (__x86_64__)
540 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v )
541 {
542 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
544 regs->rip = vmcb->rip;
545 regs->rsp = vmcb->rsp;
546 regs->rflags = vmcb->rflags;
547 regs->cs = vmcb->cs.sel;
548 regs->ds = vmcb->ds.sel;
549 regs->es = vmcb->es.sel;
550 regs->ss = vmcb->ss.sel;
551 }
552 #elif defined (__i386__)
553 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
554 {
555 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
557 regs->eip = vmcb->rip;
558 regs->esp = vmcb->rsp;
559 regs->eflags = vmcb->rflags;
560 regs->cs = vmcb->cs.sel;
561 regs->ds = vmcb->ds.sel;
562 regs->es = vmcb->es.sel;
563 regs->ss = vmcb->ss.sel;
564 }
565 #endif
567 /* XXX Use svm_load_cpu_guest_regs instead */
568 #if defined (__i386__)
569 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
570 {
571 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
572 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
574 /* Write the guest register value into VMCB */
575 vmcb->rax = regs->eax;
576 vmcb->ss.sel = regs->ss;
577 vmcb->rsp = regs->esp;
578 vmcb->rflags = regs->eflags;
579 vmcb->cs.sel = regs->cs;
580 vmcb->rip = regs->eip;
581 if (regs->eflags & EF_TF)
582 *intercepts |= EXCEPTION_BITMAP_DB;
583 else
584 *intercepts &= ~EXCEPTION_BITMAP_DB;
585 }
586 #else /* (__i386__) */
587 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
588 {
589 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
590 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
592 /* Write the guest register value into VMCB */
593 vmcb->rax = regs->rax;
594 vmcb->ss.sel = regs->ss;
595 vmcb->rsp = regs->rsp;
596 vmcb->rflags = regs->rflags;
597 vmcb->cs.sel = regs->cs;
598 vmcb->rip = regs->rip;
599 if (regs->rflags & EF_TF)
600 *intercepts |= EXCEPTION_BITMAP_DB;
601 else
602 *intercepts &= ~EXCEPTION_BITMAP_DB;
603 }
604 #endif /* !(__i386__) */
606 int svm_paging_enabled(struct vcpu *v)
607 {
608 unsigned long cr0;
610 cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
612 return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
613 }
616 /* Make sure that xen intercepts any FP accesses from current */
617 void svm_stts(struct vcpu *v)
618 {
619 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
621 /* FPU state already dirty? Then no need to setup_fpu() lazily. */
622 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
623 return;
625 /*
626 * If the guest does not have TS enabled then we must cause and handle an
627 * exception on first use of the FPU. If the guest *does* have TS enabled
628 * then this is not necessary: no FPU activity can occur until the guest
629 * clears CR0.TS, and we will initialise the FPU when that happens.
630 */
631 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
632 {
633 v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
634 vmcb->cr0 |= X86_CR0_TS;
635 }
636 }
638 static void arch_svm_do_launch(struct vcpu *v)
639 {
640 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
641 int error;
643 #if 0
644 if (svm_dbg_on)
645 printk("Do launch\n");
646 #endif
647 error = construct_vmcb(&v->arch.hvm_svm, regs);
648 if ( error < 0 )
649 {
650 if (v->vcpu_id == 0) {
651 printk("Failed to construct a new VMCB for BSP.\n");
652 } else {
653 printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
654 }
655 domain_crash_synchronous();
656 }
658 svm_do_launch(v);
659 #if 0
660 if (svm_dbg_on)
661 svm_dump_host_regs(__func__);
662 #endif
663 reset_stack_and_jump(svm_asm_do_launch);
664 }
666 static void svm_freeze_time(struct vcpu *v)
667 {
668 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
670 if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
671 v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v);
672 stop_timer(&(vpit->pit_timer));
673 }
674 }
676 static void svm_ctxt_switch_from(struct vcpu *v)
677 {
678 svm_freeze_time(v);
679 }
681 static void svm_ctxt_switch_to(struct vcpu *v)
682 {
683 }
685 void svm_final_setup_guest(struct vcpu *v)
686 {
687 v->arch.schedule_tail = arch_svm_do_launch;
688 v->arch.ctxt_switch_from = svm_ctxt_switch_from;
689 v->arch.ctxt_switch_to = svm_ctxt_switch_to;
691 if (v == v->domain->vcpu[0])
692 {
693 struct domain *d = v->domain;
694 struct vcpu *vc;
696 /* Initialize monitor page table */
697 for_each_vcpu(d, vc)
698 vc->arch.monitor_table = mk_pagetable(0);
700 /*
701 * Required to do this once per domain
702 * TODO: add a seperate function to do these.
703 */
704 memset(&d->shared_info->evtchn_mask[0], 0xff,
705 sizeof(d->shared_info->evtchn_mask));
707 /*
708 * Put the domain in shadow mode even though we're going to be using
709 * the shared 1:1 page table initially. It shouldn't hurt
710 */
711 shadow_mode_enable(d,
712 SHM_enable|SHM_refcounts|
713 SHM_translate|SHM_external|SHM_wr_pt_pte);
714 }
715 }
718 static void svm_relinquish_guest_resources(struct domain *d)
719 {
720 extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
721 struct vcpu *v;
723 for_each_vcpu ( d, v )
724 {
725 if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
726 continue;
727 #if 0
728 /* Memory leak by not freeing this. XXXKAF: *Why* is not per core?? */
729 free_host_save_area(v->arch.hvm_svm.host_save_area);
730 #endif
732 destroy_vmcb(&v->arch.hvm_svm);
733 free_monitor_pagetable(v);
734 kill_timer(&v->arch.hvm_svm.hlt_timer);
735 if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
736 {
737 kill_timer( &(VLAPIC(v)->vlapic_timer) );
738 xfree(VLAPIC(v));
739 }
740 }
742 kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
744 if ( d->arch.hvm_domain.shared_page_va )
745 unmap_domain_page_global(
746 (void *)d->arch.hvm_domain.shared_page_va);
748 shadow_direct_map_clean(d);
749 }
752 void arch_svm_do_resume(struct vcpu *v)
753 {
754 /* pinning VCPU to a different core? */
755 if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
756 svm_do_resume( v );
757 reset_stack_and_jump( svm_asm_do_resume );
758 }
759 else {
760 printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() );
761 v->arch.hvm_svm.launch_core = smp_processor_id();
762 svm_migrate_timers( v );
763 svm_do_resume( v );
764 reset_stack_and_jump( svm_asm_do_resume );
765 }
766 }
769 void svm_migrate_timers(struct vcpu *v)
770 {
771 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
773 migrate_timer( &vpit->pit_timer, v->processor );
774 migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
775 if ( hvm_apic_support(v->domain) && VLAPIC( v ))
776 migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
777 }
780 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
781 {
782 struct vcpu *v = current;
783 unsigned long eip;
784 unsigned long gpa; /* FIXME: PAE */
785 int result;
786 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
788 ASSERT(vmcb);
790 //#if HVM_DEBUG
791 eip = vmcb->rip;
792 HVM_DBG_LOG(DBG_LEVEL_VMMU,
793 "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
794 va, eip, (unsigned long)regs->error_code);
795 //#endif
797 if ( !svm_paging_enabled(v) )
798 {
799 if ( shadow_direct_map_fault(va, regs) )
800 return 1;
802 handle_mmio(va, va);
803 TRACE_VMEXIT(2,2);
804 return 1;
805 }
808 gpa = gva_to_gpa(va);
810 /* Use 1:1 page table to identify MMIO address space */
811 if (mmio_space(gpa))
812 {
813 /* No support for APIC */
814 if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
815 {
816 int inst_len;
817 inst_len = svm_instruction_length(v);
818 if (inst_len == -1)
819 {
820 printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
821 domain_crash_synchronous();
822 }
824 __update_guest_eip(vmcb, inst_len);
826 return 1;
827 }
829 TRACE_VMEXIT (2,2);
830 handle_mmio(va, gpa);
832 return 1;
833 }
835 result = shadow_fault(va, regs);
837 if( result ) {
838 /* Let's make sure that the Guest TLB is flushed */
839 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
840 }
842 TRACE_VMEXIT (2,result);
844 return result;
845 }
848 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
849 {
850 struct vcpu *v = current;
852 setup_fpu(v);
853 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
855 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
856 vmcb->cr0 &= ~X86_CR0_TS;
857 }
860 static void svm_do_general_protection_fault(struct vcpu *v,
861 struct cpu_user_regs *regs)
862 {
863 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
864 unsigned long eip, error_code;
866 ASSERT(vmcb);
868 eip = vmcb->rip;
869 error_code = vmcb->exitinfo1;
871 if (vmcb->idtr.limit == 0) {
872 printf("Huh? We got a GP Fault with an invalid IDTR!\n");
873 svm_dump_vmcb(__func__, vmcb);
874 svm_dump_regs(__func__, regs);
875 svm_dump_inst(vmcb->rip);
876 __hvm_bug(regs);
877 }
879 HVM_DBG_LOG(DBG_LEVEL_1,
880 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
881 eip, error_code);
883 HVM_DBG_LOG(DBG_LEVEL_1,
884 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
885 (unsigned long)regs->eax, (unsigned long)regs->ebx,
886 (unsigned long)regs->ecx, (unsigned long)regs->edx,
887 (unsigned long)regs->esi, (unsigned long)regs->edi);
890 /* Reflect it back into the guest */
891 svm_inject_exception(vmcb, TRAP_gp_fault, 1, error_code);
892 }
894 /* Reserved bits: [31:14], [12:1] */
895 #define SVM_VCPU_CPUID_L1_RESERVED 0xffffdffe
897 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
898 struct cpu_user_regs *regs)
899 {
900 unsigned int eax, ebx, ecx, edx;
901 unsigned long eip;
902 struct vcpu *v = current;
903 int inst_len;
905 ASSERT(vmcb);
907 eip = vmcb->rip;
909 HVM_DBG_LOG(DBG_LEVEL_1,
910 "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
911 " (esi) %lx, (edi) %lx",
912 (unsigned long)regs->eax, (unsigned long)regs->ebx,
913 (unsigned long)regs->ecx, (unsigned long)regs->edx,
914 (unsigned long)regs->esi, (unsigned long)regs->edi);
916 cpuid(input, &eax, &ebx, &ecx, &edx);
918 if (input == 1)
919 {
920 if ( !hvm_apic_support(v->domain) ||
921 !vlapic_global_enabled((VLAPIC(v))) )
922 clear_bit(X86_FEATURE_APIC, &edx);
924 #if CONFIG_PAGING_LEVELS < 3
925 clear_bit(X86_FEATURE_PAE, &edx);
926 clear_bit(X86_FEATURE_PSE, &edx);
927 clear_bit(X86_FEATURE_PSE36, &edx);
928 #else
929 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
930 {
931 if ( !v->domain->arch.hvm_domain.pae_enabled )
932 clear_bit(X86_FEATURE_PAE, &edx);
933 clear_bit(X86_FEATURE_PSE, &edx);
934 clear_bit(X86_FEATURE_PSE36, &edx);
935 }
936 #endif
938 /* Clear out reserved bits. */
939 ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
940 clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
941 }
942 #ifdef __i386__
943 else if ( input == 0x80000001 )
944 {
945 /* Mask feature for Intel ia32e or AMD long mode. */
946 clear_bit(X86_FEATURE_LM & 31, &edx);
947 }
948 #endif
950 regs->eax = (unsigned long)eax;
951 regs->ebx = (unsigned long)ebx;
952 regs->ecx = (unsigned long)ecx;
953 regs->edx = (unsigned long)edx;
955 HVM_DBG_LOG(DBG_LEVEL_1,
956 "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
957 "ebx=%x, ecx=%x, edx=%x",
958 eip, input, eax, ebx, ecx, edx);
960 inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
961 ASSERT(inst_len > 0);
962 __update_guest_eip(vmcb, inst_len);
963 }
966 static inline unsigned long *get_reg_p(unsigned int gpreg,
967 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
968 {
969 unsigned long *reg_p = NULL;
970 switch (gpreg)
971 {
972 case SVM_REG_EAX:
973 reg_p = (unsigned long *)&regs->eax;
974 break;
975 case SVM_REG_EBX:
976 reg_p = (unsigned long *)&regs->ebx;
977 break;
978 case SVM_REG_ECX:
979 reg_p = (unsigned long *)&regs->ecx;
980 break;
981 case SVM_REG_EDX:
982 reg_p = (unsigned long *)&regs->edx;
983 break;
984 case SVM_REG_EDI:
985 reg_p = (unsigned long *)&regs->edi;
986 break;
987 case SVM_REG_ESI:
988 reg_p = (unsigned long *)&regs->esi;
989 break;
990 case SVM_REG_EBP:
991 reg_p = (unsigned long *)&regs->ebp;
992 break;
993 case SVM_REG_ESP:
994 reg_p = (unsigned long *)&vmcb->rsp;
995 break;
996 #if __x86_64__
997 case SVM_REG_R8:
998 reg_p = (unsigned long *)&regs->r8;
999 break;
1000 case SVM_REG_R9:
1001 reg_p = (unsigned long *)&regs->r9;
1002 break;
1003 case SVM_REG_R10:
1004 reg_p = (unsigned long *)&regs->r10;
1005 break;
1006 case SVM_REG_R11:
1007 reg_p = (unsigned long *)&regs->r11;
1008 break;
1009 case SVM_REG_R12:
1010 reg_p = (unsigned long *)&regs->r12;
1011 break;
1012 case SVM_REG_R13:
1013 reg_p = (unsigned long *)&regs->r13;
1014 break;
1015 case SVM_REG_R14:
1016 reg_p = (unsigned long *)&regs->r14;
1017 break;
1018 case SVM_REG_R15:
1019 reg_p = (unsigned long *)&regs->r15;
1020 break;
1021 #endif
1022 default:
1023 BUG();
1026 return reg_p;
1030 static inline unsigned long get_reg(unsigned int gpreg,
1031 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1033 unsigned long *gp;
1034 gp = get_reg_p(gpreg, regs, vmcb);
1035 return *gp;
1039 static inline void set_reg(unsigned int gpreg, unsigned long value,
1040 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1042 unsigned long *gp;
1043 gp = get_reg_p(gpreg, regs, vmcb);
1044 *gp = value;
1048 static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
1049 struct cpu_user_regs *regs)
1051 unsigned long *reg_p = 0;
1052 unsigned int gpreg = 0;
1053 unsigned long eip;
1054 int inst_len;
1055 int index;
1056 struct vmcb_struct *vmcb;
1057 u8 buffer[MAX_INST_LEN];
1058 u8 prefix = 0;
1060 vmcb = v->arch.hvm_svm.vmcb;
1062 ASSERT(vmcb);
1064 eip = vmcb->rip;
1065 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1066 index = skip_prefix_bytes(buffer, sizeof(buffer));
1068 ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
1070 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
1071 prefix = buffer[index-1];
1073 gpreg = decode_src_reg(prefix, buffer[index + 2]);
1074 ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
1076 HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
1077 eip, reg, gpreg);
1079 reg_p = get_reg_p(gpreg, regs, vmcb);
1081 switch (type)
1083 case TYPE_MOV_TO_DR:
1084 inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
1085 v->arch.guest_context.debugreg[reg] = *reg_p;
1086 break;
1087 case TYPE_MOV_FROM_DR:
1088 inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
1089 *reg_p = v->arch.guest_context.debugreg[reg];
1090 break;
1091 default:
1092 __hvm_bug(regs);
1093 break;
1095 ASSERT(inst_len > 0);
1096 __update_guest_eip(vmcb, inst_len);
1100 static unsigned int check_for_null_selector(struct vmcb_struct *vmcb,
1101 unsigned int dir, unsigned long *base, unsigned int real)
1104 unsigned char inst[MAX_INST_LEN];
1105 segment_selector_t seg;
1106 int i;
1108 memset(inst, 0, MAX_INST_LEN);
1109 if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
1110 != MAX_INST_LEN)
1112 printk("check_for_null_selector: get guest instruction failed\n");
1113 domain_crash_synchronous();
1116 for (i = 0; i < MAX_INST_LEN; i++)
1118 switch (inst[i])
1120 case 0xf3: /* REPZ */
1121 case 0xf2: /* REPNZ */
1122 case 0xf0: /* LOCK */
1123 case 0x66: /* data32 */
1124 case 0x67: /* addr32 */
1125 #if __x86_64__
1126 /* REX prefixes */
1127 case 0x40:
1128 case 0x41:
1129 case 0x42:
1130 case 0x43:
1131 case 0x44:
1132 case 0x45:
1133 case 0x46:
1134 case 0x47:
1136 case 0x48:
1137 case 0x49:
1138 case 0x4a:
1139 case 0x4b:
1140 case 0x4c:
1141 case 0x4d:
1142 case 0x4e:
1143 case 0x4f:
1144 #endif
1145 continue;
1146 case 0x2e: /* CS */
1147 seg = vmcb->cs;
1148 break;
1149 case 0x36: /* SS */
1150 seg = vmcb->ss;
1151 break;
1152 case 0x26: /* ES */
1153 seg = vmcb->es;
1154 break;
1155 case 0x64: /* FS */
1156 seg = vmcb->fs;
1157 break;
1158 case 0x65: /* GS */
1159 seg = vmcb->gs;
1160 break;
1161 case 0x3e: /* DS */
1162 /* FALLTHROUGH */
1163 seg = vmcb->ds;
1164 break;
1165 default:
1166 if (dir == IOREQ_READ) /* IN/INS instruction? */
1167 seg = vmcb->es;
1168 else
1169 seg = vmcb->ds;
1172 if (base)
1173 *base = seg.base;
1175 return seg.attributes.fields.p;
1178 ASSERT(0);
1179 return 0;
1183 /* Get the address of INS/OUTS instruction */
1184 static inline unsigned long svm_get_io_address(struct vmcb_struct *vmcb,
1185 struct cpu_user_regs *regs, unsigned int dir, unsigned int real)
1187 unsigned long addr = 0;
1188 unsigned long base = 0;
1190 check_for_null_selector(vmcb, dir, &base, real);
1192 if (dir == IOREQ_WRITE)
1194 if (real)
1195 addr = (regs->esi & 0xFFFF) + base;
1196 else
1197 addr = regs->esi + base;
1199 else
1201 if (real)
1202 addr = (regs->edi & 0xFFFF) + base;
1203 else
1204 addr = regs->edi + base;
1207 return addr;
1211 static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs)
1213 struct mmio_op *mmio_opp;
1214 unsigned long eip, cs, eflags, cr0;
1215 unsigned long port;
1216 unsigned int real, size, dir;
1217 ioio_info_t info;
1219 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1221 ASSERT(vmcb);
1222 mmio_opp = &current->arch.hvm_vcpu.mmio_op;
1223 mmio_opp->instr = INSTR_PIO;
1224 mmio_opp->flags = 0;
1226 eip = vmcb->rip;
1227 cs = vmcb->cs.sel;
1228 eflags = vmcb->rflags;
1230 info.bytes = vmcb->exitinfo1;
1232 port = info.fields.port; /* port used to be addr */
1233 dir = info.fields.type; /* direction */
1234 if (info.fields.sz32)
1235 size = 4;
1236 else if (info.fields.sz16)
1237 size = 2;
1238 else
1239 size = 1;
1241 cr0 = vmcb->cr0;
1242 real = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
1244 HVM_DBG_LOG(DBG_LEVEL_IO,
1245 "svm_io_instruction: port 0x%lx real %d, eip=%lx:%lx, "
1246 "exit_qualification = %lx",
1247 (unsigned long) port, real, cs, eip, (unsigned long)info.bytes);
1248 /* string instruction */
1249 if (info.fields.str)
1251 unsigned long addr, count = 1;
1252 int sign = regs->eflags & EF_DF ? -1 : 1;
1254 /* Need the original rip, here. */
1255 addr = svm_get_io_address(vmcb, regs, dir, real);
1257 /* "rep" prefix */
1258 if (info.fields.rep)
1260 mmio_opp->flags |= REPZ;
1261 count = real ? regs->ecx & 0xFFFF : regs->ecx;
1264 /*
1265 * Handle string pio instructions that cross pages or that
1266 * are unaligned. See the comments in hvm_platform.c/handle_mmio()
1267 */
1268 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
1270 unsigned long value = 0;
1272 mmio_opp->flags |= OVERLAP;
1274 if (dir == IOREQ_WRITE)
1275 hvm_copy(&value, addr, size, HVM_COPY_IN);
1277 send_pio_req(regs, port, 1, size, value, dir, 0);
1279 else
1281 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
1283 if (sign > 0)
1284 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
1285 else
1286 count = (addr & ~PAGE_MASK) / size;
1288 else
1289 vmcb->rip = vmcb->exitinfo2;
1291 send_pio_req(regs, port, count, size, addr, dir, 1);
1294 else
1296 /*
1297 * On SVM, the RIP of the intruction following the IN/OUT is saved in
1298 * ExitInfo2
1299 */
1300 vmcb->rip = vmcb->exitinfo2;
1302 if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
1303 hvm_print_line(v, regs->eax); /* guest debug output */
1305 send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
1309 static int svm_set_cr0(unsigned long value)
1311 struct vcpu *v = current;
1312 unsigned long mfn;
1313 int paging_enabled;
1314 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1315 unsigned long crn;
1317 ASSERT(vmcb);
1319 /* We don't want to lose PG. ET is reserved and should be always be 1*/
1320 paging_enabled = svm_paging_enabled(v);
1321 value |= X86_CR0_ET;
1322 vmcb->cr0 = value | X86_CR0_PG;
1323 v->arch.hvm_svm.cpu_shadow_cr0 = value;
1325 /* TS cleared? Then initialise FPU now. */
1326 if ( !(value & X86_CR0_TS) )
1328 setup_fpu(v);
1329 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1332 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
1334 if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
1336 /* The guest CR3 must be pointing to the guest physical. */
1337 if (!VALID_MFN(mfn =
1338 get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
1339 || !get_page(mfn_to_page(mfn), v->domain))
1341 printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
1342 domain_crash_synchronous(); /* need to take a clean path */
1345 #if defined(__x86_64__)
1346 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
1347 && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
1348 &v->arch.hvm_svm.cpu_state))
1350 HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
1351 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1354 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
1356 /* Here the PAE is should to be opened */
1357 HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
1358 set_bit(SVM_CPU_STATE_LMA_ENABLED,
1359 &v->arch.hvm_svm.cpu_state);
1360 vmcb->efer |= (EFER_LMA | EFER_LME);
1362 #if CONFIG_PAGING_LEVELS >= 4
1363 if (!shadow_set_guest_paging_levels(v->domain, 4))
1365 printk("Unsupported guest paging levels\n");
1366 domain_crash_synchronous(); /* need to take a clean path */
1368 #endif
1370 else
1371 #endif /* __x86_64__ */
1373 #if CONFIG_PAGING_LEVELS >= 3
1374 if (!shadow_set_guest_paging_levels(v->domain, 2))
1376 printk("Unsupported guest paging levels\n");
1377 domain_crash_synchronous(); /* need to take a clean path */
1379 #endif
1382 /* update CR4's PAE if needed */
1383 crn = vmcb->cr4;
1384 if ((!(crn & X86_CR4_PAE))
1385 && test_bit(SVM_CPU_STATE_PAE_ENABLED,
1386 &v->arch.hvm_svm.cpu_state))
1388 HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
1389 vmcb->cr4 |= X86_CR4_PAE;
1392 /* Now arch.guest_table points to machine physical. */
1393 v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
1394 update_pagetables(v);
1396 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
1397 (unsigned long) (mfn << PAGE_SHIFT));
1399 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1400 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1402 /* arch->shadow_table should hold the next CR3 for shadow */
1403 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
1404 v->arch.hvm_svm.cpu_cr3, mfn);
1407 /*
1408 * SVM implements paged real-mode and when we return to real-mode
1409 * we revert back to the physical mappings that the domain builder
1410 * created.
1411 */
1412 if ((value & X86_CR0_PE) == 0) {
1413 if (value & X86_CR0_PG) {
1414 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1415 return 0;
1418 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1419 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
1422 return 1;
1425 /*
1426 * Read from control registers. CR0 and CR4 are read from the shadow.
1427 */
1428 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
1430 unsigned long value = 0;
1431 struct vcpu *v = current;
1432 struct vmcb_struct *vmcb;
1434 vmcb = v->arch.hvm_svm.vmcb;
1435 ASSERT(vmcb);
1437 switch (cr)
1439 case 0:
1440 value = v->arch.hvm_svm.cpu_shadow_cr0;
1441 break;
1442 case 2:
1443 value = vmcb->cr2;
1444 break;
1445 case 3:
1446 value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
1447 break;
1448 case 4:
1449 value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
1450 break;
1451 case 8:
1452 #if 0
1453 value = vmcb->m_cr8;
1454 #else
1455 ASSERT(0);
1456 #endif
1457 break;
1459 default:
1460 __hvm_bug(regs);
1463 set_reg(gp, value, regs, vmcb);
1465 HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
1469 /*
1470 * Write to control registers
1471 */
1472 static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
1474 unsigned long value;
1475 unsigned long old_cr;
1476 struct vcpu *v = current;
1477 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1479 ASSERT(vmcb);
1481 value = get_reg(gpreg, regs, vmcb);
1483 HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
1484 HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
1486 switch (cr)
1488 case 0:
1489 return svm_set_cr0(value);
1491 case 3:
1493 unsigned long old_base_mfn, mfn;
1495 /* If paging is not enabled yet, simply copy the value to CR3. */
1496 if (!svm_paging_enabled(v)) {
1497 v->arch.hvm_svm.cpu_cr3 = value;
1498 break;
1500 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1502 /* We make a new one if the shadow does not exist. */
1503 if (value == v->arch.hvm_svm.cpu_cr3)
1505 /*
1506 * This is simple TLB flush, implying the guest has
1507 * removed some translation or changed page attributes.
1508 * We simply invalidate the shadow.
1509 */
1510 mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
1511 if (mfn != pagetable_get_pfn(v->arch.guest_table))
1512 __hvm_bug(regs);
1513 shadow_sync_all(v->domain);
1515 else
1517 /*
1518 * If different, make a shadow. Check if the PDBR is valid
1519 * first.
1520 */
1521 HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
1522 if (((value >> PAGE_SHIFT) > v->domain->max_pages)
1523 || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
1524 || !get_page(mfn_to_page(mfn), v->domain))
1526 printk("Invalid CR3 value=%lx\n", value);
1527 domain_crash_synchronous(); /* need to take a clean path */
1530 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1531 v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
1533 if (old_base_mfn)
1534 put_page(mfn_to_page(old_base_mfn));
1536 update_pagetables(v);
1538 /* arch.shadow_table should now hold the next CR3 for shadow*/
1539 v->arch.hvm_svm.cpu_cr3 = value;
1540 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
1541 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1543 break;
1546 case 4:
1547 /* CR4 */
1548 if (value & X86_CR4_PAE) {
1549 set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
1550 } else {
1551 if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
1552 &v->arch.hvm_svm.cpu_state)) {
1553 svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
1555 clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
1558 old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
1559 v->arch.hvm_svm.cpu_shadow_cr4 = value;
1560 vmcb->cr4 = value | SVM_CR4_HOST_MASK;
1562 /*
1563 * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
1564 * all TLB entries except global entries.
1565 */
1566 if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
1568 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1569 shadow_sync_all(v->domain);
1571 break;
1573 default:
1574 printk("invalid cr: %d\n", cr);
1575 __hvm_bug(regs);
1578 return 1;
1582 #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
1585 static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
1586 struct cpu_user_regs *regs)
1588 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1589 int inst_len = 0;
1590 int index;
1591 unsigned int gpreg;
1592 unsigned long value;
1593 u8 buffer[MAX_INST_LEN];
1594 u8 prefix = 0;
1595 int result = 1;
1596 enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
1597 enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
1598 enum instruction_index match;
1600 ASSERT(vmcb);
1602 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1603 /* get index to first actual instruction byte - as we will need to know where the
1604 * prefix lives later on
1605 */
1606 index = skip_prefix_bytes(buffer, sizeof(buffer));
1608 if (type == TYPE_MOV_TO_CR)
1610 inst_len = __get_instruction_length_from_list(vmcb, list_a,
1611 ARR_SIZE(list_a), &buffer[index], &match);
1613 else
1615 inst_len = __get_instruction_length_from_list(vmcb, list_b,
1616 ARR_SIZE(list_b), &buffer[index], &match);
1619 ASSERT(inst_len > 0);
1621 inst_len += index;
1623 /* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */
1624 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
1625 prefix = buffer[index-1];
1627 HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
1629 switch (match)
1631 case INSTR_MOV2CR:
1632 gpreg = decode_src_reg(prefix, buffer[index+2]);
1633 result = mov_to_cr(gpreg, cr, regs);
1634 break;
1636 case INSTR_MOVCR2:
1637 gpreg = decode_src_reg(prefix, buffer[index+2]);
1638 mov_from_cr(cr, gpreg, regs);
1639 break;
1641 case INSTR_CLTS:
1642 /* TS being cleared means that it's time to restore fpu state. */
1643 setup_fpu(current);
1644 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1645 vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
1646 v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
1647 break;
1649 case INSTR_LMSW:
1650 if (svm_dbg_on)
1651 svm_dump_inst(svm_rip2pointer(vmcb));
1653 gpreg = decode_src_reg(prefix, buffer[index+2]);
1654 value = get_reg(gpreg, regs, vmcb) & 0xF;
1656 if (svm_dbg_on)
1657 printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1658 inst_len);
1660 value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
1662 if (svm_dbg_on)
1663 printk("CR0-LMSW CR0 - New value=%lx\n", value);
1665 result = svm_set_cr0(value);
1666 break;
1668 case INSTR_SMSW:
1669 svm_dump_inst(svm_rip2pointer(vmcb));
1670 value = v->arch.hvm_svm.cpu_shadow_cr0;
1671 gpreg = decode_src_reg(prefix, buffer[index+2]);
1672 set_reg(gpreg, value, regs, vmcb);
1674 if (svm_dbg_on)
1675 printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1676 inst_len);
1677 break;
1679 default:
1680 __hvm_bug(regs);
1681 break;
1684 ASSERT(inst_len);
1686 __update_guest_eip(vmcb, inst_len);
1688 return result;
1691 static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
1693 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1694 int inst_len;
1695 u64 msr_content=0;
1697 ASSERT(vmcb);
1699 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
1700 "exitinfo = %lx", (unsigned long)regs->ecx,
1701 (unsigned long)regs->eax, (unsigned long)regs->edx,
1702 (unsigned long)vmcb->exitinfo1);
1704 /* is it a read? */
1705 if (vmcb->exitinfo1 == 0)
1707 inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
1709 regs->edx = 0;
1710 switch (regs->ecx) {
1711 case MSR_IA32_TIME_STAMP_COUNTER:
1713 struct hvm_virpit *vpit;
1715 rdtscll(msr_content);
1716 vpit = &(v->domain->arch.hvm_domain.vpit);
1717 msr_content += vpit->cache_tsc_offset;
1718 break;
1720 case MSR_IA32_SYSENTER_CS:
1721 msr_content = vmcb->sysenter_cs;
1722 break;
1723 case MSR_IA32_SYSENTER_ESP:
1724 msr_content = vmcb->sysenter_esp;
1725 break;
1726 case MSR_IA32_SYSENTER_EIP:
1727 msr_content = vmcb->sysenter_eip;
1728 break;
1729 case MSR_IA32_APICBASE:
1730 msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
1731 break;
1732 default:
1733 if (long_mode_do_msr_read(regs))
1734 goto done;
1735 rdmsr_safe(regs->ecx, regs->eax, regs->edx);
1736 break;
1738 regs->eax = msr_content & 0xFFFFFFFF;
1739 regs->edx = msr_content >> 32;
1741 else
1743 inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
1744 msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32);
1746 switch (regs->ecx)
1748 case MSR_IA32_TIME_STAMP_COUNTER:
1749 svm_set_guest_time(v, msr_content);
1750 break;
1751 case MSR_IA32_SYSENTER_CS:
1752 vmcb->sysenter_cs = msr_content;
1753 break;
1754 case MSR_IA32_SYSENTER_ESP:
1755 vmcb->sysenter_esp = msr_content;
1756 break;
1757 case MSR_IA32_SYSENTER_EIP:
1758 vmcb->sysenter_eip = msr_content;
1759 break;
1760 case MSR_IA32_APICBASE:
1761 vlapic_msr_set(VLAPIC(v), msr_content);
1762 break;
1763 default:
1764 long_mode_do_msr_write(regs);
1765 break;
1769 done:
1771 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
1772 "ecx=%lx, eax=%lx, edx=%lx",
1773 (unsigned long)regs->ecx, (unsigned long)regs->eax,
1774 (unsigned long)regs->edx);
1776 __update_guest_eip(vmcb, inst_len);
1780 /*
1781 * Need to use this exit to reschedule
1782 */
1783 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
1785 struct vcpu *v = current;
1786 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
1787 s_time_t next_pit = -1, next_wakeup;
1789 __update_guest_eip(vmcb, 1);
1791 /* check for interrupt not handled or new interrupt */
1792 if ( vmcb->vintr.fields.irq || cpu_has_pending_irq(v) )
1793 return;
1795 if ( !v->vcpu_id )
1796 next_pit = get_pit_scheduled(v, vpit);
1797 next_wakeup = get_apictime_scheduled(v);
1798 if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
1799 next_wakeup = next_pit;
1800 if ( next_wakeup != - 1 )
1801 set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
1802 hvm_safe_block();
1806 static inline void svm_vmexit_do_mwait(void)
1811 #ifdef XEN_DEBUGGER
1812 static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
1813 struct cpu_user_regs *regs)
1815 regs->eip = vmcb->rip;
1816 regs->esp = vmcb->rsp;
1817 regs->eflags = vmcb->rflags;
1819 regs->xcs = vmcb->cs.sel;
1820 regs->xds = vmcb->ds.sel;
1821 regs->xes = vmcb->es.sel;
1822 regs->xfs = vmcb->fs.sel;
1823 regs->xgs = vmcb->gs.sel;
1824 regs->xss = vmcb->ss.sel;
1828 static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
1830 vmcb->ss.sel = regs->xss;
1831 vmcb->rsp = regs->esp;
1832 vmcb->rflags = regs->eflags;
1833 vmcb->cs.sel = regs->xcs;
1834 vmcb->rip = regs->eip;
1836 vmcb->gs.sel = regs->xgs;
1837 vmcb->fs.sel = regs->xfs;
1838 vmcb->es.sel = regs->xes;
1839 vmcb->ds.sel = regs->xds;
1841 #endif
1844 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
1846 struct vcpu *v = current;
1847 u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
1848 unsigned long g_vaddr;
1849 int inst_len;
1850 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1852 ASSERT(vmcb);
1853 /*
1854 * Unknown how many bytes the invlpg instruction will take. Use the
1855 * maximum instruction length here
1856 */
1857 if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
1859 printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
1860 __hvm_bug(regs);
1863 if (invlpga)
1865 inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
1866 ASSERT(inst_len > 0);
1867 __update_guest_eip(vmcb, inst_len);
1869 /*
1870 * The address is implicit on this instruction At the moment, we don't
1871 * use ecx (ASID) to identify individual guests pages
1872 */
1873 g_vaddr = regs->eax;
1875 else
1877 /* What about multiple prefix codes? */
1878 prefix = (is_prefix(opcode[0])?opcode[0]:0);
1879 inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
1880 ASSERT(inst_len > 0);
1882 inst_len--;
1883 length -= inst_len;
1885 /*
1886 * Decode memory operand of the instruction including ModRM, SIB, and
1887 * displacement to get effecticve address and length in bytes. Assume
1888 * the system in either 32- or 64-bit mode.
1889 */
1890 g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
1891 &opcode[inst_len], &length);
1893 inst_len += length;
1894 __update_guest_eip (vmcb, inst_len);
1897 /* Overkill, we may not this */
1898 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1899 shadow_invlpg(v, g_vaddr);
1903 /*
1904 * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
1905 * 16-bit realmode. Basically, this mimics a processor reset.
1907 * returns 0 on success, non-zero otherwise
1908 */
1909 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
1910 struct cpu_user_regs *regs)
1912 struct vmcb_struct *vmcb;
1914 ASSERT(v);
1915 ASSERT(regs);
1917 vmcb = v->arch.hvm_svm.vmcb;
1919 ASSERT(vmcb);
1921 /* clear the vmcb and user regs */
1922 memset(regs, 0, sizeof(struct cpu_user_regs));
1924 /* VMCB Control */
1925 vmcb->tsc_offset = 0;
1927 /* VMCB State */
1928 vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
1929 v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
1931 vmcb->cr2 = 0;
1932 vmcb->efer = EFER_SVME;
1934 vmcb->cr4 = SVM_CR4_HOST_MASK;
1935 v->arch.hvm_svm.cpu_shadow_cr4 = 0;
1937 /* This will jump to ROMBIOS */
1938 vmcb->rip = 0xFFF0;
1940 /* setup the segment registers and all their hidden states */
1941 vmcb->cs.sel = 0xF000;
1942 vmcb->cs.attributes.bytes = 0x089b;
1943 vmcb->cs.limit = 0xffff;
1944 vmcb->cs.base = 0x000F0000;
1946 vmcb->ss.sel = 0x00;
1947 vmcb->ss.attributes.bytes = 0x0893;
1948 vmcb->ss.limit = 0xffff;
1949 vmcb->ss.base = 0x00;
1951 vmcb->ds.sel = 0x00;
1952 vmcb->ds.attributes.bytes = 0x0893;
1953 vmcb->ds.limit = 0xffff;
1954 vmcb->ds.base = 0x00;
1956 vmcb->es.sel = 0x00;
1957 vmcb->es.attributes.bytes = 0x0893;
1958 vmcb->es.limit = 0xffff;
1959 vmcb->es.base = 0x00;
1961 vmcb->fs.sel = 0x00;
1962 vmcb->fs.attributes.bytes = 0x0893;
1963 vmcb->fs.limit = 0xffff;
1964 vmcb->fs.base = 0x00;
1966 vmcb->gs.sel = 0x00;
1967 vmcb->gs.attributes.bytes = 0x0893;
1968 vmcb->gs.limit = 0xffff;
1969 vmcb->gs.base = 0x00;
1971 vmcb->ldtr.sel = 0x00;
1972 vmcb->ldtr.attributes.bytes = 0x0000;
1973 vmcb->ldtr.limit = 0x0;
1974 vmcb->ldtr.base = 0x00;
1976 vmcb->gdtr.sel = 0x00;
1977 vmcb->gdtr.attributes.bytes = 0x0000;
1978 vmcb->gdtr.limit = 0x0;
1979 vmcb->gdtr.base = 0x00;
1981 vmcb->tr.sel = 0;
1982 vmcb->tr.attributes.bytes = 0;
1983 vmcb->tr.limit = 0x0;
1984 vmcb->tr.base = 0;
1986 vmcb->idtr.sel = 0x00;
1987 vmcb->idtr.attributes.bytes = 0x0000;
1988 vmcb->idtr.limit = 0x3ff;
1989 vmcb->idtr.base = 0x00;
1991 vmcb->rax = 0;
1993 return 0;
1997 /*
1998 * svm_do_vmmcall - SVM VMMCALL handler
2000 * returns 0 on success, non-zero otherwise
2001 */
2002 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
2004 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2005 int inst_len;
2007 ASSERT(vmcb);
2008 ASSERT(regs);
2010 inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
2011 ASSERT(inst_len > 0);
2013 /* VMMCALL sanity check */
2014 if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
2016 printf("VMMCALL CPL check failed\n");
2017 return -1;
2020 /* handle the request */
2021 switch (regs->edi)
2023 case VMMCALL_RESET_TO_REALMODE:
2024 if (svm_do_vmmcall_reset_to_realmode(v, regs))
2026 printf("svm_do_vmmcall_reset_to_realmode() failed\n");
2027 return -1;
2030 /* since we just reset the VMCB, return without adjusting the eip */
2031 return 0;
2032 case VMMCALL_DEBUG:
2033 printf("DEBUG features not implemented yet\n");
2034 break;
2035 default:
2036 break;
2039 hvm_print_line(v, regs->eax); /* provides the current domain */
2041 __update_guest_eip(vmcb, inst_len);
2042 return 0;
2046 void svm_dump_inst(unsigned long eip)
2048 u8 opcode[256];
2049 unsigned long ptr;
2050 int len;
2051 int i;
2053 ptr = eip & ~0xff;
2054 len = 0;
2056 if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
2057 len = sizeof(opcode);
2059 printf("Code bytes around(len=%d) %lx:", len, eip);
2060 for (i = 0; i < len; i++)
2062 if ((i & 0x0f) == 0)
2063 printf("\n%08lx:", ptr+i);
2065 printf("%02x ", opcode[i]);
2068 printf("\n");
2072 void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
2074 struct vcpu *v = current;
2075 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2076 unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
2078 printf("%s: guest registers from %s:\n", __func__, from);
2079 #if defined (__x86_64__)
2080 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
2081 regs->rax, regs->rbx, regs->rcx);
2082 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
2083 regs->rdx, regs->rsi, regs->rdi);
2084 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
2085 regs->rbp, regs->rsp, regs->r8);
2086 printk("r9: %016lx r10: %016lx r11: %016lx\n",
2087 regs->r9, regs->r10, regs->r11);
2088 printk("r12: %016lx r13: %016lx r14: %016lx\n",
2089 regs->r12, regs->r13, regs->r14);
2090 printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
2091 regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
2092 #else
2093 printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
2094 regs->eax, regs->ebx, regs->ecx, regs->edx);
2095 printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
2096 regs->edi, regs->esi, regs->ebp, regs->esp);
2097 printf("%s: guest cr0: %lx\n", __func__,
2098 v->arch.hvm_svm.cpu_shadow_cr0);
2099 printf("guest CR3 = %llx\n", vmcb->cr3);
2100 #endif
2101 printf("%s: pt = %lx\n", __func__, pt);
2105 void svm_dump_host_regs(const char *from)
2107 struct vcpu *v = current;
2108 unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
2109 unsigned long cr3, cr0;
2110 printf("Host registers at %s\n", from);
2112 __asm__ __volatile__ ("\tmov %%cr0,%0\n"
2113 "\tmov %%cr3,%1\n"
2114 : "=r" (cr0), "=r"(cr3));
2115 printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
2118 #ifdef SVM_EXTRA_DEBUG
2119 static char *exit_reasons[] = {
2120 [VMEXIT_CR0_READ] = "CR0_READ",
2121 [VMEXIT_CR1_READ] = "CR1_READ",
2122 [VMEXIT_CR2_READ] = "CR2_READ",
2123 [VMEXIT_CR3_READ] = "CR3_READ",
2124 [VMEXIT_CR4_READ] = "CR4_READ",
2125 [VMEXIT_CR5_READ] = "CR5_READ",
2126 [VMEXIT_CR6_READ] = "CR6_READ",
2127 [VMEXIT_CR7_READ] = "CR7_READ",
2128 [VMEXIT_CR8_READ] = "CR8_READ",
2129 [VMEXIT_CR9_READ] = "CR9_READ",
2130 [VMEXIT_CR10_READ] = "CR10_READ",
2131 [VMEXIT_CR11_READ] = "CR11_READ",
2132 [VMEXIT_CR12_READ] = "CR12_READ",
2133 [VMEXIT_CR13_READ] = "CR13_READ",
2134 [VMEXIT_CR14_READ] = "CR14_READ",
2135 [VMEXIT_CR15_READ] = "CR15_READ",
2136 [VMEXIT_CR0_WRITE] = "CR0_WRITE",
2137 [VMEXIT_CR1_WRITE] = "CR1_WRITE",
2138 [VMEXIT_CR2_WRITE] = "CR2_WRITE",
2139 [VMEXIT_CR3_WRITE] = "CR3_WRITE",
2140 [VMEXIT_CR4_WRITE] = "CR4_WRITE",
2141 [VMEXIT_CR5_WRITE] = "CR5_WRITE",
2142 [VMEXIT_CR6_WRITE] = "CR6_WRITE",
2143 [VMEXIT_CR7_WRITE] = "CR7_WRITE",
2144 [VMEXIT_CR8_WRITE] = "CR8_WRITE",
2145 [VMEXIT_CR9_WRITE] = "CR9_WRITE",
2146 [VMEXIT_CR10_WRITE] = "CR10_WRITE",
2147 [VMEXIT_CR11_WRITE] = "CR11_WRITE",
2148 [VMEXIT_CR12_WRITE] = "CR12_WRITE",
2149 [VMEXIT_CR13_WRITE] = "CR13_WRITE",
2150 [VMEXIT_CR14_WRITE] = "CR14_WRITE",
2151 [VMEXIT_CR15_WRITE] = "CR15_WRITE",
2152 [VMEXIT_DR0_READ] = "DR0_READ",
2153 [VMEXIT_DR1_READ] = "DR1_READ",
2154 [VMEXIT_DR2_READ] = "DR2_READ",
2155 [VMEXIT_DR3_READ] = "DR3_READ",
2156 [VMEXIT_DR4_READ] = "DR4_READ",
2157 [VMEXIT_DR5_READ] = "DR5_READ",
2158 [VMEXIT_DR6_READ] = "DR6_READ",
2159 [VMEXIT_DR7_READ] = "DR7_READ",
2160 [VMEXIT_DR8_READ] = "DR8_READ",
2161 [VMEXIT_DR9_READ] = "DR9_READ",
2162 [VMEXIT_DR10_READ] = "DR10_READ",
2163 [VMEXIT_DR11_READ] = "DR11_READ",
2164 [VMEXIT_DR12_READ] = "DR12_READ",
2165 [VMEXIT_DR13_READ] = "DR13_READ",
2166 [VMEXIT_DR14_READ] = "DR14_READ",
2167 [VMEXIT_DR15_READ] = "DR15_READ",
2168 [VMEXIT_DR0_WRITE] = "DR0_WRITE",
2169 [VMEXIT_DR1_WRITE] = "DR1_WRITE",
2170 [VMEXIT_DR2_WRITE] = "DR2_WRITE",
2171 [VMEXIT_DR3_WRITE] = "DR3_WRITE",
2172 [VMEXIT_DR4_WRITE] = "DR4_WRITE",
2173 [VMEXIT_DR5_WRITE] = "DR5_WRITE",
2174 [VMEXIT_DR6_WRITE] = "DR6_WRITE",
2175 [VMEXIT_DR7_WRITE] = "DR7_WRITE",
2176 [VMEXIT_DR8_WRITE] = "DR8_WRITE",
2177 [VMEXIT_DR9_WRITE] = "DR9_WRITE",
2178 [VMEXIT_DR10_WRITE] = "DR10_WRITE",
2179 [VMEXIT_DR11_WRITE] = "DR11_WRITE",
2180 [VMEXIT_DR12_WRITE] = "DR12_WRITE",
2181 [VMEXIT_DR13_WRITE] = "DR13_WRITE",
2182 [VMEXIT_DR14_WRITE] = "DR14_WRITE",
2183 [VMEXIT_DR15_WRITE] = "DR15_WRITE",
2184 [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
2185 [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
2186 [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
2187 [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
2188 [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
2189 [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
2190 [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
2191 [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
2192 [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
2193 [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
2194 [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
2195 [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
2196 [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
2197 [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
2198 [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
2199 [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
2200 [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
2201 [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
2202 [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
2203 [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
2204 [VMEXIT_INTR] = "INTR",
2205 [VMEXIT_NMI] = "NMI",
2206 [VMEXIT_SMI] = "SMI",
2207 [VMEXIT_INIT] = "INIT",
2208 [VMEXIT_VINTR] = "VINTR",
2209 [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
2210 [VMEXIT_IDTR_READ] = "IDTR_READ",
2211 [VMEXIT_GDTR_READ] = "GDTR_READ",
2212 [VMEXIT_LDTR_READ] = "LDTR_READ",
2213 [VMEXIT_TR_READ] = "TR_READ",
2214 [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
2215 [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
2216 [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
2217 [VMEXIT_TR_WRITE] = "TR_WRITE",
2218 [VMEXIT_RDTSC] = "RDTSC",
2219 [VMEXIT_RDPMC] = "RDPMC",
2220 [VMEXIT_PUSHF] = "PUSHF",
2221 [VMEXIT_POPF] = "POPF",
2222 [VMEXIT_CPUID] = "CPUID",
2223 [VMEXIT_RSM] = "RSM",
2224 [VMEXIT_IRET] = "IRET",
2225 [VMEXIT_SWINT] = "SWINT",
2226 [VMEXIT_INVD] = "INVD",
2227 [VMEXIT_PAUSE] = "PAUSE",
2228 [VMEXIT_HLT] = "HLT",
2229 [VMEXIT_INVLPG] = "INVLPG",
2230 [VMEXIT_INVLPGA] = "INVLPGA",
2231 [VMEXIT_IOIO] = "IOIO",
2232 [VMEXIT_MSR] = "MSR",
2233 [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
2234 [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
2235 [VMEXIT_SHUTDOWN] = "SHUTDOWN",
2236 [VMEXIT_VMRUN] = "VMRUN",
2237 [VMEXIT_VMMCALL] = "VMMCALL",
2238 [VMEXIT_VMLOAD] = "VMLOAD",
2239 [VMEXIT_VMSAVE] = "VMSAVE",
2240 [VMEXIT_STGI] = "STGI",
2241 [VMEXIT_CLGI] = "CLGI",
2242 [VMEXIT_SKINIT] = "SKINIT",
2243 [VMEXIT_RDTSCP] = "RDTSCP",
2244 [VMEXIT_ICEBP] = "ICEBP",
2245 [VMEXIT_NPF] = "NPF"
2246 };
2247 #endif /* SVM_EXTRA_DEBUG */
2249 #ifdef SVM_WALK_GUEST_PAGES
2250 void walk_shadow_and_guest_pt(unsigned long gva)
2252 l2_pgentry_t gpde;
2253 l2_pgentry_t spde;
2254 l1_pgentry_t gpte;
2255 l1_pgentry_t spte;
2256 struct vcpu *v = current;
2257 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2258 unsigned long gpa;
2260 gpa = gva_to_gpa( gva );
2261 printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
2262 if( !svm_paging_enabled(v) || mmio_space(gpa) )
2263 return;
2265 /* let's dump the guest and shadow page info */
2267 __guest_get_l2e(v, gva, &gpde);
2268 printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
2269 __shadow_get_l2e( v, gva, &spde );
2270 printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
2272 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
2273 return;
2275 spte = l1e_empty();
2277 // This is actually overkill - we only need to make sure the hl2 is in-sync.
2278 shadow_sync_va(v, gva);
2280 gpte.l1 = 0;
2281 __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
2282 printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
2283 __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
2284 printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
2286 #endif /* SVM_WALK_GUEST_PAGES */
2288 asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
2290 unsigned int exit_reason;
2291 unsigned long eip;
2292 struct vcpu *v = current;
2293 int error;
2294 int do_debug = 0;
2295 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2297 ASSERT(vmcb);
2299 exit_reason = vmcb->exitcode;
2300 save_svm_cpu_user_regs(v, &regs);
2301 v->arch.hvm_svm.injecting_event = 0;
2303 vmcb->tlb_control = 1;
2305 #ifdef SVM_EXTRA_DEBUG
2307 #if defined(__i386__)
2308 #define rip eip
2309 #endif
2311 static unsigned long intercepts_counter = 0;
2313 if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
2315 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2317 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2318 intercepts_counter,
2319 exit_reasons[exit_reason], exit_reason, regs.cs,
2320 (unsigned long long) regs.rip,
2321 (unsigned long long) vmcb->exitinfo1,
2322 (unsigned long long) vmcb->exitinfo2,
2323 (unsigned long long) vmcb->exitintinfo.bytes);
2326 else if (svm_dbg_on
2327 && exit_reason != VMEXIT_IOIO
2328 && exit_reason != VMEXIT_INTR)
2331 if (exit_reasons[exit_reason])
2333 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2334 intercepts_counter,
2335 exit_reasons[exit_reason], exit_reason, regs.cs,
2336 (unsigned long long) regs.rip,
2337 (unsigned long long) vmcb->exitinfo1,
2338 (unsigned long long) vmcb->exitinfo2,
2339 (unsigned long long) vmcb->exitintinfo.bytes);
2341 else
2343 printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2344 intercepts_counter, exit_reason, exit_reason, regs.cs,
2345 (unsigned long long) regs.rip,
2346 (unsigned long long) vmcb->exitinfo1,
2347 (unsigned long long) vmcb->exitinfo2,
2348 (unsigned long long) vmcb->exitintinfo.bytes);
2352 #ifdef SVM_WALK_GUEST_PAGES
2353 if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
2355 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2356 walk_shadow_and_guest_pt( vmcb->exitinfo2 );
2358 #endif
2360 intercepts_counter++;
2362 #if 0
2363 if (svm_dbg_on)
2364 do_debug = svm_do_debugout(exit_reason);
2365 #endif
2367 if (do_debug)
2369 printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
2370 "shadow_table = 0x%08x\n",
2371 __func__,
2372 (int) v->arch.guest_table.pfn,
2373 (int) v->arch.monitor_table.pfn,
2374 (int) v->arch.shadow_table.pfn);
2376 svm_dump_vmcb(__func__, vmcb);
2377 svm_dump_regs(__func__, &regs);
2378 svm_dump_inst(svm_rip2pointer(vmcb));
2381 #if defined(__i386__)
2382 #undef rip
2383 #endif
2386 #endif /* SVM_EXTRA_DEBUG */
2388 if (exit_reason == -1)
2390 printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
2391 __func__);
2392 BUG();
2393 domain_crash_synchronous();
2396 perfc_incra(vmexits, exit_reason);
2397 eip = vmcb->rip;
2399 #ifdef SVM_EXTRA_DEBUG
2400 if (do_debug)
2402 printk("eip = %lx, exit_reason = %d (0x%x)\n",
2403 eip, exit_reason, exit_reason);
2405 #endif /* SVM_EXTRA_DEBUG */
2407 TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
2409 switch (exit_reason)
2411 case VMEXIT_EXCEPTION_DB:
2413 #ifdef XEN_DEBUGGER
2414 svm_debug_save_cpu_user_regs(&regs);
2415 pdb_handle_exception(1, &regs, 1);
2416 svm_debug_restore_cpu_user_regs(&regs);
2417 #else
2418 svm_store_cpu_user_regs(&regs, v);
2419 domain_pause_for_debugger();
2420 #endif
2422 break;
2424 case VMEXIT_NMI:
2425 do_nmi(&regs, 0);
2426 break;
2428 case VMEXIT_SMI:
2429 /*
2430 * For asynchronous SMI's, we just need to allow global interrupts
2431 * so that the SMI is taken properly in the context of the host. The
2432 * standard code does a STGI after the VMEXIT which should accomplish
2433 * this task. Continue as normal and restart the guest.
2434 */
2435 break;
2437 case VMEXIT_INIT:
2438 /*
2439 * Nothing to do, in fact we should never get to this point.
2440 */
2441 break;
2443 #ifdef XEN_DEBUGGER
2444 case VMEXIT_EXCEPTION_BP:
2445 svm_debug_save_cpu_user_regs(&regs);
2446 pdb_handle_exception(3, &regs, 1);
2447 svm_debug_restore_cpu_user_regs(&regs);
2448 break;
2449 #endif
2451 case VMEXIT_EXCEPTION_NM:
2452 svm_do_no_device_fault(vmcb);
2453 break;
2455 case VMEXIT_EXCEPTION_GP:
2456 /* This should probably not be trapped in the future */
2457 regs.error_code = vmcb->exitinfo1;
2458 v->arch.hvm_svm.injecting_event = 1;
2459 svm_do_general_protection_fault(v, &regs);
2460 break;
2462 case VMEXIT_EXCEPTION_PF:
2464 unsigned long va;
2465 va = vmcb->exitinfo2;
2466 regs.error_code = vmcb->exitinfo1;
2467 HVM_DBG_LOG(DBG_LEVEL_VMMU,
2468 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
2469 (unsigned long)regs.eax, (unsigned long)regs.ebx,
2470 (unsigned long)regs.ecx, (unsigned long)regs.edx,
2471 (unsigned long)regs.esi, (unsigned long)regs.edi);
2473 v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
2475 //printk("PF1\n");
2476 if (!(error = svm_do_page_fault(va, &regs)))
2478 v->arch.hvm_svm.injecting_event = 1;
2479 /* Inject #PG using Interruption-Information Fields */
2480 svm_inject_exception(vmcb, TRAP_page_fault, 1, regs.error_code);
2482 v->arch.hvm_svm.cpu_cr2 = va;
2483 vmcb->cr2 = va;
2484 TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
2485 VMEXIT_EXCEPTION_PF, va);
2487 break;
2490 case VMEXIT_EXCEPTION_DF:
2491 printk("Guest double fault");
2492 BUG();
2493 break;
2495 case VMEXIT_INTR:
2496 raise_softirq(SCHEDULE_SOFTIRQ);
2497 break;
2499 case VMEXIT_GDTR_WRITE:
2500 printk("WRITE to GDTR\n");
2501 break;
2503 case VMEXIT_TASK_SWITCH:
2504 __hvm_bug(&regs);
2505 break;
2507 case VMEXIT_CPUID:
2508 svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
2509 break;
2511 case VMEXIT_HLT:
2512 svm_vmexit_do_hlt(vmcb);
2513 break;
2515 case VMEXIT_INVLPG:
2516 svm_handle_invlpg(0, &regs);
2517 break;
2519 case VMEXIT_INVLPGA:
2520 svm_handle_invlpg(1, &regs);
2521 break;
2523 case VMEXIT_VMMCALL:
2524 svm_do_vmmcall(v, &regs);
2525 break;
2527 case VMEXIT_CR0_READ:
2528 svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
2529 break;
2531 case VMEXIT_CR2_READ:
2532 svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
2533 break;
2535 case VMEXIT_CR3_READ:
2536 svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
2537 break;
2539 case VMEXIT_CR4_READ:
2540 svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
2541 break;
2543 case VMEXIT_CR8_READ:
2544 svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
2545 break;
2547 case VMEXIT_CR0_WRITE:
2548 svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
2549 break;
2551 case VMEXIT_CR2_WRITE:
2552 svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
2553 break;
2555 case VMEXIT_CR3_WRITE:
2556 svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
2557 local_flush_tlb();
2558 break;
2560 case VMEXIT_CR4_WRITE:
2561 svm_cr_access(v, 4, TYPE_MOV_TO_CR, &regs);
2562 break;
2564 case VMEXIT_CR8_WRITE:
2565 svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
2566 break;
2568 case VMEXIT_DR0_READ:
2569 svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
2570 break;
2572 case VMEXIT_DR1_READ:
2573 svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
2574 break;
2576 case VMEXIT_DR2_READ:
2577 svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
2578 break;
2580 case VMEXIT_DR3_READ:
2581 svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
2582 break;
2584 case VMEXIT_DR6_READ:
2585 svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
2586 break;
2588 case VMEXIT_DR7_READ:
2589 svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
2590 break;
2592 case VMEXIT_DR0_WRITE:
2593 svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
2594 break;
2596 case VMEXIT_DR1_WRITE:
2597 svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
2598 break;
2600 case VMEXIT_DR2_WRITE:
2601 svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
2602 break;
2604 case VMEXIT_DR3_WRITE:
2605 svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
2606 break;
2608 case VMEXIT_DR6_WRITE:
2609 svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
2610 break;
2612 case VMEXIT_DR7_WRITE:
2613 svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
2614 break;
2616 case VMEXIT_IOIO:
2617 svm_io_instruction(v, &regs);
2618 break;
2620 case VMEXIT_MSR:
2621 svm_do_msr_access(v, &regs);
2622 break;
2624 case VMEXIT_SHUTDOWN:
2625 printk("Guest shutdown exit\n");
2626 domain_crash_synchronous();
2627 break;
2629 default:
2630 printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, "
2631 "exitinfo2 = %llx\n", exit_reason,
2632 (unsigned long long)vmcb->exitinfo1,
2633 (unsigned long long)vmcb->exitinfo2);
2634 __hvm_bug(&regs); /* should not happen */
2635 break;
2638 #ifdef SVM_EXTRA_DEBUG
2639 if (do_debug)
2641 printk("%s: Done switch on vmexit_code\n", __func__);
2642 svm_dump_regs(__func__, &regs);
2645 if (do_debug)
2647 printk("vmexit_handler():- guest_table = 0x%08x, "
2648 "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
2649 (int)v->arch.guest_table.pfn,
2650 (int)v->arch.monitor_table.pfn,
2651 (int)v->arch.shadow_table.pfn);
2652 printk("svm_vmexit_handler: Returning\n");
2654 #endif
2656 return;
2659 asmlinkage void svm_load_cr2(void)
2661 struct vcpu *v = current;
2663 local_irq_disable();
2664 #ifdef __i386__
2665 asm volatile("movl %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2666 #else
2667 asm volatile("movq %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2668 #endif
2671 asmlinkage void svm_asid(void)
2673 struct vcpu *v = current;
2674 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2676 /*
2677 * if need to assign new asid, or if switching cores,
2678 * retire asid for the old core, and assign a new asid to the current core.
2679 */
2680 if ( test_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ) ||
2681 ( v->arch.hvm_svm.asid_core != v->arch.hvm_svm.launch_core )) {
2682 /* recycle asid */
2683 if ( !asidpool_assign_next( vmcb, 1,
2684 v->arch.hvm_svm.asid_core, v->arch.hvm_svm.launch_core )) {
2685 /* If we get here, we have a major problem */
2686 domain_crash_synchronous();
2689 v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core;
2690 clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
2694 /*
2695 * Local variables:
2696 * mode: C
2697 * c-set-style: "BSD"
2698 * c-basic-offset: 4
2699 * tab-width: 4
2700 * indent-tabs-mode: nil
2701 * End:
2702 */