direct-io.hg

view xen/arch/x86/hvm/svm/svm.c @ 8736:8aeb417387ca

Fix some more pfn/mfn/gmfn/gpfn inconsistencies. Fix some direct
uses of max_page variable to use the mfn_valid() predicate.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 02 12:18:28 2006 +0100 (2006-02-02)
parents 0c94043f5c5b
children ad0c3fa46c76
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 <xen/hypercall.h>
29 #include <asm/current.h>
30 #include <asm/io.h>
31 #include <asm/shadow.h>
32 #include <asm/regs.h>
33 #include <asm/cpufeature.h>
34 #include <asm/processor.h>
35 #include <asm/types.h>
36 #include <asm/msr.h>
37 #include <asm/spinlock.h>
38 #include <asm/hvm/hvm.h>
39 #include <asm/hvm/support.h>
40 #include <asm/hvm/io.h>
41 #include <asm/hvm/svm/svm.h>
42 #include <asm/hvm/svm/vmcb.h>
43 #include <asm/hvm/svm/emulate.h>
44 #include <asm/hvm/svm/vmmcall.h>
45 #include <asm/hvm/svm/intr.h>
46 #include <asm/shadow.h>
47 #if CONFIG_PAGING_LEVELS >= 3
48 #include <asm/shadow_64.h>
49 #endif
50 #include <public/sched.h>
51 #include <public/hvm/ioreq.h>
53 #ifdef CONFIG_SVM
55 #define SVM_EXTRA_DEBUG
57 #ifdef TRACE_BUFFER
58 static unsigned long trace_values[NR_CPUS][4];
59 #define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
60 #else
61 #define TRACE_VMEXIT(index,value) ((void)0)
62 #endif
64 /* Useful define */
65 #define MAX_INST_SIZE 15
67 /*
68 * External functions, etc. We should move these to some suitable header file(s) */
70 extern long evtchn_send(int lport);
71 extern void do_nmi(struct cpu_user_regs *, unsigned long);
72 extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
73 int inst_len);
74 extern asmlinkage void do_IRQ(struct cpu_user_regs *);
75 extern void smp_apic_timer_interrupt(struct cpu_user_regs *);
76 extern void timer_interrupt(int, void *, struct cpu_user_regs *);
77 extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
78 unsigned long count, int size, long value, int dir, int pvalid);
79 extern int svm_instrlen(struct cpu_user_regs *regs, int mode);
80 extern void svm_dump_inst(unsigned long eip);
81 extern int svm_dbg_on;
82 void svm_manual_event_injection32(struct vcpu *v, struct cpu_user_regs *regs,
83 int vector, int has_code);
84 void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
86 static struct asid_pool ASIDpool[NR_CPUS];
88 /*
89 * Initializes the POOL of ASID used by the guests per core.
90 */
91 void asidpool_init( int core )
92 {
93 int i;
94 ASIDpool[core].asid_lock = SPIN_LOCK_UNLOCKED;
95 spin_lock(&ASIDpool[core].asid_lock);
96 /* Host ASID is always in use */
97 ASIDpool[core].asid[INITIAL_ASID] = ASID_INUSE;
98 for( i=1; i<ASID_MAX; i++ )
99 {
100 ASIDpool[core].asid[i] = ASID_AVAILABLE;
101 }
102 spin_unlock(&ASIDpool[core].asid_lock);
103 }
106 /* internal function to get the next available ASID */
107 static int asidpool_fetch_next( struct vmcb_struct *vmcb, int core )
108 {
109 int i;
110 for( i = 1; i < ASID_MAX; i++ )
111 {
112 if( ASIDpool[core].asid[i] == ASID_AVAILABLE )
113 {
114 vmcb->guest_asid = i;
115 ASIDpool[core].asid[i] = ASID_INUSE;
116 return i;
117 }
118 }
119 return -1;
120 }
123 /*
124 * This functions assigns on the passed VMCB, the next
125 * available ASID number. If none are available, the
126 * TLB flush flag is set, and all retireds ASID
127 * are made available.
128 *
129 * Returns: 1 -- sucess;
130 * 0 -- failure -- no more ASID numbers
131 * available.
132 */
133 int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
134 int oldcore, int newcore )
135 {
136 int i;
137 int res = 1;
138 static unsigned long cnt=0;
140 spin_lock(&ASIDpool[oldcore].asid_lock);
141 if( retire_current && vmcb->guest_asid ) {
142 ASIDpool[oldcore].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
143 }
144 spin_unlock(&ASIDpool[oldcore].asid_lock);
145 spin_lock(&ASIDpool[newcore].asid_lock);
146 if( asidpool_fetch_next( vmcb, newcore ) < 0 ) {
147 if (svm_dbg_on)
148 printk( "SVM: tlb(%ld)\n", cnt++ );
149 /* FLUSH the TLB and all retired slots are made available */
150 vmcb->tlb_control = 1;
151 for( i = 1; i < ASID_MAX; i++ ) {
152 if( ASIDpool[newcore].asid[i] == ASID_RETIRED ) {
153 ASIDpool[newcore].asid[i] = ASID_AVAILABLE;
154 }
155 }
156 /* Get the First slot available */
157 res = asidpool_fetch_next( vmcb, newcore ) > 0;
158 }
159 spin_unlock(&ASIDpool[newcore].asid_lock);
160 return res;
161 }
163 void asidpool_retire( struct vmcb_struct *vmcb, int core )
164 {
165 spin_lock(&ASIDpool[core].asid_lock);
166 if( vmcb->guest_asid ) {
167 ASIDpool[core].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
168 }
169 spin_unlock(&ASIDpool[core].asid_lock);
170 }
172 static inline int svm_inject_exception(struct vcpu *v, int trap, int error_code)
173 {
174 void save_svm_cpu_user_regs(struct vcpu *, struct cpu_user_regs *);
175 struct cpu_user_regs regs;
177 printf("svm_inject_exception(trap %d, error_code 0x%x)\n",
178 trap, error_code);
179 save_svm_cpu_user_regs(v, &regs);
180 __hvm_bug(&regs);
181 }
183 void stop_svm(void)
184 {
185 u32 eax, edx;
187 /* We turn off the EFER_SVME bit. */
188 rdmsr(MSR_EFER, eax, edx);
189 eax &= ~EFER_SVME;
190 wrmsr(MSR_EFER, eax, edx);
192 printk("AMD SVM Extension is disabled.\n");
193 }
195 int svm_initialize_guest_resources(struct vcpu *v)
196 {
197 svm_final_setup_guest(v);
198 return 1;
199 }
201 int svm_relinquish_guest_resources(struct vcpu *v)
202 {
203 svm_relinquish_resources(v);
204 return 1;
205 }
207 void svm_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
208 {
209 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
211 #if defined (__x86_64__)
212 regs->rip = vmcb->rip;
213 regs->rsp = vmcb->rsp;
214 regs->rflags = vmcb->rflags;
215 regs->cs = vmcb->cs.sel;
216 regs->ds = vmcb->ds.sel;
217 regs->es = vmcb->es.sel;
218 regs->ss = vmcb->ss.sel;
219 regs->gs = vmcb->gs.sel;
220 regs->fs = vmcb->fs.sel;
221 #elif defined (__i386__)
222 regs->eip = vmcb->rip;
223 regs->esp = vmcb->rsp;
224 regs->eflags = vmcb->rflags;
225 regs->cs = vmcb->cs.sel;
226 regs->ds = vmcb->ds.sel;
227 regs->es = vmcb->es.sel;
228 regs->ss = vmcb->ss.sel;
229 regs->gs = vmcb->gs.sel;
230 regs->fs = vmcb->fs.sel;
231 #endif
232 }
234 void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
235 {
236 svm_load_cpu_user_regs(v, regs);
237 }
239 #ifdef __x86_64__
240 static struct svm_msr_state percpu_msr[NR_CPUS];
242 static u32 msr_data_index[VMX_MSR_COUNT] =
243 {
244 MSR_LSTAR, MSR_STAR, MSR_CSTAR,
245 MSR_SYSCALL_MASK, MSR_EFER,
246 };
248 void svm_save_segments(struct vcpu *v)
249 {
250 rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_svm.msr_content.shadow_gs);
251 }
253 /*
254 * To avoid MSR save/restore at every VM exit/entry time, we restore
255 * the x86_64 specific MSRs at domain switch time. Since those MSRs are
256 * are not modified once set for generic domains, we don't save them,
257 * but simply reset them to the values set at percpu_traps_init().
258 */
259 void svm_load_msrs(struct vcpu *n)
260 {
261 struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
262 int i;
264 if ( !hvm_switch_on )
265 return;
267 while ( host_state->flags )
268 {
269 i = find_first_set_bit(host_state->flags);
270 wrmsrl(msr_data_index[i], host_state->msr_items[i]);
271 clear_bit(i, &host_state->flags);
272 }
273 }
275 static void svm_save_init_msrs(void)
276 {
277 struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
278 int i;
280 for ( i = 0; i < SVM_MSR_COUNT; i++ )
281 rdmsrl(msr_data_index[i], host_state->msr_items[i]);
282 }
284 #define CASE_READ_MSR(address) \
285 case MSR_ ## address: \
286 msr_content = msr->msr_items[SVM_INDEX_MSR_ ## address]; \
287 break
289 #define CASE_WRITE_MSR(address) \
290 case MSR_ ## address: \
291 msr->msr_items[SVM_INDEX_MSR_ ## address] = msr_content; \
292 if (!test_bit(SVM_INDEX_MSR_ ## address, &msr->flags)) \
293 { \
294 set_bit(SVM_INDEX_MSR_ ## address, &msr->flags); \
295 } \
296 break
299 #define IS_CANO_ADDRESS(add) 1
301 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
302 {
303 u64 msr_content = 0;
304 struct vcpu *vc = current;
305 struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
306 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
308 switch (regs->ecx)
309 {
310 case MSR_EFER:
311 msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
312 HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n",
313 (unsigned long long)msr_content);
315 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
316 msr_content |= 1 << _EFER_LME;
318 if (SVM_LONG_GUEST(vc))
319 msr_content |= 1 << _EFER_LMA;
321 break;
323 case MSR_FS_BASE:
324 if (!(SVM_LONG_GUEST(vc)))
325 /* XXX should it be GP fault */
326 domain_crash_synchronous();
328 msr_content = vmcb->fs.base;
329 break;
331 case MSR_GS_BASE:
332 if (!(SVM_LONG_GUEST(vc)))
333 domain_crash_synchronous();
335 msr_content = vmcb->gs.base;
336 break;
338 case MSR_SHADOW_GS_BASE:
339 msr_content = msr->shadow_gs;
340 break;
342 CASE_READ_MSR(STAR);
343 CASE_READ_MSR(LSTAR);
344 CASE_READ_MSR(CSTAR);
345 CASE_READ_MSR(SYSCALL_MASK);
346 default:
347 return 0;
348 }
350 HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n",
351 msr_content);
353 regs->eax = msr_content & 0xffffffff;
354 regs->edx = msr_content >> 32;
355 return 1;
356 }
358 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
359 {
360 u64 msr_content = regs->eax | ((u64)regs->edx << 32);
361 struct vcpu *vc = current;
362 struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
363 struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
364 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
366 HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n",
367 regs->ecx, msr_content);
369 switch (regs->ecx)
370 {
371 case MSR_EFER:
372 if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
373 &vc->arch.hvm_svm.cpu_state))
374 {
375 if (test_bit(SVM_CPU_STATE_PG_ENABLED, &vc->arch.hvm_svm.cpu_state)
376 || !test_bit(SVM_CPU_STATE_PAE_ENABLED,
377 &vc->arch.hvm_svm.cpu_state))
378 {
379 svm_inject_exception(vc, TRAP_gp_fault, 0);
380 }
381 }
383 if (msr_content & EFER_LME)
384 set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
386 /* No update for LME/LMA since it have no effect */
387 msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
388 if (msr_content & ~(EFER_LME | EFER_LMA))
389 {
390 msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
391 if (!test_bit(SVM_INDEX_MSR_EFER, &msr->flags))
392 {
393 rdmsrl(MSR_EFER, host_state->msr_items[SVM_INDEX_MSR_EFER]);
394 set_bit(SVM_INDEX_MSR_EFER, &host_state->flags);
395 set_bit(SVM_INDEX_MSR_EFER, &msr->flags);
396 wrmsrl(MSR_EFER, msr_content);
397 }
398 }
399 break;
401 case MSR_FS_BASE:
402 case MSR_GS_BASE:
403 if (!(SVM_LONG_GUEST(vc)))
404 domain_crash_synchronous();
406 if (!IS_CANO_ADDRESS(msr_content))
407 {
408 HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
409 svm_inject_exception(vc, TRAP_gp_fault, 0);
410 }
412 if (regs->ecx == MSR_FS_BASE)
413 vmcb->fs.base = msr_content;
414 else
415 vmcb->gs.base = msr_content;
416 break;
418 case MSR_SHADOW_GS_BASE:
419 if (!(SVM_LONG_GUEST(vc)))
420 domain_crash_synchronous();
422 vc->arch.hvm_svm.msr_content.shadow_gs = msr_content;
423 wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
424 break;
426 CASE_WRITE_MSR(STAR);
427 CASE_WRITE_MSR(LSTAR);
428 CASE_WRITE_MSR(CSTAR);
429 CASE_WRITE_MSR(SYSCALL_MASK);
430 default:
431 return 0;
432 }
433 return 1;
434 }
436 void
437 svm_restore_msrs(struct vcpu *v)
438 {
439 int i = 0;
440 struct svm_msr_state *guest_state;
441 struct svm_msr_state *host_state;
442 unsigned long guest_flags;
444 guest_state = &v->arch.hvm_svm.msr_content;;
445 host_state = &percpu_msr[smp_processor_id()];
447 wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
448 guest_flags = guest_state->flags;
449 if (!guest_flags)
450 return;
452 while (guest_flags){
453 i = find_first_set_bit(guest_flags);
455 HVM_DBG_LOG(DBG_LEVEL_2,
456 "restore guest's index %d msr %lx with %lx\n",
457 i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]);
458 set_bit(i, &host_state->flags);
459 wrmsrl(msr_data_index[i], guest_state->msr_items[i]);
460 clear_bit(i, &guest_flags);
461 }
462 }
463 #else
464 #define svm_save_init_msrs() ((void)0)
466 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
467 {
468 return 0;
469 }
471 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
472 {
473 return 0;
474 }
475 #endif
477 void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
478 {
479 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
481 crs[0] = vmcb->cr0;
482 crs[3] = vmcb->cr3;
483 crs[4] = vmcb->cr4;
484 }
486 void svm_modify_guest_state(struct vcpu *v)
487 {
488 svm_modify_vmcb(v, &v->arch.guest_context.user_regs);
489 }
491 int svm_realmode(struct vcpu *v)
492 {
493 unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
494 unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
496 return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
497 }
499 int svm_instruction_length(struct vcpu *v)
500 {
501 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
502 unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
504 mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
505 return svm_instrlen(guest_cpu_user_regs(), mode);
506 }
508 int start_svm(void)
509 {
510 u32 eax, ecx, edx;
512 /* Xen does not fill x86_capability words except 0. */
513 ecx = cpuid_ecx(0x80000001);
514 boot_cpu_data.x86_capability[5] = ecx;
516 if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
517 return 0;
519 rdmsr(MSR_EFER, eax, edx);
520 eax |= EFER_SVME;
521 wrmsr(MSR_EFER, eax, edx);
522 asidpool_init(smp_processor_id());
523 printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
525 svm_save_init_msrs();
527 /* Setup HVM interfaces */
528 hvm_funcs.disable = stop_svm;
530 hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
531 hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
533 hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
534 hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
536 #ifdef __x86_64__
537 hvm_funcs.save_segments = svm_save_segments;
538 hvm_funcs.load_msrs = svm_load_msrs;
539 hvm_funcs.restore_msrs = svm_restore_msrs;
540 #endif
542 hvm_funcs.store_cpu_guest_ctrl_regs = svm_store_cpu_guest_ctrl_regs;
543 hvm_funcs.modify_guest_state = svm_modify_guest_state;
545 hvm_funcs.realmode = svm_realmode;
546 hvm_funcs.paging_enabled = svm_paging_enabled;
547 hvm_funcs.instruction_length = svm_instruction_length;
549 hvm_enabled = 1;
551 return 1;
552 }
554 int svm_dbg_on = 0;
556 static inline int svm_do_debugout(unsigned long exit_code)
557 {
558 int i;
560 static unsigned long counter = 0;
561 static unsigned long works[] =
562 {
563 VMEXIT_IOIO,
564 VMEXIT_HLT,
565 VMEXIT_CPUID,
566 VMEXIT_DR0_READ,
567 VMEXIT_DR1_READ,
568 VMEXIT_DR2_READ,
569 VMEXIT_DR3_READ,
570 VMEXIT_DR6_READ,
571 VMEXIT_DR7_READ,
572 VMEXIT_DR0_WRITE,
573 VMEXIT_DR1_WRITE,
574 VMEXIT_DR2_WRITE,
575 VMEXIT_DR3_WRITE,
576 VMEXIT_CR0_READ,
577 VMEXIT_CR0_WRITE,
578 VMEXIT_CR3_READ,
579 VMEXIT_CR4_READ,
580 VMEXIT_MSR,
581 VMEXIT_CR0_WRITE,
582 VMEXIT_CR3_WRITE,
583 VMEXIT_CR4_WRITE,
584 VMEXIT_EXCEPTION_PF,
585 VMEXIT_INTR,
586 VMEXIT_INVLPG,
587 VMEXIT_EXCEPTION_NM
588 };
591 #if 0
592 if (svm_dbg_on && exit_code != 0x7B)
593 return 1;
594 #endif
596 counter++;
598 #if 0
599 if ((exit_code == 0x4E
600 || exit_code == VMEXIT_CR0_READ
601 || exit_code == VMEXIT_CR0_WRITE)
602 && counter < 200000)
603 return 0;
605 if ((exit_code == 0x4E) && counter < 500000)
606 return 0;
607 #endif
609 for (i = 0; i < sizeof(works) / sizeof(works[0]); i++)
610 if (exit_code == works[i])
611 return 0;
613 return 1;
614 }
617 void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
618 {
619 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
621 ASSERT(vmcb);
623 ctxt->eax = vmcb->rax;
624 ctxt->ss = vmcb->ss.sel;
625 ctxt->esp = vmcb->rsp;
626 ctxt->eflags = vmcb->rflags;
627 ctxt->cs = vmcb->cs.sel;
628 ctxt->eip = vmcb->rip;
630 ctxt->gs = vmcb->gs.sel;
631 ctxt->fs = vmcb->fs.sel;
632 ctxt->es = vmcb->es.sel;
633 ctxt->ds = vmcb->ds.sel;
634 }
636 #if defined (__x86_64__)
637 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *c )
638 {
639 }
640 #elif defined (__i386__)
641 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
642 {
643 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
645 regs->eip = vmcb->rip;
646 regs->esp = vmcb->rsp;
647 regs->eflags = vmcb->rflags;
648 regs->cs = vmcb->cs.sel;
649 regs->ds = vmcb->ds.sel;
650 regs->es = vmcb->es.sel;
651 regs->ss = vmcb->ss.sel;
652 }
653 #endif
655 /* XXX Use svm_load_cpu_guest_regs instead */
656 #if defined (__i386__)
657 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
658 {
659 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
660 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
662 /* Write the guest register value into VMCB */
663 vmcb->rax = regs->eax;
664 vmcb->ss.sel = regs->ss;
665 vmcb->rsp = regs->esp;
666 vmcb->rflags = regs->eflags;
667 vmcb->cs.sel = regs->cs;
668 vmcb->rip = regs->eip;
669 if (regs->eflags & EF_TF)
670 *intercepts |= EXCEPTION_BITMAP_DB;
671 else
672 *intercepts &= ~EXCEPTION_BITMAP_DB;
673 }
674 #else /* (__i386__) */
675 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
676 {
677 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
678 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
680 /* Write the guest register value into VMCB */
681 vmcb->rax = regs->rax;
682 vmcb->ss.sel = regs->ss;
683 vmcb->rsp = regs->rsp;
684 vmcb->rflags = regs->rflags;
685 vmcb->cs.sel = regs->cs;
686 vmcb->rip = regs->rip;
687 if (regs->rflags & EF_TF)
688 *intercepts |= EXCEPTION_BITMAP_DB;
689 else
690 *intercepts &= ~EXCEPTION_BITMAP_DB;
691 }
692 #endif /* !(__i386__) */
694 int svm_paging_enabled(struct vcpu *v)
695 {
696 unsigned long cr0;
698 cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
700 return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
701 }
704 /* Make sure that xen intercepts any FP accesses from current */
705 void svm_stts(struct vcpu *v)
706 {
707 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
709 ASSERT(vmcb);
711 vmcb->cr0 |= X86_CR0_TS;
713 if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
714 v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
715 }
717 static void arch_svm_do_launch(struct vcpu *v)
718 {
719 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
720 int error;
722 #if 0
723 if (svm_dbg_on)
724 printk("Do launch\n");
725 #endif
726 error = construct_vmcb(&v->arch.hvm_svm, regs);
727 if ( error < 0 )
728 {
729 if (v->vcpu_id == 0) {
730 printk("Failed to construct a new VMCB for BSP.\n");
731 } else {
732 printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
733 }
734 domain_crash_synchronous();
735 }
737 svm_do_launch(v);
738 #if 0
739 if (svm_dbg_on)
740 svm_dump_host_regs(__func__);
741 #endif
742 reset_stack_and_jump(svm_asm_do_launch);
743 }
745 void svm_final_setup_guest(struct vcpu *v)
746 {
747 v->arch.schedule_tail = arch_svm_do_launch;
749 if (v == v->domain->vcpu[0])
750 {
751 struct domain *d = v->domain;
752 struct vcpu *vc;
754 /* Initialize monitor page table */
755 for_each_vcpu(d, vc)
756 vc->arch.monitor_table = mk_pagetable(0);
758 /*
759 * Required to do this once per domain
760 * TODO: add a seperate function to do these.
761 */
762 memset(&d->shared_info->evtchn_mask[0], 0xff,
763 sizeof(d->shared_info->evtchn_mask));
765 /*
766 * Put the domain in shadow mode even though we're going to be using
767 * the shared 1:1 page table initially. It shouldn't hurt
768 */
769 shadow_mode_enable(d,
770 SHM_enable|SHM_refcounts|
771 SHM_translate|SHM_external|SHM_wr_pt_pte);
772 }
773 }
776 void svm_relinquish_resources(struct vcpu *v)
777 {
778 struct hvm_virpit *vpit;
779 extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
781 #if 0
782 /*
783 * This is not stored at the moment. We need to keep it somewhere and free
784 * it Or maybe not, as it's a per-cpu-core item, and I guess we don't
785 * normally remove CPU's other than for hot-plug capable systems, where I
786 * guess we have to allocate and free host-save area in this case. Let's
787 * not worry about it at the moment, as loosing one page per CPU hot-plug
788 * event doesn't seem that excessive. But I may be wrong.
789 */
790 free_host_save_area(v->arch.hvm_svm.host_save_area);
791 #endif
793 if (v->vcpu_id == 0) {
794 /* unmap IO shared page */
795 struct domain *d = v->domain;
796 if (d->arch.hvm_domain.shared_page_va)
797 unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va);
798 }
800 destroy_vmcb(&v->arch.hvm_svm);
801 free_monitor_pagetable(v);
802 vpit = &v->domain->arch.hvm_domain.vpit;
803 kill_timer(&vpit->pit_timer);
804 kill_timer(&v->arch.hvm_svm.hlt_timer);
805 if ( hvm_apic_support(v->domain) ) {
806 kill_timer( &(VLAPIC(v)->vlapic_timer) );
807 xfree( VLAPIC(v) );
808 }
809 }
812 void arch_svm_do_resume(struct vcpu *v)
813 {
814 svm_do_resume(v);
815 reset_stack_and_jump(svm_asm_do_resume);
816 }
819 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
820 {
821 struct vcpu *v = current;
822 unsigned long eip;
823 unsigned long gpa; /* FIXME: PAE */
824 int result;
825 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
827 ASSERT(vmcb);
829 //#if HVM_DEBUG
830 eip = vmcb->rip;
831 HVM_DBG_LOG(DBG_LEVEL_VMMU,
832 "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
833 va, eip, (unsigned long)regs->error_code);
834 //#endif
836 if (!svm_paging_enabled(v))
837 {
838 handle_mmio(va, va);
839 TRACE_VMEXIT(2,2);
840 return 1;
841 }
843 update_pagetables(v);
845 gpa = gva_to_gpa(va);
847 /* Use 1:1 page table to identify MMIO address space */
848 if (mmio_space(gpa))
849 {
850 /* No support for APIC */
851 if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
852 {
853 unsigned long inst_len;
854 inst_len = svm_instruction_length(v);
855 if (inst_len == (unsigned long)-1)
856 {
857 printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
858 domain_crash_synchronous();
859 }
861 __update_guest_eip(vmcb, inst_len);
863 return 1;
864 }
866 TRACE_VMEXIT (2,2);
867 handle_mmio(va, gpa);
869 return 1;
870 }
872 result = shadow_fault(va, regs);
874 if( result ) {
875 /* Let's make sure that the Guest TLB is flushed */
876 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
877 }
879 TRACE_VMEXIT (2,result);
881 return result;
882 }
885 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
886 {
887 struct vcpu *v = current;
889 clts();
891 setup_fpu(v);
893 if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
894 vmcb->cr0 &= ~X86_CR0_TS;
896 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
897 }
900 static void svm_do_general_protection_fault(struct vcpu *v,
901 struct cpu_user_regs *regs)
902 {
903 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
904 unsigned long eip, error_code;
905 eventinj_t event;
907 ASSERT(vmcb);
909 eip = vmcb->rip;
910 error_code = vmcb->exitinfo1;
912 HVM_DBG_LOG(DBG_LEVEL_1,
913 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
914 eip, error_code);
916 HVM_DBG_LOG(DBG_LEVEL_1,
917 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
918 (unsigned long)regs->eax, (unsigned long)regs->ebx,
919 (unsigned long)regs->ecx, (unsigned long)regs->edx,
920 (unsigned long)regs->esi, (unsigned long)regs->edi);
923 /* Reflect it back into the guest */
924 event.bytes = 0;
925 event.fields.v = 1;
926 event.fields.type = EVENTTYPE_EXCEPTION;
927 event.fields.vector = 13;
928 event.fields.ev = 1;
929 event.fields.errorcode = error_code;
931 vmcb->eventinj = event;
932 }
934 /* Reserved bits: [31:14], [12:1] */
935 #define SVM_VCPU_CPUID_L1_RESERVED 0xffffdffe
937 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
938 struct cpu_user_regs *regs)
939 {
940 unsigned int eax, ebx, ecx, edx;
941 unsigned long eip;
942 struct vcpu *v = current;
943 unsigned int inst_len;
945 ASSERT(vmcb);
947 eip = vmcb->rip;
949 HVM_DBG_LOG(DBG_LEVEL_1,
950 "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
951 " (esi) %lx, (edi) %lx",
952 (unsigned long)regs->eax, (unsigned long)regs->ebx,
953 (unsigned long)regs->ecx, (unsigned long)regs->edx,
954 (unsigned long)regs->esi, (unsigned long)regs->edi);
956 cpuid(input, &eax, &ebx, &ecx, &edx);
958 if (input == 1)
959 {
960 if ( hvm_apic_support(v->domain) &&
961 !vlapic_global_enabled((VLAPIC(v))) )
962 clear_bit(X86_FEATURE_APIC, &edx);
964 #ifdef __x86_64__
965 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
966 #endif
967 {
968 clear_bit(X86_FEATURE_PSE, &edx);
969 clear_bit(X86_FEATURE_PAE, &edx);
970 clear_bit(X86_FEATURE_PSE36, &edx);
971 }
973 /* Clear out reserved bits. */
974 ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
975 }
976 #ifdef __i386__
977 else if ( input == 0x80000001 )
978 {
979 /* Mask feature for Intel ia32e or AMD long mode. */
980 clear_bit(X86_FEATURE_LM & 31, &edx);
981 }
982 #endif
984 regs->eax = (unsigned long)eax;
985 regs->ebx = (unsigned long)ebx;
986 regs->ecx = (unsigned long)ecx;
987 regs->edx = (unsigned long)edx;
989 HVM_DBG_LOG(DBG_LEVEL_1,
990 "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
991 "ebx=%x, ecx=%x, edx=%x",
992 eip, input, eax, ebx, ecx, edx);
994 inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
995 __update_guest_eip(vmcb, inst_len);
996 }
999 static inline unsigned long *get_reg_p(unsigned int gpreg,
1000 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1002 unsigned long *reg_p = NULL;
1003 switch (gpreg)
1005 case SVM_REG_EAX:
1006 reg_p = (unsigned long *)&regs->eax;
1007 break;
1008 case SVM_REG_EBX:
1009 reg_p = (unsigned long *)&regs->ebx;
1010 break;
1011 case SVM_REG_ECX:
1012 reg_p = (unsigned long *)&regs->ecx;
1013 break;
1014 case SVM_REG_EDX:
1015 reg_p = (unsigned long *)&regs->edx;
1016 break;
1017 case SVM_REG_EDI:
1018 reg_p = (unsigned long *)&regs->edi;
1019 break;
1020 case SVM_REG_ESI:
1021 reg_p = (unsigned long *)&regs->esi;
1022 break;
1023 case SVM_REG_EBP:
1024 reg_p = (unsigned long *)&regs->ebp;
1025 break;
1026 case SVM_REG_ESP:
1027 reg_p = (unsigned long *)&vmcb->rsp;
1028 break;
1029 #if __x86_64__
1030 case SVM_REG_R8:
1031 reg_p = (unsigned long *)&regs->r8;
1032 break;
1033 case SVM_REG_R9:
1034 reg_p = (unsigned long *)&regs->r9;
1035 break;
1036 case SVM_REG_R10:
1037 reg_p = (unsigned long *)&regs->r10;
1038 break;
1039 case SVM_REG_R11:
1040 reg_p = (unsigned long *)&regs->r11;
1041 break;
1042 case SVM_REG_R12:
1043 reg_p = (unsigned long *)&regs->r12;
1044 break;
1045 case SVM_REG_R13:
1046 reg_p = (unsigned long *)&regs->r13;
1047 break;
1048 case SVM_REG_R14:
1049 reg_p = (unsigned long *)&regs->r14;
1050 break;
1051 case SVM_REG_R15:
1052 reg_p = (unsigned long *)&regs->r15;
1053 break;
1054 #endif
1055 default:
1056 BUG();
1059 return reg_p;
1063 static inline unsigned long get_reg(unsigned int gpreg,
1064 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1066 unsigned long *gp;
1067 gp = get_reg_p(gpreg, regs, vmcb);
1068 return *gp;
1072 static inline void set_reg(unsigned int gpreg, unsigned long value,
1073 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1075 unsigned long *gp;
1076 gp = get_reg_p(gpreg, regs, vmcb);
1077 *gp = value;
1081 static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
1082 struct cpu_user_regs *regs)
1084 unsigned long *reg_p = 0;
1085 unsigned int gpreg = 0;
1086 unsigned long eip;
1087 unsigned int inst_len;
1088 struct vmcb_struct *vmcb;
1089 u8 buffer[MAX_INST_LEN];
1091 vmcb = v->arch.hvm_svm.vmcb;
1093 ASSERT(vmcb);
1095 eip = vmcb->rip;
1096 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1098 ASSERT(buffer[0] == 0x0f && (buffer[1] & 0xFD) == 0x21);
1100 gpreg = decode_src_reg(buffer[2]);
1101 #if DEBUG
1102 ASSERT(reg == decode_dest_reg(buffer[2]));
1103 #endif
1105 HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
1106 eip, reg, gpreg);
1108 reg_p = get_reg_p(gpreg, regs, vmcb);
1110 switch (type)
1112 case TYPE_MOV_TO_DR:
1113 inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
1114 v->arch.guest_context.debugreg[reg] = *reg_p;
1115 break;
1116 case TYPE_MOV_FROM_DR:
1117 inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
1118 *reg_p = v->arch.guest_context.debugreg[reg];
1119 break;
1120 default:
1121 __hvm_bug(regs);
1122 break;
1124 __update_guest_eip(vmcb, inst_len);
1128 static unsigned int check_for_null_selector(struct vmcb_struct *vmcb,
1129 unsigned int dir, unsigned long *base, unsigned int real)
1132 unsigned char inst[MAX_INST_LEN];
1133 segment_selector_t seg;
1134 int i;
1136 memset(inst, 0, MAX_INST_LEN);
1137 if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
1138 != MAX_INST_LEN)
1140 printk("check_for_null_selector: get guest instruction failed\n");
1141 domain_crash_synchronous();
1144 for (i = 0; i < MAX_INST_LEN; i++)
1146 switch (inst[i])
1148 case 0xf3: /* REPZ */
1149 case 0xf2: /* REPNZ */
1150 case 0xf0: /* LOCK */
1151 case 0x66: /* data32 */
1152 case 0x67: /* addr32 */
1153 #if __x86_64__
1154 /* REX prefixes */
1155 case 0x40:
1156 case 0x41:
1157 case 0x42:
1158 case 0x43:
1159 case 0x44:
1160 case 0x45:
1161 case 0x46:
1162 case 0x47:
1164 case 0x48:
1165 case 0x49:
1166 case 0x4a:
1167 case 0x4b:
1168 case 0x4c:
1169 case 0x4d:
1170 case 0x4e:
1171 case 0x4f:
1172 #endif
1173 continue;
1174 case 0x2e: /* CS */
1175 seg = vmcb->cs;
1176 break;
1177 case 0x36: /* SS */
1178 seg = vmcb->ss;
1179 break;
1180 case 0x26: /* ES */
1181 seg = vmcb->es;
1182 break;
1183 case 0x64: /* FS */
1184 seg = vmcb->fs;
1185 break;
1186 case 0x65: /* GS */
1187 seg = vmcb->gs;
1188 break;
1189 case 0x3e: /* DS */
1190 /* FALLTHROUGH */
1191 seg = vmcb->ds;
1192 break;
1193 default:
1194 if (dir == IOREQ_READ)
1195 seg = vmcb->es;
1196 else
1197 seg = vmcb->ds;
1200 /* In real Mode */
1201 if (real)
1202 seg.base = seg.sel << 4;
1204 if (base)
1205 *base = seg.base;
1207 return seg.attributes.fields.p;
1210 ASSERT(0);
1211 return 0;
1215 /* Get the address of INS/OUTS instruction */
1216 static inline unsigned long svm_get_io_address(struct vmcb_struct *vmcb,
1217 struct cpu_user_regs *regs, unsigned int dir, unsigned int real)
1219 unsigned long addr = 0;
1220 unsigned long base = 0;
1222 check_for_null_selector(vmcb, dir, &base, real);
1224 if (dir == IOREQ_WRITE)
1226 if (real)
1227 addr = (regs->esi & 0xFFFF) + base;
1228 else
1229 addr = regs->esi + base;
1231 else
1233 if (real)
1234 addr = (regs->edi & 0xFFFF) + base;
1235 else
1236 addr = regs->edi + base;
1239 return addr;
1243 static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs)
1245 struct mmio_op *mmio_opp;
1246 unsigned long eip, cs, eflags, cr0;
1247 unsigned long port;
1248 unsigned int real, size, dir;
1249 ioio_info_t info;
1251 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1253 ASSERT(vmcb);
1254 mmio_opp = &current->arch.hvm_vcpu.mmio_op;
1255 mmio_opp->instr = INSTR_PIO;
1256 mmio_opp->flags = 0;
1258 eip = vmcb->rip;
1259 cs = vmcb->cs.sel;
1260 eflags = vmcb->rflags;
1262 info.bytes = vmcb->exitinfo1;
1264 port = info.fields.port; /* port used to be addr */
1265 dir = info.fields.type; /* direction */
1266 if (info.fields.sz32)
1267 size = 4;
1268 else if (info.fields.sz16)
1269 size = 2;
1270 else
1271 size = 1;
1273 cr0 = vmcb->cr0;
1274 real = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
1276 HVM_DBG_LOG(DBG_LEVEL_IO,
1277 "svm_io_instruction: port 0x%lx real %d, eip=%lx:%lx, "
1278 "exit_qualification = %lx",
1279 (unsigned long) port, real, cs, eip, (unsigned long)info.bytes);
1281 /*
1282 * On SVM, the RIP of the intruction following the IN/OUT is saved in
1283 * ExitInfo2
1284 */
1285 vmcb->rip = vmcb->exitinfo2;
1287 /* string instruction */
1288 if (info.fields.str)
1290 unsigned long addr, count = 1;
1291 int sign = regs->eflags & EF_DF ? -1 : 1;
1293 addr = svm_get_io_address(vmcb, regs, dir, real);
1295 /* "rep" prefix */
1296 if (info.fields.rep)
1298 mmio_opp->flags |= REPZ;
1299 count = real ? regs->ecx & 0xFFFF : regs->ecx;
1302 /*
1303 * Handle string pio instructions that cross pages or that
1304 * are unaligned. See the comments in hvm_platform.c/handle_mmio()
1305 */
1306 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
1308 unsigned long value = 0;
1310 mmio_opp->flags |= OVERLAP;
1312 if (dir == IOREQ_WRITE)
1313 hvm_copy(&value, addr, size, HVM_COPY_IN);
1315 send_pio_req(regs, port, 1, size, value, dir, 0);
1317 else
1319 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
1321 if (sign > 0)
1322 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
1323 else
1324 count = (addr & ~PAGE_MASK) / size;
1327 send_pio_req(regs, port, count, size, addr, dir, 1);
1330 else
1332 if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
1333 hvm_print_line(v, regs->eax); /* guest debug output */
1335 send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
1340 static int svm_set_cr0(unsigned long value)
1342 struct vcpu *v = current;
1343 unsigned long mfn;
1344 int paging_enabled;
1345 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1347 ASSERT(vmcb);
1349 /* We don't want to lose PG. ET is reserved and should be always be 1*/
1350 paging_enabled = svm_paging_enabled(v);
1351 value |= X86_CR0_ET;
1352 vmcb->cr0 = value | X86_CR0_PG;
1353 v->arch.hvm_svm.cpu_shadow_cr0 = value;
1355 /* Check if FP Unit Trap need to be on */
1356 if (value & X86_CR0_TS)
1358 vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
1361 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
1363 if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
1365 /* The guest CR3 must be pointing to the guest physical. */
1366 if (!VALID_MFN(mfn =
1367 get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
1368 || !get_page(mfn_to_page(mfn), v->domain))
1370 printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
1371 domain_crash_synchronous(); /* need to take a clean path */
1374 #if defined(__x86_64__)
1375 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
1376 && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
1377 &v->arch.hvm_svm.cpu_state))
1379 HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
1380 svm_inject_exception(v, TRAP_gp_fault, 0);
1383 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
1385 /* Here the PAE is should to be opened */
1386 HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
1387 set_bit(SVM_CPU_STATE_LMA_ENABLED,
1388 &v->arch.hvm_svm.cpu_state);
1389 #if 0
1390 __vmread(VM_ENTRY_CONTROLS, &vm_entry_value);
1391 vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE;
1392 __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
1393 #else
1394 printk("Cannot yet set SVM_CPU_STATE_LMA_ENABLED\n");
1395 domain_crash_synchronous();
1396 #endif
1398 #if CONFIG_PAGING_LEVELS >= 4
1399 if (!shadow_set_guest_paging_levels(v->domain, 4))
1401 printk("Unsupported guest paging levels\n");
1402 domain_crash_synchronous(); /* need to take a clean path */
1404 #endif
1406 else
1408 #if CONFIG_PAGING_LEVELS >= 4
1409 if (!shadow_set_guest_paging_levels(v->domain, 2))
1411 printk("Unsupported guest paging levels\n");
1412 domain_crash_synchronous(); /* need to take a clean path */
1414 #endif
1417 #if 0
1418 unsigned long crn;
1420 /* update CR4's PAE if needed */
1421 __vmread(GUEST_CR4, &crn);
1422 if ((!(crn & X86_CR4_PAE))
1423 && test_bit(SVM_CPU_STATE_PAE_ENABLED,
1424 &v->arch.hvm_svm.cpu_state))
1426 HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
1427 __vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
1429 #else
1430 printk("Cannot yet set SVM_CPU_STATE_PAE_ENABLED\n");
1431 domain_crash_synchronous();
1432 #endif
1433 #elif defined(__i386__)
1435 unsigned long old_base_mfn;
1436 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1437 if (old_base_mfn)
1438 put_page(mfn_to_page(old_base_mfn));
1440 #endif
1441 /* Now arch.guest_table points to machine physical. */
1442 v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
1443 update_pagetables(v);
1445 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
1446 (unsigned long) (mfn << PAGE_SHIFT));
1448 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1449 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1451 /* arch->shadow_table should hold the next CR3 for shadow */
1452 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
1453 v->arch.hvm_svm.cpu_cr3, mfn);
1456 /*
1457 * SVM implements paged real-mode and when we return to real-mode
1458 * we revert back to the physical mappings that the domain builder
1459 * created.
1460 */
1461 if ((value & X86_CR0_PE) == 0) {
1462 if (value & X86_CR0_PG) {
1463 svm_inject_exception(v, TRAP_gp_fault, 0);
1464 return 0;
1467 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1468 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
1471 return 1;
1475 /*
1476 * Read from control registers. CR0 and CR4 are read from the shadow.
1477 */
1478 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
1480 unsigned long value = 0;
1481 struct vcpu *v = current;
1482 struct vmcb_struct *vmcb;
1484 vmcb = v->arch.hvm_svm.vmcb;
1485 ASSERT(vmcb);
1487 switch (cr)
1489 case 0:
1490 value = v->arch.hvm_svm.cpu_shadow_cr0;
1491 break;
1492 case 2:
1493 value = vmcb->cr2;
1494 break;
1495 case 3:
1496 value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
1497 break;
1498 case 4:
1499 value = vmcb->cr4;
1500 break;
1501 case 8:
1502 #if 0
1503 value = vmcb->m_cr8;
1504 #else
1505 ASSERT(0);
1506 #endif
1507 break;
1509 default:
1510 __hvm_bug(regs);
1513 set_reg(gp, value, regs, vmcb);
1515 HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
1519 /*
1520 * Write to control registers
1521 */
1522 static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
1524 unsigned long value;
1525 unsigned long old_cr;
1526 struct vcpu *v = current;
1527 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1529 ASSERT(vmcb);
1531 value = get_reg(gpreg, regs, vmcb);
1533 HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
1534 HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
1536 switch (cr)
1538 case 0:
1539 return svm_set_cr0(value);
1541 case 3:
1543 unsigned long old_base_mfn, mfn;
1545 /* If paging is not enabled yet, simply copy the value to CR3. */
1546 if (!svm_paging_enabled(v)) {
1547 v->arch.hvm_svm.cpu_cr3 = value;
1548 break;
1550 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1552 /* We make a new one if the shadow does not exist. */
1553 if (value == v->arch.hvm_svm.cpu_cr3)
1555 /*
1556 * This is simple TLB flush, implying the guest has
1557 * removed some translation or changed page attributes.
1558 * We simply invalidate the shadow.
1559 */
1560 mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
1561 if (mfn != pagetable_get_pfn(v->arch.guest_table))
1562 __hvm_bug(regs);
1563 shadow_sync_all(v->domain);
1565 else
1567 /*
1568 * If different, make a shadow. Check if the PDBR is valid
1569 * first.
1570 */
1571 HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
1572 if (((value >> PAGE_SHIFT) > v->domain->max_pages)
1573 || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
1574 || !get_page(mfn_to_page(mfn), v->domain))
1576 printk("Invalid CR3 value=%lx\n", value);
1577 domain_crash_synchronous(); /* need to take a clean path */
1580 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1581 v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
1583 if (old_base_mfn)
1584 put_page(mfn_to_page(old_base_mfn));
1586 update_pagetables(v);
1588 /* arch.shadow_table should now hold the next CR3 for shadow*/
1589 v->arch.hvm_svm.cpu_cr3 = value;
1590 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
1591 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1593 break;
1596 case 4:
1597 /* CR4 */
1598 if (value & X86_CR4_PAE)
1599 __hvm_bug(regs); /* not implemented */
1601 old_cr = vmcb->cr4;
1603 vmcb->cr4 = value;
1605 /*
1606 * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
1607 * all TLB entries except global entries.
1608 */
1609 if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
1611 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1612 shadow_sync_all(v->domain);
1614 break;
1616 default:
1617 printk("invalid cr: %d\n", cr);
1618 __hvm_bug(regs);
1621 return 1;
1625 #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
1628 static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
1629 struct cpu_user_regs *regs)
1631 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1632 unsigned int inst_len = 0;
1633 unsigned int gpreg;
1634 unsigned long value;
1635 u8 buffer[6];
1636 int result = 1;
1637 enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
1638 enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
1639 enum instruction_index match;
1641 ASSERT(vmcb);
1643 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1645 if (type == TYPE_MOV_TO_CR)
1647 inst_len = __get_instruction_length_from_list(vmcb, list_a,
1648 ARR_SIZE(list_a), buffer, &match);
1650 else
1652 inst_len = __get_instruction_length_from_list(vmcb, list_b,
1653 ARR_SIZE(list_b), buffer, &match);
1656 HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
1658 switch (match)
1660 case INSTR_MOV2CR:
1661 gpreg = decode_src_reg(buffer[2]);
1662 result = mov_to_cr(gpreg, cr, regs);
1663 break;
1665 case INSTR_MOVCR2:
1666 gpreg = decode_src_reg(buffer[2]);
1667 mov_from_cr(cr, gpreg, regs);
1668 break;
1670 case INSTR_CLTS:
1671 clts();
1672 setup_fpu(current);
1673 vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
1674 v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
1675 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1676 break;
1678 case INSTR_LMSW:
1679 if (svm_dbg_on)
1680 svm_dump_inst(svm_rip2pointer(vmcb));
1682 gpreg = decode_src_reg(buffer[2]);
1683 value = get_reg(gpreg, regs, vmcb) & 0xF;
1685 if (svm_dbg_on)
1686 printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1687 inst_len);
1689 value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
1691 if (svm_dbg_on)
1692 printk("CR0-LMSW CR0 - New value=%lx\n", value);
1694 result = svm_set_cr0(value);
1695 break;
1697 case INSTR_SMSW:
1698 svm_dump_inst(svm_rip2pointer(vmcb));
1699 value = v->arch.hvm_svm.cpu_shadow_cr0;
1700 gpreg = decode_src_reg(buffer[2]);
1701 set_reg(gpreg, value, regs, vmcb);
1703 if (svm_dbg_on)
1704 printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1705 inst_len);
1706 break;
1708 default:
1709 __hvm_bug(regs);
1710 break;
1713 ASSERT(inst_len);
1715 __update_guest_eip(vmcb, inst_len);
1717 return result;
1720 static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
1722 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1723 unsigned int inst_len;
1724 int64_t tsc_sum;
1726 ASSERT(vmcb);
1728 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
1729 "exitinfo = %lx", (unsigned long)regs->ecx,
1730 (unsigned long)regs->eax, (unsigned long)regs->edx,
1731 (unsigned long)vmcb->exitinfo1);
1733 /* is it a read? */
1734 if (vmcb->exitinfo1 == 0)
1736 inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
1738 regs->edx = 0;
1739 switch (regs->ecx)
1741 case MSR_IA32_SYSENTER_CS:
1742 regs->eax = vmcb->sysenter_cs;
1743 break;
1744 case MSR_IA32_SYSENTER_ESP:
1745 regs->eax = vmcb->sysenter_esp;
1746 break;
1747 case MSR_IA32_SYSENTER_EIP:
1748 regs->eax = vmcb->sysenter_eip;
1749 break;
1750 case MSR_IA32_TIME_STAMP_COUNTER:
1751 __asm__ __volatile__("rdtsc" : "=a" (regs->eax), "=d" (regs->edx));
1752 tsc_sum = regs->edx;
1753 tsc_sum = (tsc_sum << 32) + regs->eax;
1754 tsc_sum += (int64_t) vmcb->tsc_offset;
1755 regs->eax = tsc_sum & 0xFFFFFFFF;
1756 regs->edx = (tsc_sum >> 32) & 0xFFFFFFFF;
1757 break;
1758 default:
1759 if (long_mode_do_msr_read(regs))
1760 goto done;
1761 rdmsr_user(regs->ecx, regs->eax, regs->edx);
1762 break;
1765 else
1767 inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
1769 switch (regs->ecx)
1771 case MSR_IA32_SYSENTER_CS:
1772 vmcb->sysenter_cs = regs->eax;
1773 break;
1774 case MSR_IA32_SYSENTER_ESP:
1775 vmcb->sysenter_esp = regs->eax;
1776 break;
1777 case MSR_IA32_SYSENTER_EIP:
1778 vmcb->sysenter_eip = regs->eax;
1779 break;
1780 default:
1781 long_mode_do_msr_write(regs);
1782 break;
1786 done:
1788 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
1789 "ecx=%lx, eax=%lx, edx=%lx",
1790 (unsigned long)regs->ecx, (unsigned long)regs->eax,
1791 (unsigned long)regs->edx);
1793 __update_guest_eip(vmcb, inst_len);
1797 /*
1798 * Need to use this exit to reschedule
1799 */
1800 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
1802 struct vcpu *v = current;
1803 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
1804 s_time_t next_pit = -1, next_wakeup;
1805 unsigned int inst_len;
1807 svm_stts(v);
1808 inst_len = __get_instruction_length(vmcb, INSTR_HLT, NULL);
1809 __update_guest_eip(vmcb, inst_len);
1811 if ( !v->vcpu_id ) {
1812 next_pit = get_pit_scheduled(v, vpit);
1814 next_wakeup = get_apictime_scheduled(v);
1815 if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
1816 next_wakeup = next_pit;
1818 if ( next_wakeup != - 1 )
1819 set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
1820 do_sched_op(SCHEDOP_block, 0);
1824 static inline void svm_vmexit_do_mwait(void)
1826 return;
1830 #ifdef XEN_DEBUGGER
1831 static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
1832 struct cpu_user_regs *regs)
1834 regs->eip = vmcb->rip;
1835 regs->esp = vmcb->rsp;
1836 regs->eflags = vmcb->rflags;
1838 regs->xcs = vmcb->cs.sel;
1839 regs->xds = vmcb->ds.sel;
1840 regs->xes = vmcb->es.sel;
1841 regs->xfs = vmcb->fs.sel;
1842 regs->xgs = vmcb->gs.sel;
1843 regs->xss = vmcb->ss.sel;
1847 static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
1849 vmcb->ss.sel = regs->xss;
1850 vmcb->rsp = regs->esp;
1851 vmcb->rflags = regs->eflags;
1852 vmcb->cs.sel = regs->xcs;
1853 vmcb->rip = regs->eip;
1855 vmcb->gs.sel = regs->xgs;
1856 vmcb->fs.sel = regs->xfs;
1857 vmcb->es.sel = regs->xes;
1858 vmcb->ds.sel = regs->xds;
1860 #endif
1863 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
1865 struct vcpu *v = current;
1866 u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
1867 unsigned long g_vaddr;
1868 unsigned int inst_len;
1869 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1871 ASSERT(vmcb);
1872 /*
1873 * Unknown how many bytes the invlpg instruction will take. Use the
1874 * maximum instruction length here
1875 */
1876 if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
1878 printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
1879 __hvm_bug(regs);
1882 if (invlpga)
1884 inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
1885 __update_guest_eip(vmcb, inst_len);
1887 /*
1888 * The address is implicit on this instruction At the moment, we don't
1889 * use ecx (ASID) to identify individual guests pages
1890 */
1891 g_vaddr = regs->eax;
1893 else
1895 /* What about multiple prefix codes? */
1896 prefix = (is_prefix(opcode[0])?opcode[0]:0);
1897 inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
1899 inst_len--;
1900 length -= inst_len;
1902 /*
1903 * Decode memory operand of the instruction including ModRM, SIB, and
1904 * displacement to get effecticve address and length in bytes. Assume
1905 * the system in either 32- or 64-bit mode.
1906 */
1907 g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
1908 &opcode[inst_len], &length);
1910 inst_len += length;
1911 __update_guest_eip (vmcb, inst_len);
1914 /* Overkill, we may not this */
1915 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1916 shadow_invlpg(v, g_vaddr);
1920 /*
1921 * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
1922 * 16-bit realmode. Basically, this mimics a processor reset.
1924 * returns 0 on success, non-zero otherwise
1925 */
1926 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
1927 struct cpu_user_regs *regs)
1929 struct vmcb_struct *vmcb;
1931 ASSERT(v);
1932 ASSERT(regs);
1934 vmcb = v->arch.hvm_svm.vmcb;
1936 ASSERT(vmcb);
1938 /* clear the vmcb and user regs */
1939 memset(regs, 0, sizeof(struct cpu_user_regs));
1941 /* VMCB Control */
1942 vmcb->tsc_offset = 0;
1944 /* VMCB State */
1945 vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
1946 v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
1948 vmcb->cr2 = 0;
1949 vmcb->cr4 = 0;
1951 /* This will jump to ROMBIOS */
1952 vmcb->rip = 0xFFF0;
1954 /* setup the segment registers and all their hidden states */
1955 vmcb->cs.sel = 0xF000;
1956 vmcb->cs.attributes.bytes = 0x089b;
1957 vmcb->cs.limit = 0xffff;
1958 vmcb->cs.base = 0x000F0000;
1960 vmcb->ss.sel = 0x00;
1961 vmcb->ss.attributes.bytes = 0x0893;
1962 vmcb->ss.limit = 0xffff;
1963 vmcb->ss.base = 0x00;
1965 vmcb->ds.sel = 0x00;
1966 vmcb->ds.attributes.bytes = 0x0893;
1967 vmcb->ds.limit = 0xffff;
1968 vmcb->ds.base = 0x00;
1970 vmcb->es.sel = 0x00;
1971 vmcb->es.attributes.bytes = 0x0893;
1972 vmcb->es.limit = 0xffff;
1973 vmcb->es.base = 0x00;
1975 vmcb->fs.sel = 0x00;
1976 vmcb->fs.attributes.bytes = 0x0893;
1977 vmcb->fs.limit = 0xffff;
1978 vmcb->fs.base = 0x00;
1980 vmcb->gs.sel = 0x00;
1981 vmcb->gs.attributes.bytes = 0x0893;
1982 vmcb->gs.limit = 0xffff;
1983 vmcb->gs.base = 0x00;
1985 vmcb->ldtr.sel = 0x00;
1986 vmcb->ldtr.attributes.bytes = 0x0000;
1987 vmcb->ldtr.limit = 0x0;
1988 vmcb->ldtr.base = 0x00;
1990 vmcb->gdtr.sel = 0x00;
1991 vmcb->gdtr.attributes.bytes = 0x0000;
1992 vmcb->gdtr.limit = 0x0;
1993 vmcb->gdtr.base = 0x00;
1995 vmcb->tr.sel = 0;
1996 vmcb->tr.attributes.bytes = 0;
1997 vmcb->tr.limit = 0x0;
1998 vmcb->tr.base = 0;
2000 vmcb->idtr.sel = 0x00;
2001 vmcb->idtr.attributes.bytes = 0x0000;
2002 vmcb->idtr.limit = 0x3ff;
2003 vmcb->idtr.base = 0x00;
2005 vmcb->rax = 0;
2007 return 0;
2011 /*
2012 * svm_do_vmmcall - SVM VMMCALL handler
2014 * returns 0 on success, non-zero otherwise
2015 */
2016 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
2018 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2019 unsigned int inst_len;
2021 ASSERT(vmcb);
2022 ASSERT(regs);
2024 inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
2026 /* VMMCALL sanity check */
2027 if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
2029 printf("VMMCALL CPL check failed\n");
2030 return -1;
2033 /* handle the request */
2034 switch (regs->edi)
2036 case VMMCALL_RESET_TO_REALMODE:
2037 if (svm_do_vmmcall_reset_to_realmode(v, regs))
2039 printf("svm_do_vmmcall_reset_to_realmode() failed\n");
2040 return -1;
2043 /* since we just reset the VMCB, return without adjusting the eip */
2044 return 0;
2045 case VMMCALL_DEBUG:
2046 printf("DEBUG features not implemented yet\n");
2047 break;
2048 default:
2049 break;
2052 hvm_print_line(v, regs->eax); /* provides the current domain */
2054 __update_guest_eip(vmcb, inst_len);
2055 return 0;
2059 void svm_dump_inst(unsigned long eip)
2061 u8 opcode[256];
2062 unsigned long ptr;
2063 int len;
2064 int i;
2066 ptr = eip & ~0xff;
2067 len = 0;
2069 if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
2070 len = sizeof(opcode);
2072 printf("Code bytes around(len=%d) %lx:", len, eip);
2073 for (i = 0; i < len; i++)
2075 if ((i & 0x0f) == 0)
2076 printf("\n%08lx:", ptr+i);
2078 printf("%02x ", opcode[i]);
2081 printf("\n");
2085 void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
2087 struct vcpu *v = current;
2088 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2089 unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
2091 printf("%s: guest registers from %s:\n", __func__, from);
2092 #if defined (__x86_64__)
2093 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
2094 regs->rax, regs->rbx, regs->rcx);
2095 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
2096 regs->rdx, regs->rsi, regs->rdi);
2097 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
2098 regs->rbp, regs->rsp, regs->r8);
2099 printk("r9: %016lx r10: %016lx r11: %016lx\n",
2100 regs->r9, regs->r10, regs->r11);
2101 printk("r12: %016lx r13: %016lx r14: %016lx\n",
2102 regs->r12, regs->r13, regs->r14);
2103 printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
2104 regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
2105 #else
2106 printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
2107 regs->eax, regs->ebx, regs->ecx, regs->edx);
2108 printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
2109 regs->edi, regs->esi, regs->ebp, regs->esp);
2110 printf("%s: guest cr0: %lx\n", __func__,
2111 v->arch.hvm_svm.cpu_shadow_cr0);
2112 printf("guest CR3 = %llx\n", vmcb->cr3);
2113 #endif
2114 printf("%s: pt = %lx\n", __func__, pt);
2118 void svm_dump_host_regs(const char *from)
2120 struct vcpu *v = current;
2121 unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
2122 unsigned long cr3, cr0;
2123 printf("Host registers at %s\n", from);
2125 __asm__ __volatile__ ("\tmov %%cr0,%0\n"
2126 "\tmov %%cr3,%1\n"
2127 : "=r" (cr0), "=r"(cr3));
2128 printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
2131 #ifdef SVM_EXTRA_DEBUG
2132 static char *exit_reasons[] = {
2133 [VMEXIT_CR0_READ] = "CR0_READ",
2134 [VMEXIT_CR1_READ] = "CR1_READ",
2135 [VMEXIT_CR2_READ] = "CR2_READ",
2136 [VMEXIT_CR3_READ] = "CR3_READ",
2137 [VMEXIT_CR4_READ] = "CR4_READ",
2138 [VMEXIT_CR5_READ] = "CR5_READ",
2139 [VMEXIT_CR6_READ] = "CR6_READ",
2140 [VMEXIT_CR7_READ] = "CR7_READ",
2141 [VMEXIT_CR8_READ] = "CR8_READ",
2142 [VMEXIT_CR9_READ] = "CR9_READ",
2143 [VMEXIT_CR10_READ] = "CR10_READ",
2144 [VMEXIT_CR11_READ] = "CR11_READ",
2145 [VMEXIT_CR12_READ] = "CR12_READ",
2146 [VMEXIT_CR13_READ] = "CR13_READ",
2147 [VMEXIT_CR14_READ] = "CR14_READ",
2148 [VMEXIT_CR15_READ] = "CR15_READ",
2149 [VMEXIT_CR0_WRITE] = "CR0_WRITE",
2150 [VMEXIT_CR1_WRITE] = "CR1_WRITE",
2151 [VMEXIT_CR2_WRITE] = "CR2_WRITE",
2152 [VMEXIT_CR3_WRITE] = "CR3_WRITE",
2153 [VMEXIT_CR4_WRITE] = "CR4_WRITE",
2154 [VMEXIT_CR5_WRITE] = "CR5_WRITE",
2155 [VMEXIT_CR6_WRITE] = "CR6_WRITE",
2156 [VMEXIT_CR7_WRITE] = "CR7_WRITE",
2157 [VMEXIT_CR8_WRITE] = "CR8_WRITE",
2158 [VMEXIT_CR9_WRITE] = "CR9_WRITE",
2159 [VMEXIT_CR10_WRITE] = "CR10_WRITE",
2160 [VMEXIT_CR11_WRITE] = "CR11_WRITE",
2161 [VMEXIT_CR12_WRITE] = "CR12_WRITE",
2162 [VMEXIT_CR13_WRITE] = "CR13_WRITE",
2163 [VMEXIT_CR14_WRITE] = "CR14_WRITE",
2164 [VMEXIT_CR15_WRITE] = "CR15_WRITE",
2165 [VMEXIT_DR0_READ] = "DR0_READ",
2166 [VMEXIT_DR1_READ] = "DR1_READ",
2167 [VMEXIT_DR2_READ] = "DR2_READ",
2168 [VMEXIT_DR3_READ] = "DR3_READ",
2169 [VMEXIT_DR4_READ] = "DR4_READ",
2170 [VMEXIT_DR5_READ] = "DR5_READ",
2171 [VMEXIT_DR6_READ] = "DR6_READ",
2172 [VMEXIT_DR7_READ] = "DR7_READ",
2173 [VMEXIT_DR8_READ] = "DR8_READ",
2174 [VMEXIT_DR9_READ] = "DR9_READ",
2175 [VMEXIT_DR10_READ] = "DR10_READ",
2176 [VMEXIT_DR11_READ] = "DR11_READ",
2177 [VMEXIT_DR12_READ] = "DR12_READ",
2178 [VMEXIT_DR13_READ] = "DR13_READ",
2179 [VMEXIT_DR14_READ] = "DR14_READ",
2180 [VMEXIT_DR15_READ] = "DR15_READ",
2181 [VMEXIT_DR0_WRITE] = "DR0_WRITE",
2182 [VMEXIT_DR1_WRITE] = "DR1_WRITE",
2183 [VMEXIT_DR2_WRITE] = "DR2_WRITE",
2184 [VMEXIT_DR3_WRITE] = "DR3_WRITE",
2185 [VMEXIT_DR4_WRITE] = "DR4_WRITE",
2186 [VMEXIT_DR5_WRITE] = "DR5_WRITE",
2187 [VMEXIT_DR6_WRITE] = "DR6_WRITE",
2188 [VMEXIT_DR7_WRITE] = "DR7_WRITE",
2189 [VMEXIT_DR8_WRITE] = "DR8_WRITE",
2190 [VMEXIT_DR9_WRITE] = "DR9_WRITE",
2191 [VMEXIT_DR10_WRITE] = "DR10_WRITE",
2192 [VMEXIT_DR11_WRITE] = "DR11_WRITE",
2193 [VMEXIT_DR12_WRITE] = "DR12_WRITE",
2194 [VMEXIT_DR13_WRITE] = "DR13_WRITE",
2195 [VMEXIT_DR14_WRITE] = "DR14_WRITE",
2196 [VMEXIT_DR15_WRITE] = "DR15_WRITE",
2197 [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
2198 [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
2199 [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
2200 [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
2201 [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
2202 [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
2203 [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
2204 [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
2205 [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
2206 [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
2207 [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
2208 [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
2209 [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
2210 [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
2211 [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
2212 [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
2213 [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
2214 [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
2215 [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
2216 [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
2217 [VMEXIT_INTR] = "INTR",
2218 [VMEXIT_NMI] = "NMI",
2219 [VMEXIT_SMI] = "SMI",
2220 [VMEXIT_INIT] = "INIT",
2221 [VMEXIT_VINTR] = "VINTR",
2222 [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
2223 [VMEXIT_IDTR_READ] = "IDTR_READ",
2224 [VMEXIT_GDTR_READ] = "GDTR_READ",
2225 [VMEXIT_LDTR_READ] = "LDTR_READ",
2226 [VMEXIT_TR_READ] = "TR_READ",
2227 [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
2228 [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
2229 [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
2230 [VMEXIT_TR_WRITE] = "TR_WRITE",
2231 [VMEXIT_RDTSC] = "RDTSC",
2232 [VMEXIT_RDPMC] = "RDPMC",
2233 [VMEXIT_PUSHF] = "PUSHF",
2234 [VMEXIT_POPF] = "POPF",
2235 [VMEXIT_CPUID] = "CPUID",
2236 [VMEXIT_RSM] = "RSM",
2237 [VMEXIT_IRET] = "IRET",
2238 [VMEXIT_SWINT] = "SWINT",
2239 [VMEXIT_INVD] = "INVD",
2240 [VMEXIT_PAUSE] = "PAUSE",
2241 [VMEXIT_HLT] = "HLT",
2242 [VMEXIT_INVLPG] = "INVLPG",
2243 [VMEXIT_INVLPGA] = "INVLPGA",
2244 [VMEXIT_IOIO] = "IOIO",
2245 [VMEXIT_MSR] = "MSR",
2246 [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
2247 [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
2248 [VMEXIT_SHUTDOWN] = "SHUTDOWN",
2249 [VMEXIT_VMRUN] = "VMRUN",
2250 [VMEXIT_VMMCALL] = "VMMCALL",
2251 [VMEXIT_VMLOAD] = "VMLOAD",
2252 [VMEXIT_VMSAVE] = "VMSAVE",
2253 [VMEXIT_STGI] = "STGI",
2254 [VMEXIT_CLGI] = "CLGI",
2255 [VMEXIT_SKINIT] = "SKINIT",
2256 [VMEXIT_RDTSCP] = "RDTSCP",
2257 [VMEXIT_ICEBP] = "ICEBP",
2258 [VMEXIT_NPF] = "NPF"
2259 };
2260 #endif /* SVM_EXTRA_DEBUG */
2262 #ifdef SVM_WALK_GUEST_PAGES
2263 void walk_shadow_and_guest_pt(unsigned long gva)
2265 l2_pgentry_t gpde;
2266 l2_pgentry_t spde;
2267 l1_pgentry_t gpte;
2268 l1_pgentry_t spte;
2269 struct vcpu *v = current;
2270 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2271 unsigned long gpa;
2273 gpa = gva_to_gpa( gva );
2274 printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
2275 if( !svm_paging_enabled(v) || mmio_space( gpa ) )
2277 return;
2280 /* let's dump the guest and shadow page info */
2282 __guest_get_l2e(v, gva, &gpde);
2283 printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
2284 __shadow_get_l2e( v, gva, &spde );
2285 printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
2287 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
2288 return;
2290 spte = l1e_empty();
2292 // This is actually overkill - we only need to make sure the hl2 is in-sync.
2293 shadow_sync_va(v, gva);
2295 gpte.l1 = 0;
2296 __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
2297 printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
2298 __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
2299 printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
2301 #endif /* SVM_WALK_GUEST_PAGES */
2303 asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
2305 unsigned int exit_reason;
2306 unsigned long eip;
2307 struct vcpu *v = current;
2308 int error;
2309 int do_debug = 0;
2310 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2312 ASSERT(vmcb);
2314 exit_reason = vmcb->exitcode;
2315 save_svm_cpu_user_regs(v, &regs);
2316 v->arch.hvm_svm.injecting_event = 0;
2318 vmcb->tlb_control = 0;
2320 #ifdef SVM_EXTRA_DEBUG
2322 #if defined(__i386__)
2323 #define rip eip
2324 #endif
2326 static unsigned long intercepts_counter = 0;
2328 if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
2330 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2332 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2333 intercepts_counter,
2334 exit_reasons[exit_reason], exit_reason, regs.cs,
2335 (unsigned long long) regs.rip,
2336 (unsigned long long) vmcb->exitinfo1,
2337 (unsigned long long) vmcb->exitinfo2,
2338 (unsigned long long) vmcb->exitintinfo.bytes);
2341 else if (svm_dbg_on
2342 && exit_reason != VMEXIT_IOIO
2343 && exit_reason != VMEXIT_INTR)
2346 if (exit_reasons[exit_reason])
2348 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2349 intercepts_counter,
2350 exit_reasons[exit_reason], exit_reason, regs.cs,
2351 (unsigned long long) regs.rip,
2352 (unsigned long long) vmcb->exitinfo1,
2353 (unsigned long long) vmcb->exitinfo2,
2354 (unsigned long long) vmcb->exitintinfo.bytes);
2356 else
2358 printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2359 intercepts_counter, exit_reason, exit_reason, regs.cs,
2360 (unsigned long long) regs.rip,
2361 (unsigned long long) vmcb->exitinfo1,
2362 (unsigned long long) vmcb->exitinfo2,
2363 (unsigned long long) vmcb->exitintinfo.bytes);
2367 #ifdef SVM_WALK_GUEST_PAGES
2368 if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
2370 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2371 walk_shadow_and_guest_pt( vmcb->exitinfo2 );
2373 #endif
2375 intercepts_counter++;
2377 #if 0
2378 if (svm_dbg_on)
2379 do_debug = svm_do_debugout(exit_reason);
2380 #endif
2382 if (do_debug)
2384 printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
2385 "shadow_table = 0x%08x\n",
2386 __func__,
2387 (int) v->arch.guest_table.pfn,
2388 (int) v->arch.monitor_table.pfn,
2389 (int) v->arch.shadow_table.pfn);
2391 svm_dump_vmcb(__func__, vmcb);
2392 svm_dump_regs(__func__, &regs);
2393 svm_dump_inst(svm_rip2pointer(vmcb));
2396 #if defined(__i386__)
2397 #undef rip
2398 #endif
2401 #endif /* SVM_EXTRA_DEBUG */
2403 if (exit_reason == -1)
2405 printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
2406 __func__);
2407 BUG();
2408 domain_crash_synchronous();
2411 perfc_incra(vmexits, exit_reason);
2412 eip = vmcb->rip;
2414 #ifdef SVM_EXTRA_DEBUG
2415 if (do_debug)
2417 printk("eip = %lx, exit_reason = %d (0x%x)\n",
2418 eip, exit_reason, exit_reason);
2420 #endif /* SVM_EXTRA_DEBUG */
2422 TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
2424 switch (exit_reason)
2426 case VMEXIT_EXCEPTION_DB:
2428 #ifdef XEN_DEBUGGER
2429 svm_debug_save_cpu_user_regs(&regs);
2430 pdb_handle_exception(1, &regs, 1);
2431 svm_debug_restore_cpu_user_regs(&regs);
2432 #else
2433 svm_store_cpu_user_regs(&regs, v);
2434 domain_pause_for_debugger();
2435 do_sched_op(SCHEDOP_yield, 0);
2436 #endif
2438 break;
2440 case VMEXIT_NMI:
2441 do_nmi(&regs, 0);
2442 break;
2444 #ifdef XEN_DEBUGGER
2445 case VMEXIT_EXCEPTION_BP:
2446 svm_debug_save_cpu_user_regs(&regs);
2447 pdb_handle_exception(3, &regs, 1);
2448 svm_debug_restore_cpu_user_regs(&regs);
2449 break;
2450 #endif
2452 case VMEXIT_EXCEPTION_NM:
2453 svm_do_no_device_fault(vmcb);
2454 break;
2456 case VMEXIT_EXCEPTION_GP:
2457 /* This should probably not be trapped in the future */
2458 regs.error_code = vmcb->exitinfo1;
2459 v->arch.hvm_svm.injecting_event = 1;
2460 svm_do_general_protection_fault(v, &regs);
2461 break;
2463 case VMEXIT_EXCEPTION_PF:
2465 unsigned long va;
2466 va = vmcb->exitinfo2;
2467 regs.error_code = vmcb->exitinfo1;
2468 HVM_DBG_LOG(DBG_LEVEL_VMMU,
2469 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
2470 (unsigned long)regs.eax, (unsigned long)regs.ebx,
2471 (unsigned long)regs.ecx, (unsigned long)regs.edx,
2472 (unsigned long)regs.esi, (unsigned long)regs.edi);
2474 v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
2476 //printk("PF1\n");
2477 if (!(error = svm_do_page_fault(va, &regs)))
2479 v->arch.hvm_svm.injecting_event = 1;
2480 /* Inject #PG using Interruption-Information Fields */
2481 vmcb->eventinj.bytes = 0;
2482 vmcb->eventinj.fields.v = 1;
2483 vmcb->eventinj.fields.ev = 1;
2484 vmcb->eventinj.fields.errorcode = regs.error_code;
2485 vmcb->eventinj.fields.type = EVENTTYPE_EXCEPTION;
2486 vmcb->eventinj.fields.vector = TRAP_page_fault;
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 svm_stts(v);
2502 raise_softirq(SCHEDULE_SOFTIRQ);
2503 break;
2505 case VMEXIT_GDTR_WRITE:
2506 printk("WRITE to GDTR\n");
2507 break;
2509 case VMEXIT_TASK_SWITCH:
2510 __hvm_bug(&regs);
2511 break;
2513 case VMEXIT_CPUID:
2514 svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
2515 break;
2517 case VMEXIT_HLT:
2518 svm_vmexit_do_hlt(vmcb);
2519 break;
2521 case VMEXIT_INVLPG:
2522 svm_handle_invlpg(0, &regs);
2523 break;
2525 case VMEXIT_INVLPGA:
2526 svm_handle_invlpg(1, &regs);
2527 break;
2529 case VMEXIT_VMMCALL:
2530 svm_do_vmmcall(v, &regs);
2531 break;
2533 case VMEXIT_CR0_READ:
2534 svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
2535 break;
2537 case VMEXIT_CR2_READ:
2538 svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
2539 break;
2541 case VMEXIT_CR3_READ:
2542 svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
2543 break;
2545 case VMEXIT_CR4_READ:
2546 svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
2547 break;
2549 case VMEXIT_CR8_READ:
2550 svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
2551 break;
2553 case VMEXIT_CR0_WRITE:
2554 svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
2555 break;
2557 case VMEXIT_CR2_WRITE:
2558 svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
2559 break;
2561 case VMEXIT_CR3_WRITE:
2562 svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
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;
2680 int core = smp_processor_id();
2681 /*
2682 * if need to assign new asid or if switching cores,
2683 * then retire asid for old core, and assign new for new core.
2684 */
2685 if( svm_dbg_on)
2686 printk("old core %d new core %d\n",(int)v->arch.hvm_svm.core,(int)core);
2688 if( test_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags) ||
2689 (v->arch.hvm_svm.core != core)) {
2690 if(!asidpool_assign_next(vmcb, 1,
2691 v->arch.hvm_svm.core, core)) {
2692 BUG();
2695 clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
2697 #endif /* CONFIG_SVM */
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 */