ia64/xen-unstable

view xen/arch/x86/hvm/svm/svm.c @ 8801:65127e18d821

Attached patch for svm will enable a tlb flush for each vmrun.

Setting the tbl_control flag to 1 in the vmcb, causes a complete tlb
flush on this core. We have seen issues (blue screens) when utilizing
ASID granularity with WinxpSP1 running on cores>0. we have found that
flushing the TLBs each vmrun alleviates winxpsp1 crashes. We have also
sometimes seen a substantial performance improvement(!) when flushing
each vmrun, which was completely unexpected. We are continuing to
investigate root cause, but for the moment, we would like to just flush
each vmrun. Digging around in the SPT code might be necessary here also.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 09 00:13:46 2006 +0100 (2006-02-09)
parents 707cb68a391f
children 3cb8e672b115
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 #define SVM_EXTRA_DEBUG
55 #ifdef TRACE_BUFFER
56 static unsigned long trace_values[NR_CPUS][4];
57 #define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
58 #else
59 #define TRACE_VMEXIT(index,value) ((void)0)
60 #endif
62 /* Useful define */
63 #define MAX_INST_SIZE 15
65 /*
66 * External functions, etc. We should move these to some suitable header file(s) */
68 extern long evtchn_send(int lport);
69 extern void do_nmi(struct cpu_user_regs *, unsigned long);
70 extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
71 int inst_len);
72 extern asmlinkage void do_IRQ(struct cpu_user_regs *);
73 extern void smp_apic_timer_interrupt(struct cpu_user_regs *);
74 extern void timer_interrupt(int, void *, struct cpu_user_regs *);
75 extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
76 unsigned long count, int size, long value, int dir, int pvalid);
77 extern int svm_instrlen(struct cpu_user_regs *regs, int mode);
78 extern void svm_dump_inst(unsigned long eip);
79 extern int svm_dbg_on;
80 void svm_manual_event_injection32(struct vcpu *v, struct cpu_user_regs *regs,
81 int vector, int has_code);
82 void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
84 static struct asid_pool ASIDpool[NR_CPUS];
86 /*
87 * Initializes the POOL of ASID used by the guests per core.
88 */
89 void asidpool_init( int core )
90 {
91 int i;
92 ASIDpool[core].asid_lock = SPIN_LOCK_UNLOCKED;
93 spin_lock(&ASIDpool[core].asid_lock);
94 /* Host ASID is always in use */
95 ASIDpool[core].asid[INITIAL_ASID] = ASID_INUSE;
96 for( i=1; i<ASID_MAX; i++ )
97 {
98 ASIDpool[core].asid[i] = ASID_AVAILABLE;
99 }
100 spin_unlock(&ASIDpool[core].asid_lock);
101 }
104 /* internal function to get the next available ASID */
105 static int asidpool_fetch_next( struct vmcb_struct *vmcb, int core )
106 {
107 int i;
108 for( i = 1; i < ASID_MAX; i++ )
109 {
110 if( ASIDpool[core].asid[i] == ASID_AVAILABLE )
111 {
112 vmcb->guest_asid = i;
113 ASIDpool[core].asid[i] = ASID_INUSE;
114 return i;
115 }
116 }
117 return -1;
118 }
121 /*
122 * This functions assigns on the passed VMCB, the next
123 * available ASID number. If none are available, the
124 * TLB flush flag is set, and all retireds ASID
125 * are made available.
126 *
127 * Returns: 1 -- sucess;
128 * 0 -- failure -- no more ASID numbers
129 * available.
130 */
131 int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
132 int oldcore, int newcore )
133 {
134 int i;
135 int res = 1;
136 static unsigned long cnt=0;
138 spin_lock(&ASIDpool[oldcore].asid_lock);
139 if( retire_current && vmcb->guest_asid ) {
140 ASIDpool[oldcore].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
141 }
142 spin_unlock(&ASIDpool[oldcore].asid_lock);
143 spin_lock(&ASIDpool[newcore].asid_lock);
144 if( asidpool_fetch_next( vmcb, newcore ) < 0 ) {
145 if (svm_dbg_on)
146 printk( "SVM: tlb(%ld)\n", cnt++ );
147 /* FLUSH the TLB and all retired slots are made available */
148 vmcb->tlb_control = 1;
149 for( i = 1; i < ASID_MAX; i++ ) {
150 if( ASIDpool[newcore].asid[i] == ASID_RETIRED ) {
151 ASIDpool[newcore].asid[i] = ASID_AVAILABLE;
152 }
153 }
154 /* Get the First slot available */
155 res = asidpool_fetch_next( vmcb, newcore ) > 0;
156 }
157 spin_unlock(&ASIDpool[newcore].asid_lock);
158 return res;
159 }
161 void asidpool_retire( struct vmcb_struct *vmcb, int core )
162 {
163 spin_lock(&ASIDpool[core].asid_lock);
164 if( vmcb->guest_asid ) {
165 ASIDpool[core].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
166 }
167 spin_unlock(&ASIDpool[core].asid_lock);
168 }
170 static inline int svm_inject_exception(struct vcpu *v, int trap, int error_code)
171 {
172 void save_svm_cpu_user_regs(struct vcpu *, struct cpu_user_regs *);
173 struct cpu_user_regs regs;
175 printf("svm_inject_exception(trap %d, error_code 0x%x)\n",
176 trap, error_code);
177 save_svm_cpu_user_regs(v, &regs);
178 __hvm_bug(&regs);
179 }
181 void stop_svm(void)
182 {
183 u32 eax, edx;
185 /* We turn off the EFER_SVME bit. */
186 rdmsr(MSR_EFER, eax, edx);
187 eax &= ~EFER_SVME;
188 wrmsr(MSR_EFER, eax, edx);
190 printk("AMD SVM Extension is disabled.\n");
191 }
193 int svm_initialize_guest_resources(struct vcpu *v)
194 {
195 svm_final_setup_guest(v);
196 return 1;
197 }
199 int svm_relinquish_guest_resources(struct vcpu *v)
200 {
201 svm_relinquish_resources(v);
202 return 1;
203 }
205 void svm_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
206 {
207 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
209 #if defined (__x86_64__)
210 regs->rip = vmcb->rip;
211 regs->rsp = vmcb->rsp;
212 regs->rflags = vmcb->rflags;
213 regs->cs = vmcb->cs.sel;
214 regs->ds = vmcb->ds.sel;
215 regs->es = vmcb->es.sel;
216 regs->ss = vmcb->ss.sel;
217 regs->gs = vmcb->gs.sel;
218 regs->fs = vmcb->fs.sel;
219 #elif defined (__i386__)
220 regs->eip = vmcb->rip;
221 regs->esp = vmcb->rsp;
222 regs->eflags = vmcb->rflags;
223 regs->cs = vmcb->cs.sel;
224 regs->ds = vmcb->ds.sel;
225 regs->es = vmcb->es.sel;
226 regs->ss = vmcb->ss.sel;
227 regs->gs = vmcb->gs.sel;
228 regs->fs = vmcb->fs.sel;
229 #endif
230 }
232 void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
233 {
234 svm_load_cpu_user_regs(v, regs);
235 }
237 #ifdef __x86_64__
238 static struct svm_msr_state percpu_msr[NR_CPUS];
240 static u32 msr_data_index[VMX_MSR_COUNT] =
241 {
242 MSR_LSTAR, MSR_STAR, MSR_CSTAR,
243 MSR_SYSCALL_MASK, MSR_EFER,
244 };
246 void svm_save_segments(struct vcpu *v)
247 {
248 rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_svm.msr_content.shadow_gs);
249 }
251 /*
252 * To avoid MSR save/restore at every VM exit/entry time, we restore
253 * the x86_64 specific MSRs at domain switch time. Since those MSRs are
254 * are not modified once set for generic domains, we don't save them,
255 * but simply reset them to the values set at percpu_traps_init().
256 */
257 void svm_load_msrs(struct vcpu *n)
258 {
259 struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
260 int i;
262 if ( !hvm_switch_on )
263 return;
265 while ( host_state->flags )
266 {
267 i = find_first_set_bit(host_state->flags);
268 wrmsrl(msr_data_index[i], host_state->msr_items[i]);
269 clear_bit(i, &host_state->flags);
270 }
271 }
273 static void svm_save_init_msrs(void)
274 {
275 struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
276 int i;
278 for ( i = 0; i < SVM_MSR_COUNT; i++ )
279 rdmsrl(msr_data_index[i], host_state->msr_items[i]);
280 }
282 #define CASE_READ_MSR(address) \
283 case MSR_ ## address: \
284 msr_content = msr->msr_items[SVM_INDEX_MSR_ ## address]; \
285 break
287 #define CASE_WRITE_MSR(address) \
288 case MSR_ ## address: \
289 msr->msr_items[SVM_INDEX_MSR_ ## address] = msr_content; \
290 if (!test_bit(SVM_INDEX_MSR_ ## address, &msr->flags)) \
291 { \
292 set_bit(SVM_INDEX_MSR_ ## address, &msr->flags); \
293 } \
294 break
297 #define IS_CANO_ADDRESS(add) 1
299 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
300 {
301 u64 msr_content = 0;
302 struct vcpu *vc = current;
303 struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
304 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
306 switch (regs->ecx)
307 {
308 case MSR_EFER:
309 msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
310 HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n",
311 (unsigned long long)msr_content);
313 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
314 msr_content |= 1 << _EFER_LME;
316 if (SVM_LONG_GUEST(vc))
317 msr_content |= 1 << _EFER_LMA;
319 break;
321 case MSR_FS_BASE:
322 if (!(SVM_LONG_GUEST(vc)))
323 /* XXX should it be GP fault */
324 domain_crash_synchronous();
326 msr_content = vmcb->fs.base;
327 break;
329 case MSR_GS_BASE:
330 if (!(SVM_LONG_GUEST(vc)))
331 domain_crash_synchronous();
333 msr_content = vmcb->gs.base;
334 break;
336 case MSR_SHADOW_GS_BASE:
337 msr_content = msr->shadow_gs;
338 break;
340 CASE_READ_MSR(STAR);
341 CASE_READ_MSR(LSTAR);
342 CASE_READ_MSR(CSTAR);
343 CASE_READ_MSR(SYSCALL_MASK);
344 default:
345 return 0;
346 }
348 HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n",
349 msr_content);
351 regs->eax = msr_content & 0xffffffff;
352 regs->edx = msr_content >> 32;
353 return 1;
354 }
356 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
357 {
358 u64 msr_content = regs->eax | ((u64)regs->edx << 32);
359 struct vcpu *vc = current;
360 struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
361 struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
362 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
364 HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n",
365 regs->ecx, msr_content);
367 switch (regs->ecx)
368 {
369 case MSR_EFER:
370 if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
371 &vc->arch.hvm_svm.cpu_state))
372 {
373 if (test_bit(SVM_CPU_STATE_PG_ENABLED, &vc->arch.hvm_svm.cpu_state)
374 || !test_bit(SVM_CPU_STATE_PAE_ENABLED,
375 &vc->arch.hvm_svm.cpu_state))
376 {
377 svm_inject_exception(vc, TRAP_gp_fault, 0);
378 }
379 }
381 if (msr_content & EFER_LME)
382 set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
384 /* No update for LME/LMA since it have no effect */
385 msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
386 if (msr_content & ~(EFER_LME | EFER_LMA))
387 {
388 msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
389 if (!test_bit(SVM_INDEX_MSR_EFER, &msr->flags))
390 {
391 rdmsrl(MSR_EFER, host_state->msr_items[SVM_INDEX_MSR_EFER]);
392 set_bit(SVM_INDEX_MSR_EFER, &host_state->flags);
393 set_bit(SVM_INDEX_MSR_EFER, &msr->flags);
394 wrmsrl(MSR_EFER, msr_content);
395 }
396 }
397 break;
399 case MSR_FS_BASE:
400 case MSR_GS_BASE:
401 if (!(SVM_LONG_GUEST(vc)))
402 domain_crash_synchronous();
404 if (!IS_CANO_ADDRESS(msr_content))
405 {
406 HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
407 svm_inject_exception(vc, TRAP_gp_fault, 0);
408 }
410 if (regs->ecx == MSR_FS_BASE)
411 vmcb->fs.base = msr_content;
412 else
413 vmcb->gs.base = msr_content;
414 break;
416 case MSR_SHADOW_GS_BASE:
417 if (!(SVM_LONG_GUEST(vc)))
418 domain_crash_synchronous();
420 vc->arch.hvm_svm.msr_content.shadow_gs = msr_content;
421 wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
422 break;
424 CASE_WRITE_MSR(STAR);
425 CASE_WRITE_MSR(LSTAR);
426 CASE_WRITE_MSR(CSTAR);
427 CASE_WRITE_MSR(SYSCALL_MASK);
428 default:
429 return 0;
430 }
431 return 1;
432 }
434 void
435 svm_restore_msrs(struct vcpu *v)
436 {
437 int i = 0;
438 struct svm_msr_state *guest_state;
439 struct svm_msr_state *host_state;
440 unsigned long guest_flags;
442 guest_state = &v->arch.hvm_svm.msr_content;;
443 host_state = &percpu_msr[smp_processor_id()];
445 wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
446 guest_flags = guest_state->flags;
447 if (!guest_flags)
448 return;
450 while (guest_flags){
451 i = find_first_set_bit(guest_flags);
453 HVM_DBG_LOG(DBG_LEVEL_2,
454 "restore guest's index %d msr %lx with %lx\n",
455 i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]);
456 set_bit(i, &host_state->flags);
457 wrmsrl(msr_data_index[i], guest_state->msr_items[i]);
458 clear_bit(i, &guest_flags);
459 }
460 }
461 #else
462 #define svm_save_init_msrs() ((void)0)
464 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
465 {
466 return 0;
467 }
469 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
470 {
471 return 0;
472 }
473 #endif
475 void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
476 {
477 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
479 crs[0] = vmcb->cr0;
480 crs[3] = vmcb->cr3;
481 crs[4] = vmcb->cr4;
482 }
484 void svm_modify_guest_state(struct vcpu *v)
485 {
486 svm_modify_vmcb(v, &v->arch.guest_context.user_regs);
487 }
489 int svm_realmode(struct vcpu *v)
490 {
491 unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
492 unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
494 return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
495 }
497 int svm_instruction_length(struct vcpu *v)
498 {
499 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
500 unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
502 mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
503 return svm_instrlen(guest_cpu_user_regs(), mode);
504 }
506 int start_svm(void)
507 {
508 u32 eax, ecx, edx;
510 /* Xen does not fill x86_capability words except 0. */
511 ecx = cpuid_ecx(0x80000001);
512 boot_cpu_data.x86_capability[5] = ecx;
514 if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
515 return 0;
517 rdmsr(MSR_EFER, eax, edx);
518 eax |= EFER_SVME;
519 wrmsr(MSR_EFER, eax, edx);
520 asidpool_init(smp_processor_id());
521 printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
523 svm_save_init_msrs();
525 /* Setup HVM interfaces */
526 hvm_funcs.disable = stop_svm;
528 hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
529 hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
531 hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
532 hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
534 #ifdef __x86_64__
535 hvm_funcs.save_segments = svm_save_segments;
536 hvm_funcs.load_msrs = svm_load_msrs;
537 hvm_funcs.restore_msrs = svm_restore_msrs;
538 #endif
540 hvm_funcs.store_cpu_guest_ctrl_regs = svm_store_cpu_guest_ctrl_regs;
541 hvm_funcs.modify_guest_state = svm_modify_guest_state;
543 hvm_funcs.realmode = svm_realmode;
544 hvm_funcs.paging_enabled = svm_paging_enabled;
545 hvm_funcs.instruction_length = svm_instruction_length;
547 hvm_enabled = 1;
549 return 1;
550 }
552 int svm_dbg_on = 0;
554 static inline int svm_do_debugout(unsigned long exit_code)
555 {
556 int i;
558 static unsigned long counter = 0;
559 static unsigned long works[] =
560 {
561 VMEXIT_IOIO,
562 VMEXIT_HLT,
563 VMEXIT_CPUID,
564 VMEXIT_DR0_READ,
565 VMEXIT_DR1_READ,
566 VMEXIT_DR2_READ,
567 VMEXIT_DR3_READ,
568 VMEXIT_DR6_READ,
569 VMEXIT_DR7_READ,
570 VMEXIT_DR0_WRITE,
571 VMEXIT_DR1_WRITE,
572 VMEXIT_DR2_WRITE,
573 VMEXIT_DR3_WRITE,
574 VMEXIT_CR0_READ,
575 VMEXIT_CR0_WRITE,
576 VMEXIT_CR3_READ,
577 VMEXIT_CR4_READ,
578 VMEXIT_MSR,
579 VMEXIT_CR0_WRITE,
580 VMEXIT_CR3_WRITE,
581 VMEXIT_CR4_WRITE,
582 VMEXIT_EXCEPTION_PF,
583 VMEXIT_INTR,
584 VMEXIT_INVLPG,
585 VMEXIT_EXCEPTION_NM
586 };
589 #if 0
590 if (svm_dbg_on && exit_code != 0x7B)
591 return 1;
592 #endif
594 counter++;
596 #if 0
597 if ((exit_code == 0x4E
598 || exit_code == VMEXIT_CR0_READ
599 || exit_code == VMEXIT_CR0_WRITE)
600 && counter < 200000)
601 return 0;
603 if ((exit_code == 0x4E) && counter < 500000)
604 return 0;
605 #endif
607 for (i = 0; i < sizeof(works) / sizeof(works[0]); i++)
608 if (exit_code == works[i])
609 return 0;
611 return 1;
612 }
615 void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
616 {
617 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
619 ASSERT(vmcb);
621 ctxt->eax = vmcb->rax;
622 ctxt->ss = vmcb->ss.sel;
623 ctxt->esp = vmcb->rsp;
624 ctxt->eflags = vmcb->rflags;
625 ctxt->cs = vmcb->cs.sel;
626 ctxt->eip = vmcb->rip;
628 ctxt->gs = vmcb->gs.sel;
629 ctxt->fs = vmcb->fs.sel;
630 ctxt->es = vmcb->es.sel;
631 ctxt->ds = vmcb->ds.sel;
632 }
634 #if defined (__x86_64__)
635 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *c )
636 {
637 }
638 #elif defined (__i386__)
639 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
640 {
641 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
643 regs->eip = vmcb->rip;
644 regs->esp = vmcb->rsp;
645 regs->eflags = vmcb->rflags;
646 regs->cs = vmcb->cs.sel;
647 regs->ds = vmcb->ds.sel;
648 regs->es = vmcb->es.sel;
649 regs->ss = vmcb->ss.sel;
650 }
651 #endif
653 /* XXX Use svm_load_cpu_guest_regs instead */
654 #if defined (__i386__)
655 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
656 {
657 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
658 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
660 /* Write the guest register value into VMCB */
661 vmcb->rax = regs->eax;
662 vmcb->ss.sel = regs->ss;
663 vmcb->rsp = regs->esp;
664 vmcb->rflags = regs->eflags;
665 vmcb->cs.sel = regs->cs;
666 vmcb->rip = regs->eip;
667 if (regs->eflags & EF_TF)
668 *intercepts |= EXCEPTION_BITMAP_DB;
669 else
670 *intercepts &= ~EXCEPTION_BITMAP_DB;
671 }
672 #else /* (__i386__) */
673 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
674 {
675 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
676 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
678 /* Write the guest register value into VMCB */
679 vmcb->rax = regs->rax;
680 vmcb->ss.sel = regs->ss;
681 vmcb->rsp = regs->rsp;
682 vmcb->rflags = regs->rflags;
683 vmcb->cs.sel = regs->cs;
684 vmcb->rip = regs->rip;
685 if (regs->rflags & EF_TF)
686 *intercepts |= EXCEPTION_BITMAP_DB;
687 else
688 *intercepts &= ~EXCEPTION_BITMAP_DB;
689 }
690 #endif /* !(__i386__) */
692 int svm_paging_enabled(struct vcpu *v)
693 {
694 unsigned long cr0;
696 cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
698 return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
699 }
702 /* Make sure that xen intercepts any FP accesses from current */
703 void svm_stts(struct vcpu *v)
704 {
705 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
707 ASSERT(vmcb);
709 vmcb->cr0 |= X86_CR0_TS;
711 if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
712 v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
713 }
715 static void arch_svm_do_launch(struct vcpu *v)
716 {
717 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
718 int error;
720 #if 0
721 if (svm_dbg_on)
722 printk("Do launch\n");
723 #endif
724 error = construct_vmcb(&v->arch.hvm_svm, regs);
725 if ( error < 0 )
726 {
727 if (v->vcpu_id == 0) {
728 printk("Failed to construct a new VMCB for BSP.\n");
729 } else {
730 printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
731 }
732 domain_crash_synchronous();
733 }
735 svm_do_launch(v);
736 #if 0
737 if (svm_dbg_on)
738 svm_dump_host_regs(__func__);
739 #endif
740 reset_stack_and_jump(svm_asm_do_launch);
741 }
743 void svm_final_setup_guest(struct vcpu *v)
744 {
745 v->arch.schedule_tail = arch_svm_do_launch;
747 if (v == v->domain->vcpu[0])
748 {
749 struct domain *d = v->domain;
750 struct vcpu *vc;
752 /* Initialize monitor page table */
753 for_each_vcpu(d, vc)
754 vc->arch.monitor_table = mk_pagetable(0);
756 /*
757 * Required to do this once per domain
758 * TODO: add a seperate function to do these.
759 */
760 memset(&d->shared_info->evtchn_mask[0], 0xff,
761 sizeof(d->shared_info->evtchn_mask));
763 /*
764 * Put the domain in shadow mode even though we're going to be using
765 * the shared 1:1 page table initially. It shouldn't hurt
766 */
767 shadow_mode_enable(d,
768 SHM_enable|SHM_refcounts|
769 SHM_translate|SHM_external|SHM_wr_pt_pte);
770 }
771 }
774 void svm_relinquish_resources(struct vcpu *v)
775 {
776 struct hvm_virpit *vpit;
777 extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
779 #if 0
780 /*
781 * This is not stored at the moment. We need to keep it somewhere and free
782 * it Or maybe not, as it's a per-cpu-core item, and I guess we don't
783 * normally remove CPU's other than for hot-plug capable systems, where I
784 * guess we have to allocate and free host-save area in this case. Let's
785 * not worry about it at the moment, as loosing one page per CPU hot-plug
786 * event doesn't seem that excessive. But I may be wrong.
787 */
788 free_host_save_area(v->arch.hvm_svm.host_save_area);
789 #endif
791 if (v->vcpu_id == 0) {
792 /* unmap IO shared page */
793 struct domain *d = v->domain;
794 if (d->arch.hvm_domain.shared_page_va)
795 unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va);
796 }
798 destroy_vmcb(&v->arch.hvm_svm);
799 free_monitor_pagetable(v);
800 vpit = &v->domain->arch.hvm_domain.vpit;
801 kill_timer(&vpit->pit_timer);
802 kill_timer(&v->arch.hvm_svm.hlt_timer);
803 if ( hvm_apic_support(v->domain) ) {
804 kill_timer( &(VLAPIC(v)->vlapic_timer) );
805 xfree( VLAPIC(v) );
806 }
807 }
810 void arch_svm_do_resume(struct vcpu *v)
811 {
812 svm_do_resume(v);
813 reset_stack_and_jump(svm_asm_do_resume);
814 }
817 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
818 {
819 struct vcpu *v = current;
820 unsigned long eip;
821 unsigned long gpa; /* FIXME: PAE */
822 int result;
823 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
825 ASSERT(vmcb);
827 //#if HVM_DEBUG
828 eip = vmcb->rip;
829 HVM_DBG_LOG(DBG_LEVEL_VMMU,
830 "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
831 va, eip, (unsigned long)regs->error_code);
832 //#endif
834 if ( !svm_paging_enabled(v) )
835 {
836 if ( shadow_direct_map_fault(va, regs) )
837 return 1;
839 handle_mmio(va, va);
840 TRACE_VMEXIT(2,2);
841 return 1;
842 }
844 update_pagetables(v);
846 gpa = gva_to_gpa(va);
848 /* Use 1:1 page table to identify MMIO address space */
849 if (mmio_space(gpa))
850 {
851 /* No support for APIC */
852 if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
853 {
854 unsigned long inst_len;
855 inst_len = svm_instruction_length(v);
856 if (inst_len == (unsigned long)-1)
857 {
858 printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
859 domain_crash_synchronous();
860 }
862 __update_guest_eip(vmcb, inst_len);
864 return 1;
865 }
867 TRACE_VMEXIT (2,2);
868 handle_mmio(va, gpa);
870 return 1;
871 }
873 result = shadow_fault(va, regs);
875 if( result ) {
876 /* Let's make sure that the Guest TLB is flushed */
877 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
878 }
880 TRACE_VMEXIT (2,result);
882 return result;
883 }
886 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
887 {
888 struct vcpu *v = current;
890 clts();
892 setup_fpu(v);
894 if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
895 vmcb->cr0 &= ~X86_CR0_TS;
897 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
898 }
901 static void svm_do_general_protection_fault(struct vcpu *v,
902 struct cpu_user_regs *regs)
903 {
904 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
905 unsigned long eip, error_code;
906 eventinj_t event;
908 ASSERT(vmcb);
910 eip = vmcb->rip;
911 error_code = vmcb->exitinfo1;
913 HVM_DBG_LOG(DBG_LEVEL_1,
914 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
915 eip, error_code);
917 HVM_DBG_LOG(DBG_LEVEL_1,
918 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
919 (unsigned long)regs->eax, (unsigned long)regs->ebx,
920 (unsigned long)regs->ecx, (unsigned long)regs->edx,
921 (unsigned long)regs->esi, (unsigned long)regs->edi);
924 /* Reflect it back into the guest */
925 event.bytes = 0;
926 event.fields.v = 1;
927 event.fields.type = EVENTTYPE_EXCEPTION;
928 event.fields.vector = 13;
929 event.fields.ev = 1;
930 event.fields.errorcode = error_code;
932 vmcb->eventinj = event;
933 }
935 /* Reserved bits: [31:14], [12:1] */
936 #define SVM_VCPU_CPUID_L1_RESERVED 0xffffdffe
938 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
939 struct cpu_user_regs *regs)
940 {
941 unsigned int eax, ebx, ecx, edx;
942 unsigned long eip;
943 struct vcpu *v = current;
944 unsigned int inst_len;
946 ASSERT(vmcb);
948 eip = vmcb->rip;
950 HVM_DBG_LOG(DBG_LEVEL_1,
951 "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
952 " (esi) %lx, (edi) %lx",
953 (unsigned long)regs->eax, (unsigned long)regs->ebx,
954 (unsigned long)regs->ecx, (unsigned long)regs->edx,
955 (unsigned long)regs->esi, (unsigned long)regs->edi);
957 cpuid(input, &eax, &ebx, &ecx, &edx);
959 if (input == 1)
960 {
961 if ( hvm_apic_support(v->domain) &&
962 !vlapic_global_enabled((VLAPIC(v))) )
963 clear_bit(X86_FEATURE_APIC, &edx);
965 #ifdef __x86_64__
966 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
967 #endif
968 {
969 clear_bit(X86_FEATURE_PSE, &edx);
970 clear_bit(X86_FEATURE_PAE, &edx);
971 clear_bit(X86_FEATURE_PSE36, &edx);
972 }
974 /* Clear out reserved bits. */
975 ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
976 }
977 #ifdef __i386__
978 else if ( input == 0x80000001 )
979 {
980 /* Mask feature for Intel ia32e or AMD long mode. */
981 clear_bit(X86_FEATURE_LM & 31, &edx);
982 }
983 #endif
985 regs->eax = (unsigned long)eax;
986 regs->ebx = (unsigned long)ebx;
987 regs->ecx = (unsigned long)ecx;
988 regs->edx = (unsigned long)edx;
990 HVM_DBG_LOG(DBG_LEVEL_1,
991 "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
992 "ebx=%x, ecx=%x, edx=%x",
993 eip, input, eax, ebx, ecx, edx);
995 inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
996 __update_guest_eip(vmcb, inst_len);
997 }
1000 static inline unsigned long *get_reg_p(unsigned int gpreg,
1001 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1003 unsigned long *reg_p = NULL;
1004 switch (gpreg)
1006 case SVM_REG_EAX:
1007 reg_p = (unsigned long *)&regs->eax;
1008 break;
1009 case SVM_REG_EBX:
1010 reg_p = (unsigned long *)&regs->ebx;
1011 break;
1012 case SVM_REG_ECX:
1013 reg_p = (unsigned long *)&regs->ecx;
1014 break;
1015 case SVM_REG_EDX:
1016 reg_p = (unsigned long *)&regs->edx;
1017 break;
1018 case SVM_REG_EDI:
1019 reg_p = (unsigned long *)&regs->edi;
1020 break;
1021 case SVM_REG_ESI:
1022 reg_p = (unsigned long *)&regs->esi;
1023 break;
1024 case SVM_REG_EBP:
1025 reg_p = (unsigned long *)&regs->ebp;
1026 break;
1027 case SVM_REG_ESP:
1028 reg_p = (unsigned long *)&vmcb->rsp;
1029 break;
1030 #if __x86_64__
1031 case SVM_REG_R8:
1032 reg_p = (unsigned long *)&regs->r8;
1033 break;
1034 case SVM_REG_R9:
1035 reg_p = (unsigned long *)&regs->r9;
1036 break;
1037 case SVM_REG_R10:
1038 reg_p = (unsigned long *)&regs->r10;
1039 break;
1040 case SVM_REG_R11:
1041 reg_p = (unsigned long *)&regs->r11;
1042 break;
1043 case SVM_REG_R12:
1044 reg_p = (unsigned long *)&regs->r12;
1045 break;
1046 case SVM_REG_R13:
1047 reg_p = (unsigned long *)&regs->r13;
1048 break;
1049 case SVM_REG_R14:
1050 reg_p = (unsigned long *)&regs->r14;
1051 break;
1052 case SVM_REG_R15:
1053 reg_p = (unsigned long *)&regs->r15;
1054 break;
1055 #endif
1056 default:
1057 BUG();
1060 return reg_p;
1064 static inline unsigned long get_reg(unsigned int gpreg,
1065 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1067 unsigned long *gp;
1068 gp = get_reg_p(gpreg, regs, vmcb);
1069 return *gp;
1073 static inline void set_reg(unsigned int gpreg, unsigned long value,
1074 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
1076 unsigned long *gp;
1077 gp = get_reg_p(gpreg, regs, vmcb);
1078 *gp = value;
1082 static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
1083 struct cpu_user_regs *regs)
1085 unsigned long *reg_p = 0;
1086 unsigned int gpreg = 0;
1087 unsigned long eip;
1088 unsigned int inst_len;
1089 struct vmcb_struct *vmcb;
1090 u8 buffer[MAX_INST_LEN];
1092 vmcb = v->arch.hvm_svm.vmcb;
1094 ASSERT(vmcb);
1096 eip = vmcb->rip;
1097 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1099 ASSERT(buffer[0] == 0x0f && (buffer[1] & 0xFD) == 0x21);
1101 gpreg = decode_src_reg(buffer[2]);
1102 #if DEBUG
1103 ASSERT(reg == decode_dest_reg(buffer[2]));
1104 #endif
1106 HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
1107 eip, reg, gpreg);
1109 reg_p = get_reg_p(gpreg, regs, vmcb);
1111 switch (type)
1113 case TYPE_MOV_TO_DR:
1114 inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
1115 v->arch.guest_context.debugreg[reg] = *reg_p;
1116 break;
1117 case TYPE_MOV_FROM_DR:
1118 inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
1119 *reg_p = v->arch.guest_context.debugreg[reg];
1120 break;
1121 default:
1122 __hvm_bug(regs);
1123 break;
1125 __update_guest_eip(vmcb, inst_len);
1129 static unsigned int check_for_null_selector(struct vmcb_struct *vmcb,
1130 unsigned int dir, unsigned long *base, unsigned int real)
1133 unsigned char inst[MAX_INST_LEN];
1134 segment_selector_t seg;
1135 int i;
1137 memset(inst, 0, MAX_INST_LEN);
1138 if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
1139 != MAX_INST_LEN)
1141 printk("check_for_null_selector: get guest instruction failed\n");
1142 domain_crash_synchronous();
1145 for (i = 0; i < MAX_INST_LEN; i++)
1147 switch (inst[i])
1149 case 0xf3: /* REPZ */
1150 case 0xf2: /* REPNZ */
1151 case 0xf0: /* LOCK */
1152 case 0x66: /* data32 */
1153 case 0x67: /* addr32 */
1154 #if __x86_64__
1155 /* REX prefixes */
1156 case 0x40:
1157 case 0x41:
1158 case 0x42:
1159 case 0x43:
1160 case 0x44:
1161 case 0x45:
1162 case 0x46:
1163 case 0x47:
1165 case 0x48:
1166 case 0x49:
1167 case 0x4a:
1168 case 0x4b:
1169 case 0x4c:
1170 case 0x4d:
1171 case 0x4e:
1172 case 0x4f:
1173 #endif
1174 continue;
1175 case 0x2e: /* CS */
1176 seg = vmcb->cs;
1177 break;
1178 case 0x36: /* SS */
1179 seg = vmcb->ss;
1180 break;
1181 case 0x26: /* ES */
1182 seg = vmcb->es;
1183 break;
1184 case 0x64: /* FS */
1185 seg = vmcb->fs;
1186 break;
1187 case 0x65: /* GS */
1188 seg = vmcb->gs;
1189 break;
1190 case 0x3e: /* DS */
1191 /* FALLTHROUGH */
1192 seg = vmcb->ds;
1193 break;
1194 default:
1195 if (dir == IOREQ_READ)
1196 seg = vmcb->es;
1197 else
1198 seg = vmcb->ds;
1201 /* In real Mode */
1202 if (real)
1203 seg.base = seg.sel << 4;
1205 if (base)
1206 *base = seg.base;
1208 return seg.attributes.fields.p;
1211 ASSERT(0);
1212 return 0;
1216 /* Get the address of INS/OUTS instruction */
1217 static inline unsigned long svm_get_io_address(struct vmcb_struct *vmcb,
1218 struct cpu_user_regs *regs, unsigned int dir, unsigned int real)
1220 unsigned long addr = 0;
1221 unsigned long base = 0;
1223 check_for_null_selector(vmcb, dir, &base, real);
1225 if (dir == IOREQ_WRITE)
1227 if (real)
1228 addr = (regs->esi & 0xFFFF) + base;
1229 else
1230 addr = regs->esi + base;
1232 else
1234 if (real)
1235 addr = (regs->edi & 0xFFFF) + base;
1236 else
1237 addr = regs->edi + base;
1240 return addr;
1244 static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs)
1246 struct mmio_op *mmio_opp;
1247 unsigned long eip, cs, eflags, cr0;
1248 unsigned long port;
1249 unsigned int real, size, dir;
1250 ioio_info_t info;
1252 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1254 ASSERT(vmcb);
1255 mmio_opp = &current->arch.hvm_vcpu.mmio_op;
1256 mmio_opp->instr = INSTR_PIO;
1257 mmio_opp->flags = 0;
1259 eip = vmcb->rip;
1260 cs = vmcb->cs.sel;
1261 eflags = vmcb->rflags;
1263 info.bytes = vmcb->exitinfo1;
1265 port = info.fields.port; /* port used to be addr */
1266 dir = info.fields.type; /* direction */
1267 if (info.fields.sz32)
1268 size = 4;
1269 else if (info.fields.sz16)
1270 size = 2;
1271 else
1272 size = 1;
1274 cr0 = vmcb->cr0;
1275 real = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
1277 HVM_DBG_LOG(DBG_LEVEL_IO,
1278 "svm_io_instruction: port 0x%lx real %d, eip=%lx:%lx, "
1279 "exit_qualification = %lx",
1280 (unsigned long) port, real, cs, eip, (unsigned long)info.bytes);
1282 /*
1283 * On SVM, the RIP of the intruction following the IN/OUT is saved in
1284 * ExitInfo2
1285 */
1286 vmcb->rip = vmcb->exitinfo2;
1288 /* string instruction */
1289 if (info.fields.str)
1291 unsigned long addr, count = 1;
1292 int sign = regs->eflags & EF_DF ? -1 : 1;
1294 addr = svm_get_io_address(vmcb, regs, dir, real);
1296 /* "rep" prefix */
1297 if (info.fields.rep)
1299 mmio_opp->flags |= REPZ;
1300 count = real ? regs->ecx & 0xFFFF : regs->ecx;
1303 /*
1304 * Handle string pio instructions that cross pages or that
1305 * are unaligned. See the comments in hvm_platform.c/handle_mmio()
1306 */
1307 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
1309 unsigned long value = 0;
1311 mmio_opp->flags |= OVERLAP;
1313 if (dir == IOREQ_WRITE)
1314 hvm_copy(&value, addr, size, HVM_COPY_IN);
1316 send_pio_req(regs, port, 1, size, value, dir, 0);
1318 else
1320 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
1322 if (sign > 0)
1323 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
1324 else
1325 count = (addr & ~PAGE_MASK) / size;
1328 send_pio_req(regs, port, count, size, addr, dir, 1);
1331 else
1333 if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
1334 hvm_print_line(v, regs->eax); /* guest debug output */
1336 send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
1341 static int svm_set_cr0(unsigned long value)
1343 struct vcpu *v = current;
1344 unsigned long mfn;
1345 int paging_enabled;
1346 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1348 ASSERT(vmcb);
1350 /* We don't want to lose PG. ET is reserved and should be always be 1*/
1351 paging_enabled = svm_paging_enabled(v);
1352 value |= X86_CR0_ET;
1353 vmcb->cr0 = value | X86_CR0_PG;
1354 v->arch.hvm_svm.cpu_shadow_cr0 = value;
1356 /* Check if FP Unit Trap need to be on */
1357 if (value & X86_CR0_TS)
1359 vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
1362 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
1364 if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
1366 /* The guest CR3 must be pointing to the guest physical. */
1367 if (!VALID_MFN(mfn =
1368 get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
1369 || !get_page(mfn_to_page(mfn), v->domain))
1371 printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
1372 domain_crash_synchronous(); /* need to take a clean path */
1375 #if defined(__x86_64__)
1376 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
1377 && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
1378 &v->arch.hvm_svm.cpu_state))
1380 HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
1381 svm_inject_exception(v, TRAP_gp_fault, 0);
1384 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
1386 /* Here the PAE is should to be opened */
1387 HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
1388 set_bit(SVM_CPU_STATE_LMA_ENABLED,
1389 &v->arch.hvm_svm.cpu_state);
1390 #if 0
1391 __vmread(VM_ENTRY_CONTROLS, &vm_entry_value);
1392 vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE;
1393 __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
1394 #else
1395 printk("Cannot yet set SVM_CPU_STATE_LMA_ENABLED\n");
1396 domain_crash_synchronous();
1397 #endif
1399 #if CONFIG_PAGING_LEVELS >= 4
1400 if (!shadow_set_guest_paging_levels(v->domain, 4))
1402 printk("Unsupported guest paging levels\n");
1403 domain_crash_synchronous(); /* need to take a clean path */
1405 #endif
1407 else
1409 #if CONFIG_PAGING_LEVELS >= 4
1410 if (!shadow_set_guest_paging_levels(v->domain, 2))
1412 printk("Unsupported guest paging levels\n");
1413 domain_crash_synchronous(); /* need to take a clean path */
1415 #endif
1418 #if 0
1419 unsigned long crn;
1421 /* update CR4's PAE if needed */
1422 __vmread(GUEST_CR4, &crn);
1423 if ((!(crn & X86_CR4_PAE))
1424 && test_bit(SVM_CPU_STATE_PAE_ENABLED,
1425 &v->arch.hvm_svm.cpu_state))
1427 HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
1428 __vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
1430 #else
1431 printk("Cannot yet set SVM_CPU_STATE_PAE_ENABLED\n");
1432 domain_crash_synchronous();
1433 #endif
1434 #elif defined(__i386__)
1436 unsigned long old_base_mfn;
1437 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1438 if (old_base_mfn)
1439 put_page(mfn_to_page(old_base_mfn));
1441 #endif
1442 #if CONFIG_PAGING_LEVELS == 2
1443 shadow_direct_map_clean(v);
1444 #endif
1445 /* Now arch.guest_table points to machine physical. */
1446 v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
1447 update_pagetables(v);
1449 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
1450 (unsigned long) (mfn << PAGE_SHIFT));
1452 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1453 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1455 /* arch->shadow_table should hold the next CR3 for shadow */
1456 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
1457 v->arch.hvm_svm.cpu_cr3, mfn);
1460 /*
1461 * SVM implements paged real-mode and when we return to real-mode
1462 * we revert back to the physical mappings that the domain builder
1463 * created.
1464 */
1465 if ((value & X86_CR0_PE) == 0) {
1466 if (value & X86_CR0_PG) {
1467 svm_inject_exception(v, TRAP_gp_fault, 0);
1468 return 0;
1471 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1472 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
1475 return 1;
1479 /*
1480 * Read from control registers. CR0 and CR4 are read from the shadow.
1481 */
1482 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
1484 unsigned long value = 0;
1485 struct vcpu *v = current;
1486 struct vmcb_struct *vmcb;
1488 vmcb = v->arch.hvm_svm.vmcb;
1489 ASSERT(vmcb);
1491 switch (cr)
1493 case 0:
1494 value = v->arch.hvm_svm.cpu_shadow_cr0;
1495 break;
1496 case 2:
1497 value = vmcb->cr2;
1498 break;
1499 case 3:
1500 value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
1501 break;
1502 case 4:
1503 value = vmcb->cr4;
1504 break;
1505 case 8:
1506 #if 0
1507 value = vmcb->m_cr8;
1508 #else
1509 ASSERT(0);
1510 #endif
1511 break;
1513 default:
1514 __hvm_bug(regs);
1517 set_reg(gp, value, regs, vmcb);
1519 HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
1523 /*
1524 * Write to control registers
1525 */
1526 static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
1528 unsigned long value;
1529 unsigned long old_cr;
1530 struct vcpu *v = current;
1531 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1533 ASSERT(vmcb);
1535 value = get_reg(gpreg, regs, vmcb);
1537 HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
1538 HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
1540 switch (cr)
1542 case 0:
1543 return svm_set_cr0(value);
1545 case 3:
1547 unsigned long old_base_mfn, mfn;
1549 /* If paging is not enabled yet, simply copy the value to CR3. */
1550 if (!svm_paging_enabled(v)) {
1551 v->arch.hvm_svm.cpu_cr3 = value;
1552 break;
1554 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1556 /* We make a new one if the shadow does not exist. */
1557 if (value == v->arch.hvm_svm.cpu_cr3)
1559 /*
1560 * This is simple TLB flush, implying the guest has
1561 * removed some translation or changed page attributes.
1562 * We simply invalidate the shadow.
1563 */
1564 mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
1565 if (mfn != pagetable_get_pfn(v->arch.guest_table))
1566 __hvm_bug(regs);
1567 shadow_sync_all(v->domain);
1569 else
1571 /*
1572 * If different, make a shadow. Check if the PDBR is valid
1573 * first.
1574 */
1575 HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
1576 if (((value >> PAGE_SHIFT) > v->domain->max_pages)
1577 || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
1578 || !get_page(mfn_to_page(mfn), v->domain))
1580 printk("Invalid CR3 value=%lx\n", value);
1581 domain_crash_synchronous(); /* need to take a clean path */
1584 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
1585 v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
1587 if (old_base_mfn)
1588 put_page(mfn_to_page(old_base_mfn));
1590 update_pagetables(v);
1592 /* arch.shadow_table should now hold the next CR3 for shadow*/
1593 v->arch.hvm_svm.cpu_cr3 = value;
1594 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
1595 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
1597 break;
1600 case 4:
1601 /* CR4 */
1602 if (value & X86_CR4_PAE)
1603 __hvm_bug(regs); /* not implemented */
1605 old_cr = vmcb->cr4;
1607 vmcb->cr4 = value;
1609 /*
1610 * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
1611 * all TLB entries except global entries.
1612 */
1613 if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
1615 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1616 shadow_sync_all(v->domain);
1618 break;
1620 default:
1621 printk("invalid cr: %d\n", cr);
1622 __hvm_bug(regs);
1625 return 1;
1629 #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
1632 static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
1633 struct cpu_user_regs *regs)
1635 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1636 unsigned int inst_len = 0;
1637 unsigned int gpreg;
1638 unsigned long value;
1639 u8 buffer[6];
1640 int result = 1;
1641 enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
1642 enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
1643 enum instruction_index match;
1645 ASSERT(vmcb);
1647 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
1649 if (type == TYPE_MOV_TO_CR)
1651 inst_len = __get_instruction_length_from_list(vmcb, list_a,
1652 ARR_SIZE(list_a), buffer, &match);
1654 else
1656 inst_len = __get_instruction_length_from_list(vmcb, list_b,
1657 ARR_SIZE(list_b), buffer, &match);
1660 HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
1662 switch (match)
1664 case INSTR_MOV2CR:
1665 gpreg = decode_src_reg(buffer[2]);
1666 result = mov_to_cr(gpreg, cr, regs);
1667 break;
1669 case INSTR_MOVCR2:
1670 gpreg = decode_src_reg(buffer[2]);
1671 mov_from_cr(cr, gpreg, regs);
1672 break;
1674 case INSTR_CLTS:
1675 clts();
1676 setup_fpu(current);
1677 vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
1678 v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
1679 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
1680 break;
1682 case INSTR_LMSW:
1683 if (svm_dbg_on)
1684 svm_dump_inst(svm_rip2pointer(vmcb));
1686 gpreg = decode_src_reg(buffer[2]);
1687 value = get_reg(gpreg, regs, vmcb) & 0xF;
1689 if (svm_dbg_on)
1690 printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1691 inst_len);
1693 value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
1695 if (svm_dbg_on)
1696 printk("CR0-LMSW CR0 - New value=%lx\n", value);
1698 result = svm_set_cr0(value);
1699 break;
1701 case INSTR_SMSW:
1702 svm_dump_inst(svm_rip2pointer(vmcb));
1703 value = v->arch.hvm_svm.cpu_shadow_cr0;
1704 gpreg = decode_src_reg(buffer[2]);
1705 set_reg(gpreg, value, regs, vmcb);
1707 if (svm_dbg_on)
1708 printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
1709 inst_len);
1710 break;
1712 default:
1713 __hvm_bug(regs);
1714 break;
1717 ASSERT(inst_len);
1719 __update_guest_eip(vmcb, inst_len);
1721 return result;
1724 static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
1726 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1727 unsigned int inst_len;
1728 int64_t tsc_sum;
1730 ASSERT(vmcb);
1732 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
1733 "exitinfo = %lx", (unsigned long)regs->ecx,
1734 (unsigned long)regs->eax, (unsigned long)regs->edx,
1735 (unsigned long)vmcb->exitinfo1);
1737 /* is it a read? */
1738 if (vmcb->exitinfo1 == 0)
1740 inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
1742 regs->edx = 0;
1743 switch (regs->ecx)
1745 case MSR_IA32_SYSENTER_CS:
1746 regs->eax = vmcb->sysenter_cs;
1747 break;
1748 case MSR_IA32_SYSENTER_ESP:
1749 regs->eax = vmcb->sysenter_esp;
1750 break;
1751 case MSR_IA32_SYSENTER_EIP:
1752 regs->eax = vmcb->sysenter_eip;
1753 break;
1754 case MSR_IA32_TIME_STAMP_COUNTER:
1755 __asm__ __volatile__("rdtsc" : "=a" (regs->eax), "=d" (regs->edx));
1756 tsc_sum = regs->edx;
1757 tsc_sum = (tsc_sum << 32) + regs->eax;
1758 tsc_sum += (int64_t) vmcb->tsc_offset;
1759 regs->eax = tsc_sum & 0xFFFFFFFF;
1760 regs->edx = (tsc_sum >> 32) & 0xFFFFFFFF;
1761 break;
1762 default:
1763 if (long_mode_do_msr_read(regs))
1764 goto done;
1765 rdmsr_user(regs->ecx, regs->eax, regs->edx);
1766 break;
1769 else
1771 inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
1773 switch (regs->ecx)
1775 case MSR_IA32_SYSENTER_CS:
1776 vmcb->sysenter_cs = regs->eax;
1777 break;
1778 case MSR_IA32_SYSENTER_ESP:
1779 vmcb->sysenter_esp = regs->eax;
1780 break;
1781 case MSR_IA32_SYSENTER_EIP:
1782 vmcb->sysenter_eip = regs->eax;
1783 break;
1784 default:
1785 long_mode_do_msr_write(regs);
1786 break;
1790 done:
1792 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
1793 "ecx=%lx, eax=%lx, edx=%lx",
1794 (unsigned long)regs->ecx, (unsigned long)regs->eax,
1795 (unsigned long)regs->edx);
1797 __update_guest_eip(vmcb, inst_len);
1801 /*
1802 * Need to use this exit to reschedule
1803 */
1804 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
1806 struct vcpu *v = current;
1807 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
1808 s_time_t next_pit = -1, next_wakeup;
1809 unsigned int inst_len;
1811 svm_stts(v);
1812 inst_len = __get_instruction_length(vmcb, INSTR_HLT, NULL);
1813 __update_guest_eip(vmcb, inst_len);
1815 if ( !v->vcpu_id ) {
1816 next_pit = get_pit_scheduled(v, vpit);
1818 next_wakeup = get_apictime_scheduled(v);
1819 if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
1820 next_wakeup = next_pit;
1822 if ( next_wakeup != - 1 )
1823 set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
1824 do_sched_op(SCHEDOP_block, 0);
1828 static inline void svm_vmexit_do_mwait(void)
1830 return;
1834 #ifdef XEN_DEBUGGER
1835 static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
1836 struct cpu_user_regs *regs)
1838 regs->eip = vmcb->rip;
1839 regs->esp = vmcb->rsp;
1840 regs->eflags = vmcb->rflags;
1842 regs->xcs = vmcb->cs.sel;
1843 regs->xds = vmcb->ds.sel;
1844 regs->xes = vmcb->es.sel;
1845 regs->xfs = vmcb->fs.sel;
1846 regs->xgs = vmcb->gs.sel;
1847 regs->xss = vmcb->ss.sel;
1851 static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
1853 vmcb->ss.sel = regs->xss;
1854 vmcb->rsp = regs->esp;
1855 vmcb->rflags = regs->eflags;
1856 vmcb->cs.sel = regs->xcs;
1857 vmcb->rip = regs->eip;
1859 vmcb->gs.sel = regs->xgs;
1860 vmcb->fs.sel = regs->xfs;
1861 vmcb->es.sel = regs->xes;
1862 vmcb->ds.sel = regs->xds;
1864 #endif
1867 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
1869 struct vcpu *v = current;
1870 u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
1871 unsigned long g_vaddr;
1872 unsigned int inst_len;
1873 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1875 ASSERT(vmcb);
1876 /*
1877 * Unknown how many bytes the invlpg instruction will take. Use the
1878 * maximum instruction length here
1879 */
1880 if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
1882 printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
1883 __hvm_bug(regs);
1886 if (invlpga)
1888 inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
1889 __update_guest_eip(vmcb, inst_len);
1891 /*
1892 * The address is implicit on this instruction At the moment, we don't
1893 * use ecx (ASID) to identify individual guests pages
1894 */
1895 g_vaddr = regs->eax;
1897 else
1899 /* What about multiple prefix codes? */
1900 prefix = (is_prefix(opcode[0])?opcode[0]:0);
1901 inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
1903 inst_len--;
1904 length -= inst_len;
1906 /*
1907 * Decode memory operand of the instruction including ModRM, SIB, and
1908 * displacement to get effecticve address and length in bytes. Assume
1909 * the system in either 32- or 64-bit mode.
1910 */
1911 g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
1912 &opcode[inst_len], &length);
1914 inst_len += length;
1915 __update_guest_eip (vmcb, inst_len);
1918 /* Overkill, we may not this */
1919 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
1920 shadow_invlpg(v, g_vaddr);
1924 /*
1925 * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
1926 * 16-bit realmode. Basically, this mimics a processor reset.
1928 * returns 0 on success, non-zero otherwise
1929 */
1930 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
1931 struct cpu_user_regs *regs)
1933 struct vmcb_struct *vmcb;
1935 ASSERT(v);
1936 ASSERT(regs);
1938 vmcb = v->arch.hvm_svm.vmcb;
1940 ASSERT(vmcb);
1942 /* clear the vmcb and user regs */
1943 memset(regs, 0, sizeof(struct cpu_user_regs));
1945 /* VMCB Control */
1946 vmcb->tsc_offset = 0;
1948 /* VMCB State */
1949 vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
1950 v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
1952 vmcb->cr2 = 0;
1953 vmcb->cr4 = 0;
1955 /* This will jump to ROMBIOS */
1956 vmcb->rip = 0xFFF0;
1958 /* setup the segment registers and all their hidden states */
1959 vmcb->cs.sel = 0xF000;
1960 vmcb->cs.attributes.bytes = 0x089b;
1961 vmcb->cs.limit = 0xffff;
1962 vmcb->cs.base = 0x000F0000;
1964 vmcb->ss.sel = 0x00;
1965 vmcb->ss.attributes.bytes = 0x0893;
1966 vmcb->ss.limit = 0xffff;
1967 vmcb->ss.base = 0x00;
1969 vmcb->ds.sel = 0x00;
1970 vmcb->ds.attributes.bytes = 0x0893;
1971 vmcb->ds.limit = 0xffff;
1972 vmcb->ds.base = 0x00;
1974 vmcb->es.sel = 0x00;
1975 vmcb->es.attributes.bytes = 0x0893;
1976 vmcb->es.limit = 0xffff;
1977 vmcb->es.base = 0x00;
1979 vmcb->fs.sel = 0x00;
1980 vmcb->fs.attributes.bytes = 0x0893;
1981 vmcb->fs.limit = 0xffff;
1982 vmcb->fs.base = 0x00;
1984 vmcb->gs.sel = 0x00;
1985 vmcb->gs.attributes.bytes = 0x0893;
1986 vmcb->gs.limit = 0xffff;
1987 vmcb->gs.base = 0x00;
1989 vmcb->ldtr.sel = 0x00;
1990 vmcb->ldtr.attributes.bytes = 0x0000;
1991 vmcb->ldtr.limit = 0x0;
1992 vmcb->ldtr.base = 0x00;
1994 vmcb->gdtr.sel = 0x00;
1995 vmcb->gdtr.attributes.bytes = 0x0000;
1996 vmcb->gdtr.limit = 0x0;
1997 vmcb->gdtr.base = 0x00;
1999 vmcb->tr.sel = 0;
2000 vmcb->tr.attributes.bytes = 0;
2001 vmcb->tr.limit = 0x0;
2002 vmcb->tr.base = 0;
2004 vmcb->idtr.sel = 0x00;
2005 vmcb->idtr.attributes.bytes = 0x0000;
2006 vmcb->idtr.limit = 0x3ff;
2007 vmcb->idtr.base = 0x00;
2009 vmcb->rax = 0;
2011 return 0;
2015 /*
2016 * svm_do_vmmcall - SVM VMMCALL handler
2018 * returns 0 on success, non-zero otherwise
2019 */
2020 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
2022 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2023 unsigned int inst_len;
2025 ASSERT(vmcb);
2026 ASSERT(regs);
2028 inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
2030 /* VMMCALL sanity check */
2031 if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
2033 printf("VMMCALL CPL check failed\n");
2034 return -1;
2037 /* handle the request */
2038 switch (regs->edi)
2040 case VMMCALL_RESET_TO_REALMODE:
2041 if (svm_do_vmmcall_reset_to_realmode(v, regs))
2043 printf("svm_do_vmmcall_reset_to_realmode() failed\n");
2044 return -1;
2047 /* since we just reset the VMCB, return without adjusting the eip */
2048 return 0;
2049 case VMMCALL_DEBUG:
2050 printf("DEBUG features not implemented yet\n");
2051 break;
2052 default:
2053 break;
2056 hvm_print_line(v, regs->eax); /* provides the current domain */
2058 __update_guest_eip(vmcb, inst_len);
2059 return 0;
2063 void svm_dump_inst(unsigned long eip)
2065 u8 opcode[256];
2066 unsigned long ptr;
2067 int len;
2068 int i;
2070 ptr = eip & ~0xff;
2071 len = 0;
2073 if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
2074 len = sizeof(opcode);
2076 printf("Code bytes around(len=%d) %lx:", len, eip);
2077 for (i = 0; i < len; i++)
2079 if ((i & 0x0f) == 0)
2080 printf("\n%08lx:", ptr+i);
2082 printf("%02x ", opcode[i]);
2085 printf("\n");
2089 void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
2091 struct vcpu *v = current;
2092 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2093 unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
2095 printf("%s: guest registers from %s:\n", __func__, from);
2096 #if defined (__x86_64__)
2097 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
2098 regs->rax, regs->rbx, regs->rcx);
2099 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
2100 regs->rdx, regs->rsi, regs->rdi);
2101 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
2102 regs->rbp, regs->rsp, regs->r8);
2103 printk("r9: %016lx r10: %016lx r11: %016lx\n",
2104 regs->r9, regs->r10, regs->r11);
2105 printk("r12: %016lx r13: %016lx r14: %016lx\n",
2106 regs->r12, regs->r13, regs->r14);
2107 printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
2108 regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
2109 #else
2110 printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
2111 regs->eax, regs->ebx, regs->ecx, regs->edx);
2112 printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
2113 regs->edi, regs->esi, regs->ebp, regs->esp);
2114 printf("%s: guest cr0: %lx\n", __func__,
2115 v->arch.hvm_svm.cpu_shadow_cr0);
2116 printf("guest CR3 = %llx\n", vmcb->cr3);
2117 #endif
2118 printf("%s: pt = %lx\n", __func__, pt);
2122 void svm_dump_host_regs(const char *from)
2124 struct vcpu *v = current;
2125 unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
2126 unsigned long cr3, cr0;
2127 printf("Host registers at %s\n", from);
2129 __asm__ __volatile__ ("\tmov %%cr0,%0\n"
2130 "\tmov %%cr3,%1\n"
2131 : "=r" (cr0), "=r"(cr3));
2132 printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
2135 #ifdef SVM_EXTRA_DEBUG
2136 static char *exit_reasons[] = {
2137 [VMEXIT_CR0_READ] = "CR0_READ",
2138 [VMEXIT_CR1_READ] = "CR1_READ",
2139 [VMEXIT_CR2_READ] = "CR2_READ",
2140 [VMEXIT_CR3_READ] = "CR3_READ",
2141 [VMEXIT_CR4_READ] = "CR4_READ",
2142 [VMEXIT_CR5_READ] = "CR5_READ",
2143 [VMEXIT_CR6_READ] = "CR6_READ",
2144 [VMEXIT_CR7_READ] = "CR7_READ",
2145 [VMEXIT_CR8_READ] = "CR8_READ",
2146 [VMEXIT_CR9_READ] = "CR9_READ",
2147 [VMEXIT_CR10_READ] = "CR10_READ",
2148 [VMEXIT_CR11_READ] = "CR11_READ",
2149 [VMEXIT_CR12_READ] = "CR12_READ",
2150 [VMEXIT_CR13_READ] = "CR13_READ",
2151 [VMEXIT_CR14_READ] = "CR14_READ",
2152 [VMEXIT_CR15_READ] = "CR15_READ",
2153 [VMEXIT_CR0_WRITE] = "CR0_WRITE",
2154 [VMEXIT_CR1_WRITE] = "CR1_WRITE",
2155 [VMEXIT_CR2_WRITE] = "CR2_WRITE",
2156 [VMEXIT_CR3_WRITE] = "CR3_WRITE",
2157 [VMEXIT_CR4_WRITE] = "CR4_WRITE",
2158 [VMEXIT_CR5_WRITE] = "CR5_WRITE",
2159 [VMEXIT_CR6_WRITE] = "CR6_WRITE",
2160 [VMEXIT_CR7_WRITE] = "CR7_WRITE",
2161 [VMEXIT_CR8_WRITE] = "CR8_WRITE",
2162 [VMEXIT_CR9_WRITE] = "CR9_WRITE",
2163 [VMEXIT_CR10_WRITE] = "CR10_WRITE",
2164 [VMEXIT_CR11_WRITE] = "CR11_WRITE",
2165 [VMEXIT_CR12_WRITE] = "CR12_WRITE",
2166 [VMEXIT_CR13_WRITE] = "CR13_WRITE",
2167 [VMEXIT_CR14_WRITE] = "CR14_WRITE",
2168 [VMEXIT_CR15_WRITE] = "CR15_WRITE",
2169 [VMEXIT_DR0_READ] = "DR0_READ",
2170 [VMEXIT_DR1_READ] = "DR1_READ",
2171 [VMEXIT_DR2_READ] = "DR2_READ",
2172 [VMEXIT_DR3_READ] = "DR3_READ",
2173 [VMEXIT_DR4_READ] = "DR4_READ",
2174 [VMEXIT_DR5_READ] = "DR5_READ",
2175 [VMEXIT_DR6_READ] = "DR6_READ",
2176 [VMEXIT_DR7_READ] = "DR7_READ",
2177 [VMEXIT_DR8_READ] = "DR8_READ",
2178 [VMEXIT_DR9_READ] = "DR9_READ",
2179 [VMEXIT_DR10_READ] = "DR10_READ",
2180 [VMEXIT_DR11_READ] = "DR11_READ",
2181 [VMEXIT_DR12_READ] = "DR12_READ",
2182 [VMEXIT_DR13_READ] = "DR13_READ",
2183 [VMEXIT_DR14_READ] = "DR14_READ",
2184 [VMEXIT_DR15_READ] = "DR15_READ",
2185 [VMEXIT_DR0_WRITE] = "DR0_WRITE",
2186 [VMEXIT_DR1_WRITE] = "DR1_WRITE",
2187 [VMEXIT_DR2_WRITE] = "DR2_WRITE",
2188 [VMEXIT_DR3_WRITE] = "DR3_WRITE",
2189 [VMEXIT_DR4_WRITE] = "DR4_WRITE",
2190 [VMEXIT_DR5_WRITE] = "DR5_WRITE",
2191 [VMEXIT_DR6_WRITE] = "DR6_WRITE",
2192 [VMEXIT_DR7_WRITE] = "DR7_WRITE",
2193 [VMEXIT_DR8_WRITE] = "DR8_WRITE",
2194 [VMEXIT_DR9_WRITE] = "DR9_WRITE",
2195 [VMEXIT_DR10_WRITE] = "DR10_WRITE",
2196 [VMEXIT_DR11_WRITE] = "DR11_WRITE",
2197 [VMEXIT_DR12_WRITE] = "DR12_WRITE",
2198 [VMEXIT_DR13_WRITE] = "DR13_WRITE",
2199 [VMEXIT_DR14_WRITE] = "DR14_WRITE",
2200 [VMEXIT_DR15_WRITE] = "DR15_WRITE",
2201 [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
2202 [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
2203 [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
2204 [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
2205 [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
2206 [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
2207 [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
2208 [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
2209 [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
2210 [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
2211 [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
2212 [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
2213 [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
2214 [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
2215 [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
2216 [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
2217 [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
2218 [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
2219 [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
2220 [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
2221 [VMEXIT_INTR] = "INTR",
2222 [VMEXIT_NMI] = "NMI",
2223 [VMEXIT_SMI] = "SMI",
2224 [VMEXIT_INIT] = "INIT",
2225 [VMEXIT_VINTR] = "VINTR",
2226 [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
2227 [VMEXIT_IDTR_READ] = "IDTR_READ",
2228 [VMEXIT_GDTR_READ] = "GDTR_READ",
2229 [VMEXIT_LDTR_READ] = "LDTR_READ",
2230 [VMEXIT_TR_READ] = "TR_READ",
2231 [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
2232 [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
2233 [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
2234 [VMEXIT_TR_WRITE] = "TR_WRITE",
2235 [VMEXIT_RDTSC] = "RDTSC",
2236 [VMEXIT_RDPMC] = "RDPMC",
2237 [VMEXIT_PUSHF] = "PUSHF",
2238 [VMEXIT_POPF] = "POPF",
2239 [VMEXIT_CPUID] = "CPUID",
2240 [VMEXIT_RSM] = "RSM",
2241 [VMEXIT_IRET] = "IRET",
2242 [VMEXIT_SWINT] = "SWINT",
2243 [VMEXIT_INVD] = "INVD",
2244 [VMEXIT_PAUSE] = "PAUSE",
2245 [VMEXIT_HLT] = "HLT",
2246 [VMEXIT_INVLPG] = "INVLPG",
2247 [VMEXIT_INVLPGA] = "INVLPGA",
2248 [VMEXIT_IOIO] = "IOIO",
2249 [VMEXIT_MSR] = "MSR",
2250 [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
2251 [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
2252 [VMEXIT_SHUTDOWN] = "SHUTDOWN",
2253 [VMEXIT_VMRUN] = "VMRUN",
2254 [VMEXIT_VMMCALL] = "VMMCALL",
2255 [VMEXIT_VMLOAD] = "VMLOAD",
2256 [VMEXIT_VMSAVE] = "VMSAVE",
2257 [VMEXIT_STGI] = "STGI",
2258 [VMEXIT_CLGI] = "CLGI",
2259 [VMEXIT_SKINIT] = "SKINIT",
2260 [VMEXIT_RDTSCP] = "RDTSCP",
2261 [VMEXIT_ICEBP] = "ICEBP",
2262 [VMEXIT_NPF] = "NPF"
2263 };
2264 #endif /* SVM_EXTRA_DEBUG */
2266 #ifdef SVM_WALK_GUEST_PAGES
2267 void walk_shadow_and_guest_pt(unsigned long gva)
2269 l2_pgentry_t gpde;
2270 l2_pgentry_t spde;
2271 l1_pgentry_t gpte;
2272 l1_pgentry_t spte;
2273 struct vcpu *v = current;
2274 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2275 unsigned long gpa;
2277 gpa = gva_to_gpa( gva );
2278 printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
2279 if( !svm_paging_enabled(v) || mmio_space(gpa) )
2280 return;
2282 /* let's dump the guest and shadow page info */
2284 __guest_get_l2e(v, gva, &gpde);
2285 printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
2286 __shadow_get_l2e( v, gva, &spde );
2287 printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
2289 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
2290 return;
2292 spte = l1e_empty();
2294 // This is actually overkill - we only need to make sure the hl2 is in-sync.
2295 shadow_sync_va(v, gva);
2297 gpte.l1 = 0;
2298 __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
2299 printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
2300 __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
2301 printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
2303 #endif /* SVM_WALK_GUEST_PAGES */
2305 asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
2307 unsigned int exit_reason;
2308 unsigned long eip;
2309 struct vcpu *v = current;
2310 int error;
2311 int do_debug = 0;
2312 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2314 ASSERT(vmcb);
2316 exit_reason = vmcb->exitcode;
2317 save_svm_cpu_user_regs(v, &regs);
2318 v->arch.hvm_svm.injecting_event = 0;
2320 vmcb->tlb_control = 1;
2322 #ifdef SVM_EXTRA_DEBUG
2324 #if defined(__i386__)
2325 #define rip eip
2326 #endif
2328 static unsigned long intercepts_counter = 0;
2330 if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
2332 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2334 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2335 intercepts_counter,
2336 exit_reasons[exit_reason], exit_reason, regs.cs,
2337 (unsigned long long) regs.rip,
2338 (unsigned long long) vmcb->exitinfo1,
2339 (unsigned long long) vmcb->exitinfo2,
2340 (unsigned long long) vmcb->exitintinfo.bytes);
2343 else if (svm_dbg_on
2344 && exit_reason != VMEXIT_IOIO
2345 && exit_reason != VMEXIT_INTR)
2348 if (exit_reasons[exit_reason])
2350 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2351 intercepts_counter,
2352 exit_reasons[exit_reason], exit_reason, regs.cs,
2353 (unsigned long long) regs.rip,
2354 (unsigned long long) vmcb->exitinfo1,
2355 (unsigned long long) vmcb->exitinfo2,
2356 (unsigned long long) vmcb->exitintinfo.bytes);
2358 else
2360 printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
2361 intercepts_counter, exit_reason, exit_reason, regs.cs,
2362 (unsigned long long) regs.rip,
2363 (unsigned long long) vmcb->exitinfo1,
2364 (unsigned long long) vmcb->exitinfo2,
2365 (unsigned long long) vmcb->exitintinfo.bytes);
2369 #ifdef SVM_WALK_GUEST_PAGES
2370 if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
2372 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
2373 walk_shadow_and_guest_pt( vmcb->exitinfo2 );
2375 #endif
2377 intercepts_counter++;
2379 #if 0
2380 if (svm_dbg_on)
2381 do_debug = svm_do_debugout(exit_reason);
2382 #endif
2384 if (do_debug)
2386 printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
2387 "shadow_table = 0x%08x\n",
2388 __func__,
2389 (int) v->arch.guest_table.pfn,
2390 (int) v->arch.monitor_table.pfn,
2391 (int) v->arch.shadow_table.pfn);
2393 svm_dump_vmcb(__func__, vmcb);
2394 svm_dump_regs(__func__, &regs);
2395 svm_dump_inst(svm_rip2pointer(vmcb));
2398 #if defined(__i386__)
2399 #undef rip
2400 #endif
2403 #endif /* SVM_EXTRA_DEBUG */
2405 if (exit_reason == -1)
2407 printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
2408 __func__);
2409 BUG();
2410 domain_crash_synchronous();
2413 perfc_incra(vmexits, exit_reason);
2414 eip = vmcb->rip;
2416 #ifdef SVM_EXTRA_DEBUG
2417 if (do_debug)
2419 printk("eip = %lx, exit_reason = %d (0x%x)\n",
2420 eip, exit_reason, exit_reason);
2422 #endif /* SVM_EXTRA_DEBUG */
2424 TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
2426 switch (exit_reason)
2428 case VMEXIT_EXCEPTION_DB:
2430 #ifdef XEN_DEBUGGER
2431 svm_debug_save_cpu_user_regs(&regs);
2432 pdb_handle_exception(1, &regs, 1);
2433 svm_debug_restore_cpu_user_regs(&regs);
2434 #else
2435 svm_store_cpu_user_regs(&regs, v);
2436 domain_pause_for_debugger();
2437 do_sched_op(SCHEDOP_yield, 0);
2438 #endif
2440 break;
2442 case VMEXIT_NMI:
2443 do_nmi(&regs, 0);
2444 break;
2446 #ifdef XEN_DEBUGGER
2447 case VMEXIT_EXCEPTION_BP:
2448 svm_debug_save_cpu_user_regs(&regs);
2449 pdb_handle_exception(3, &regs, 1);
2450 svm_debug_restore_cpu_user_regs(&regs);
2451 break;
2452 #endif
2454 case VMEXIT_EXCEPTION_NM:
2455 svm_do_no_device_fault(vmcb);
2456 break;
2458 case VMEXIT_EXCEPTION_GP:
2459 /* This should probably not be trapped in the future */
2460 regs.error_code = vmcb->exitinfo1;
2461 v->arch.hvm_svm.injecting_event = 1;
2462 svm_do_general_protection_fault(v, &regs);
2463 break;
2465 case VMEXIT_EXCEPTION_PF:
2467 unsigned long va;
2468 va = vmcb->exitinfo2;
2469 regs.error_code = vmcb->exitinfo1;
2470 HVM_DBG_LOG(DBG_LEVEL_VMMU,
2471 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
2472 (unsigned long)regs.eax, (unsigned long)regs.ebx,
2473 (unsigned long)regs.ecx, (unsigned long)regs.edx,
2474 (unsigned long)regs.esi, (unsigned long)regs.edi);
2476 v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
2478 //printk("PF1\n");
2479 if (!(error = svm_do_page_fault(va, &regs)))
2481 v->arch.hvm_svm.injecting_event = 1;
2482 /* Inject #PG using Interruption-Information Fields */
2483 vmcb->eventinj.bytes = 0;
2484 vmcb->eventinj.fields.v = 1;
2485 vmcb->eventinj.fields.ev = 1;
2486 vmcb->eventinj.fields.errorcode = regs.error_code;
2487 vmcb->eventinj.fields.type = EVENTTYPE_EXCEPTION;
2488 vmcb->eventinj.fields.vector = TRAP_page_fault;
2489 v->arch.hvm_svm.cpu_cr2 = va;
2490 vmcb->cr2 = va;
2491 TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
2492 VMEXIT_EXCEPTION_PF, va);
2494 break;
2497 case VMEXIT_EXCEPTION_DF:
2498 printk("Guest double fault");
2499 BUG();
2500 break;
2502 case VMEXIT_INTR:
2503 svm_stts(v);
2504 raise_softirq(SCHEDULE_SOFTIRQ);
2505 break;
2507 case VMEXIT_GDTR_WRITE:
2508 printk("WRITE to GDTR\n");
2509 break;
2511 case VMEXIT_TASK_SWITCH:
2512 __hvm_bug(&regs);
2513 break;
2515 case VMEXIT_CPUID:
2516 svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
2517 break;
2519 case VMEXIT_HLT:
2520 svm_vmexit_do_hlt(vmcb);
2521 break;
2523 case VMEXIT_INVLPG:
2524 svm_handle_invlpg(0, &regs);
2525 break;
2527 case VMEXIT_INVLPGA:
2528 svm_handle_invlpg(1, &regs);
2529 break;
2531 case VMEXIT_VMMCALL:
2532 svm_do_vmmcall(v, &regs);
2533 break;
2535 case VMEXIT_CR0_READ:
2536 svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
2537 break;
2539 case VMEXIT_CR2_READ:
2540 svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
2541 break;
2543 case VMEXIT_CR3_READ:
2544 svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
2545 break;
2547 case VMEXIT_CR4_READ:
2548 svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
2549 break;
2551 case VMEXIT_CR8_READ:
2552 svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
2553 break;
2555 case VMEXIT_CR0_WRITE:
2556 svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
2557 break;
2559 case VMEXIT_CR2_WRITE:
2560 svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
2561 break;
2563 case VMEXIT_CR3_WRITE:
2564 svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
2565 break;
2567 case VMEXIT_CR4_WRITE:
2568 svm_cr_access(v, 4, TYPE_MOV_TO_CR, &regs);
2569 break;
2571 case VMEXIT_CR8_WRITE:
2572 svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
2573 break;
2575 case VMEXIT_DR0_READ:
2576 svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
2577 break;
2579 case VMEXIT_DR1_READ:
2580 svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
2581 break;
2583 case VMEXIT_DR2_READ:
2584 svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
2585 break;
2587 case VMEXIT_DR3_READ:
2588 svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
2589 break;
2591 case VMEXIT_DR6_READ:
2592 svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
2593 break;
2595 case VMEXIT_DR7_READ:
2596 svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
2597 break;
2599 case VMEXIT_DR0_WRITE:
2600 svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
2601 break;
2603 case VMEXIT_DR1_WRITE:
2604 svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
2605 break;
2607 case VMEXIT_DR2_WRITE:
2608 svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
2609 break;
2611 case VMEXIT_DR3_WRITE:
2612 svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
2613 break;
2615 case VMEXIT_DR6_WRITE:
2616 svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
2617 break;
2619 case VMEXIT_DR7_WRITE:
2620 svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
2621 break;
2623 case VMEXIT_IOIO:
2624 svm_io_instruction(v, &regs);
2625 break;
2627 case VMEXIT_MSR:
2628 svm_do_msr_access(v, &regs);
2629 break;
2631 case VMEXIT_SHUTDOWN:
2632 printk("Guest shutdown exit\n");
2633 domain_crash_synchronous();
2634 break;
2636 default:
2637 printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, "
2638 "exitinfo2 = %llx\n", exit_reason,
2639 (unsigned long long)vmcb->exitinfo1,
2640 (unsigned long long)vmcb->exitinfo2);
2641 __hvm_bug(&regs); /* should not happen */
2642 break;
2645 #ifdef SVM_EXTRA_DEBUG
2646 if (do_debug)
2648 printk("%s: Done switch on vmexit_code\n", __func__);
2649 svm_dump_regs(__func__, &regs);
2652 if (do_debug)
2654 printk("vmexit_handler():- guest_table = 0x%08x, "
2655 "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
2656 (int)v->arch.guest_table.pfn,
2657 (int)v->arch.monitor_table.pfn,
2658 (int)v->arch.shadow_table.pfn);
2659 printk("svm_vmexit_handler: Returning\n");
2661 #endif
2663 return;
2666 asmlinkage void svm_load_cr2(void)
2668 struct vcpu *v = current;
2670 local_irq_disable();
2671 #ifdef __i386__
2672 asm volatile("movl %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2673 #else
2674 asm volatile("movq %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
2675 #endif
2678 asmlinkage void svm_asid(void)
2680 struct vcpu *v = current;
2681 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
2682 int core = smp_processor_id();
2683 /*
2684 * if need to assign new asid or if switching cores,
2685 * then retire asid for old core, and assign new for new core.
2686 */
2687 if( svm_dbg_on)
2688 printk("old core %d new core %d\n",(int)v->arch.hvm_svm.core,(int)core);
2690 if( test_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags) ||
2691 (v->arch.hvm_svm.core != core)) {
2692 if(!asidpool_assign_next(vmcb, 1,
2693 v->arch.hvm_svm.core, core)) {
2694 BUG();
2697 clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
2700 /*
2701 * Local variables:
2702 * mode: C
2703 * c-set-style: "BSD"
2704 * c-basic-offset: 4
2705 * tab-width: 4
2706 * indent-tabs-mode: nil
2707 * End:
2708 */