ia64/xen-unstable

view xen/arch/x86/hvm/svm/svm.c @ 17489:491074885dcb

svm: Do not hide 3DNow! CPU capabilities from SVM guests.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Apr 21 12:23:55 2008 +0100 (2008-04-21)
parents cd5dc735bdf3
children 18727843db60
line source
1 /*
2 * svm.c: handling SVM architecture-related VM exits
3 * Copyright (c) 2004, Intel Corporation.
4 * Copyright (c) 2005-2007, Advanced Micro Devices, Inc.
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 */
20 #include <xen/config.h>
21 #include <xen/init.h>
22 #include <xen/lib.h>
23 #include <xen/trace.h>
24 #include <xen/sched.h>
25 #include <xen/irq.h>
26 #include <xen/softirq.h>
27 #include <xen/hypercall.h>
28 #include <xen/domain_page.h>
29 #include <asm/current.h>
30 #include <asm/io.h>
31 #include <asm/paging.h>
32 #include <asm/p2m.h>
33 #include <asm/regs.h>
34 #include <asm/cpufeature.h>
35 #include <asm/processor.h>
36 #include <asm/types.h>
37 #include <asm/debugreg.h>
38 #include <asm/msr.h>
39 #include <asm/spinlock.h>
40 #include <asm/hvm/hvm.h>
41 #include <asm/hvm/support.h>
42 #include <asm/hvm/io.h>
43 #include <asm/hvm/svm/asid.h>
44 #include <asm/hvm/svm/svm.h>
45 #include <asm/hvm/svm/vmcb.h>
46 #include <asm/hvm/svm/emulate.h>
47 #include <asm/hvm/svm/intr.h>
48 #include <asm/x86_emulate.h>
49 #include <public/sched.h>
50 #include <asm/hvm/vpt.h>
51 #include <asm/hvm/trace.h>
52 #include <asm/hap.h>
54 u32 svm_feature_flags;
56 #define set_segment_register(name, value) \
57 asm volatile ( "movw %%ax ,%%" STR(name) "" : : "a" (value) )
59 enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
61 asmlinkage void do_IRQ(struct cpu_user_regs *);
63 static void svm_update_guest_cr(struct vcpu *v, unsigned int cr);
64 static void svm_update_guest_efer(struct vcpu *v);
65 static void svm_inject_exception(
66 unsigned int trapnr, int errcode, unsigned long cr2);
67 static void svm_cpuid_intercept(
68 unsigned int *eax, unsigned int *ebx,
69 unsigned int *ecx, unsigned int *edx);
70 static void svm_wbinvd_intercept(void);
71 static void svm_fpu_dirty_intercept(void);
72 static int svm_msr_read_intercept(struct cpu_user_regs *regs);
73 static int svm_msr_write_intercept(struct cpu_user_regs *regs);
74 static void svm_invlpg_intercept(unsigned long vaddr);
76 /* va of hardware host save area */
77 static void *hsa[NR_CPUS] __read_mostly;
79 /* vmcb used for extended host state */
80 static void *root_vmcb[NR_CPUS] __read_mostly;
82 static void inline __update_guest_eip(
83 struct cpu_user_regs *regs, unsigned int inst_len)
84 {
85 struct vcpu *curr = current;
87 if ( unlikely((inst_len == 0) || (inst_len > 15)) )
88 {
89 gdprintk(XENLOG_ERR, "Bad instruction length %u\n", inst_len);
90 domain_crash(curr->domain);
91 return;
92 }
94 ASSERT(regs == guest_cpu_user_regs());
96 regs->eip += inst_len;
97 regs->eflags &= ~X86_EFLAGS_RF;
99 curr->arch.hvm_svm.vmcb->interrupt_shadow = 0;
101 if ( regs->eflags & X86_EFLAGS_TF )
102 svm_inject_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE, 0);
103 }
105 static void svm_cpu_down(void)
106 {
107 write_efer(read_efer() & ~EFER_SVME);
108 }
110 static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
111 {
112 u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
113 u32 ecx = regs->ecx;
115 HVM_DBG_LOG(DBG_LEVEL_0, "msr %x msr_content %"PRIx64,
116 ecx, msr_content);
118 switch ( ecx )
119 {
120 case MSR_EFER:
121 if ( hvm_set_efer(msr_content) )
122 return HNDL_exception_raised;
123 break;
125 case MSR_IA32_MC4_MISC: /* Threshold register */
126 case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:
127 /*
128 * MCA/MCE: Threshold register is reported to be locked, so we ignore
129 * all write accesses. This behaviour matches real HW, so guests should
130 * have no problem with this.
131 */
132 break;
134 default:
135 return HNDL_unhandled;
136 }
138 return HNDL_done;
139 }
141 static void svm_save_dr(struct vcpu *v)
142 {
143 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
145 if ( !v->arch.hvm_vcpu.flag_dr_dirty )
146 return;
148 /* Clear the DR dirty flag and re-enable intercepts for DR accesses. */
149 v->arch.hvm_vcpu.flag_dr_dirty = 0;
150 v->arch.hvm_svm.vmcb->dr_intercepts = ~0u;
152 v->arch.guest_context.debugreg[0] = read_debugreg(0);
153 v->arch.guest_context.debugreg[1] = read_debugreg(1);
154 v->arch.guest_context.debugreg[2] = read_debugreg(2);
155 v->arch.guest_context.debugreg[3] = read_debugreg(3);
156 v->arch.guest_context.debugreg[6] = vmcb->dr6;
157 v->arch.guest_context.debugreg[7] = vmcb->dr7;
158 }
160 static void __restore_debug_registers(struct vcpu *v)
161 {
162 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
164 if ( v->arch.hvm_vcpu.flag_dr_dirty )
165 return;
167 v->arch.hvm_vcpu.flag_dr_dirty = 1;
168 vmcb->dr_intercepts = 0;
170 write_debugreg(0, v->arch.guest_context.debugreg[0]);
171 write_debugreg(1, v->arch.guest_context.debugreg[1]);
172 write_debugreg(2, v->arch.guest_context.debugreg[2]);
173 write_debugreg(3, v->arch.guest_context.debugreg[3]);
174 vmcb->dr6 = v->arch.guest_context.debugreg[6];
175 vmcb->dr7 = v->arch.guest_context.debugreg[7];
176 }
178 /*
179 * DR7 is saved and restored on every vmexit. Other debug registers only
180 * need to be restored if their value is going to affect execution -- i.e.,
181 * if one of the breakpoints is enabled. So mask out all bits that don't
182 * enable some breakpoint functionality.
183 */
184 static void svm_restore_dr(struct vcpu *v)
185 {
186 if ( unlikely(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) )
187 __restore_debug_registers(v);
188 }
190 static int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
191 {
192 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
194 c->cr0 = v->arch.hvm_vcpu.guest_cr[0];
195 c->cr2 = v->arch.hvm_vcpu.guest_cr[2];
196 c->cr3 = v->arch.hvm_vcpu.guest_cr[3];
197 c->cr4 = v->arch.hvm_vcpu.guest_cr[4];
199 c->sysenter_cs = vmcb->sysenter_cs;
200 c->sysenter_esp = vmcb->sysenter_esp;
201 c->sysenter_eip = vmcb->sysenter_eip;
203 c->pending_event = 0;
204 c->error_code = 0;
205 if ( vmcb->eventinj.fields.v &&
206 hvm_event_needs_reinjection(vmcb->eventinj.fields.type,
207 vmcb->eventinj.fields.vector) )
208 {
209 c->pending_event = (uint32_t)vmcb->eventinj.bytes;
210 c->error_code = vmcb->eventinj.fields.errorcode;
211 }
213 return 1;
214 }
216 static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
217 {
218 unsigned long mfn = 0;
219 p2m_type_t p2mt;
220 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
222 if ( c->pending_valid &&
223 ((c->pending_type == 1) || (c->pending_type > 6) ||
224 (c->pending_reserved != 0)) )
225 {
226 gdprintk(XENLOG_ERR, "Invalid pending event 0x%"PRIx32".\n",
227 c->pending_event);
228 return -EINVAL;
229 }
231 if ( !paging_mode_hap(v->domain) )
232 {
233 if ( c->cr0 & X86_CR0_PG )
234 {
235 mfn = mfn_x(gfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT, &p2mt));
236 if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
237 {
238 gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",
239 c->cr3);
240 return -EINVAL;
241 }
242 }
244 if ( v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG )
245 put_page(pagetable_get_page(v->arch.guest_table));
247 v->arch.guest_table = pagetable_from_pfn(mfn);
248 }
250 v->arch.hvm_vcpu.guest_cr[0] = c->cr0 | X86_CR0_ET;
251 v->arch.hvm_vcpu.guest_cr[2] = c->cr2;
252 v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
253 v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
254 svm_update_guest_cr(v, 0);
255 svm_update_guest_cr(v, 2);
256 svm_update_guest_cr(v, 4);
258 vmcb->sysenter_cs = c->sysenter_cs;
259 vmcb->sysenter_esp = c->sysenter_esp;
260 vmcb->sysenter_eip = c->sysenter_eip;
262 if ( paging_mode_hap(v->domain) )
263 {
264 vmcb->np_enable = 1;
265 vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
266 vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
267 }
269 if ( c->pending_valid )
270 {
271 gdprintk(XENLOG_INFO, "Re-injecting 0x%"PRIx32", 0x%"PRIx32"\n",
272 c->pending_event, c->error_code);
274 if ( hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
275 {
276 vmcb->eventinj.bytes = c->pending_event;
277 vmcb->eventinj.fields.errorcode = c->error_code;
278 }
279 }
281 paging_update_paging_modes(v);
283 return 0;
284 }
287 static void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
288 {
289 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
291 data->shadow_gs = vmcb->kerngsbase;
292 data->msr_lstar = vmcb->lstar;
293 data->msr_star = vmcb->star;
294 data->msr_cstar = vmcb->cstar;
295 data->msr_syscall_mask = vmcb->sfmask;
296 data->msr_efer = v->arch.hvm_vcpu.guest_efer;
297 data->msr_flags = -1ULL;
299 data->tsc = hvm_get_guest_time(v);
300 }
303 static void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
304 {
305 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
307 vmcb->kerngsbase = data->shadow_gs;
308 vmcb->lstar = data->msr_lstar;
309 vmcb->star = data->msr_star;
310 vmcb->cstar = data->msr_cstar;
311 vmcb->sfmask = data->msr_syscall_mask;
312 v->arch.hvm_vcpu.guest_efer = data->msr_efer;
313 svm_update_guest_efer(v);
315 hvm_set_guest_time(v, data->tsc);
316 }
318 static void svm_save_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
319 {
320 svm_save_cpu_state(v, ctxt);
321 svm_vmcb_save(v, ctxt);
322 }
324 static int svm_load_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
325 {
326 svm_load_cpu_state(v, ctxt);
327 if (svm_vmcb_restore(v, ctxt)) {
328 printk("svm_vmcb restore failed!\n");
329 domain_crash(v->domain);
330 return -EINVAL;
331 }
333 return 0;
334 }
336 static void svm_fpu_enter(struct vcpu *v)
337 {
338 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
340 setup_fpu(v);
341 vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
342 }
344 static void svm_fpu_leave(struct vcpu *v)
345 {
346 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
348 ASSERT(!v->fpu_dirtied);
349 ASSERT(read_cr0() & X86_CR0_TS);
351 /*
352 * If the guest does not have TS enabled then we must cause and handle an
353 * exception on first use of the FPU. If the guest *does* have TS enabled
354 * then this is not necessary: no FPU activity can occur until the guest
355 * clears CR0.TS, and we will initialise the FPU when that happens.
356 */
357 if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
358 {
359 v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device;
360 vmcb->cr0 |= X86_CR0_TS;
361 }
362 }
364 static unsigned int svm_get_interrupt_shadow(struct vcpu *v)
365 {
366 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
367 return (vmcb->interrupt_shadow ?
368 (HVM_INTR_SHADOW_MOV_SS|HVM_INTR_SHADOW_STI) : 0);
369 }
371 static void svm_set_interrupt_shadow(struct vcpu *v, unsigned int intr_shadow)
372 {
373 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
374 vmcb->interrupt_shadow =
375 !!(intr_shadow & (HVM_INTR_SHADOW_MOV_SS|HVM_INTR_SHADOW_STI));
376 }
378 static int svm_guest_x86_mode(struct vcpu *v)
379 {
380 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
382 if ( unlikely(!(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE)) )
383 return 0;
384 if ( unlikely(guest_cpu_user_regs()->eflags & X86_EFLAGS_VM) )
385 return 1;
386 if ( hvm_long_mode_enabled(v) && likely(vmcb->cs.attr.fields.l) )
387 return 8;
388 return (likely(vmcb->cs.attr.fields.db) ? 4 : 2);
389 }
391 static void svm_update_host_cr3(struct vcpu *v)
392 {
393 /* SVM doesn't have a HOST_CR3 equivalent to update. */
394 }
396 static void svm_update_guest_cr(struct vcpu *v, unsigned int cr)
397 {
398 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
400 switch ( cr )
401 {
402 case 0: {
403 unsigned long hw_cr0_mask = 0;
405 if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
406 {
407 if ( v != current )
408 hw_cr0_mask |= X86_CR0_TS;
409 else if ( vmcb->cr0 & X86_CR0_TS )
410 svm_fpu_enter(v);
411 }
413 vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;
414 if ( !paging_mode_hap(v->domain) )
415 vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP;
416 break;
417 }
418 case 2:
419 vmcb->cr2 = v->arch.hvm_vcpu.guest_cr[2];
420 break;
421 case 3:
422 vmcb->cr3 = v->arch.hvm_vcpu.hw_cr[3];
423 svm_asid_inv_asid(v);
424 break;
425 case 4:
426 vmcb->cr4 = HVM_CR4_HOST_MASK;
427 if ( paging_mode_hap(v->domain) )
428 vmcb->cr4 &= ~X86_CR4_PAE;
429 vmcb->cr4 |= v->arch.hvm_vcpu.guest_cr[4];
430 break;
431 default:
432 BUG();
433 }
434 }
436 static void svm_update_guest_efer(struct vcpu *v)
437 {
438 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
440 vmcb->efer = (v->arch.hvm_vcpu.guest_efer | EFER_SVME) & ~EFER_LME;
441 if ( vmcb->efer & EFER_LMA )
442 vmcb->efer |= EFER_LME;
443 }
445 static void svm_flush_guest_tlbs(void)
446 {
447 /* Roll over the CPU's ASID generation, so it gets a clean TLB when we
448 * next VMRUN. (If ASIDs are disabled, the whole TLB is flushed on
449 * VMRUN anyway). */
450 svm_asid_inc_generation();
451 }
453 static void svm_sync_vmcb(struct vcpu *v)
454 {
455 struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
457 if ( arch_svm->vmcb_in_sync )
458 return;
460 arch_svm->vmcb_in_sync = 1;
462 svm_vmsave(arch_svm->vmcb);
463 }
465 static void svm_get_segment_register(struct vcpu *v, enum x86_segment seg,
466 struct segment_register *reg)
467 {
468 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
470 ASSERT((v == current) || !vcpu_runnable(v));
472 switch ( seg )
473 {
474 case x86_seg_cs:
475 memcpy(reg, &vmcb->cs, sizeof(*reg));
476 break;
477 case x86_seg_ds:
478 memcpy(reg, &vmcb->ds, sizeof(*reg));
479 break;
480 case x86_seg_es:
481 memcpy(reg, &vmcb->es, sizeof(*reg));
482 break;
483 case x86_seg_fs:
484 svm_sync_vmcb(v);
485 memcpy(reg, &vmcb->fs, sizeof(*reg));
486 break;
487 case x86_seg_gs:
488 svm_sync_vmcb(v);
489 memcpy(reg, &vmcb->gs, sizeof(*reg));
490 break;
491 case x86_seg_ss:
492 memcpy(reg, &vmcb->ss, sizeof(*reg));
493 reg->attr.fields.dpl = vmcb->cpl;
494 break;
495 case x86_seg_tr:
496 svm_sync_vmcb(v);
497 memcpy(reg, &vmcb->tr, sizeof(*reg));
498 break;
499 case x86_seg_gdtr:
500 memcpy(reg, &vmcb->gdtr, sizeof(*reg));
501 break;
502 case x86_seg_idtr:
503 memcpy(reg, &vmcb->idtr, sizeof(*reg));
504 break;
505 case x86_seg_ldtr:
506 svm_sync_vmcb(v);
507 memcpy(reg, &vmcb->ldtr, sizeof(*reg));
508 break;
509 default:
510 BUG();
511 }
512 }
514 static void svm_set_segment_register(struct vcpu *v, enum x86_segment seg,
515 struct segment_register *reg)
516 {
517 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
518 int sync = 0;
520 ASSERT((v == current) || !vcpu_runnable(v));
522 switch ( seg )
523 {
524 case x86_seg_fs:
525 case x86_seg_gs:
526 case x86_seg_tr:
527 case x86_seg_ldtr:
528 sync = (v == current);
529 break;
530 default:
531 break;
532 }
534 if ( sync )
535 svm_sync_vmcb(v);
537 switch ( seg )
538 {
539 case x86_seg_cs:
540 memcpy(&vmcb->cs, reg, sizeof(*reg));
541 break;
542 case x86_seg_ds:
543 memcpy(&vmcb->ds, reg, sizeof(*reg));
544 break;
545 case x86_seg_es:
546 memcpy(&vmcb->es, reg, sizeof(*reg));
547 break;
548 case x86_seg_fs:
549 memcpy(&vmcb->fs, reg, sizeof(*reg));
550 break;
551 case x86_seg_gs:
552 memcpy(&vmcb->gs, reg, sizeof(*reg));
553 break;
554 case x86_seg_ss:
555 memcpy(&vmcb->ss, reg, sizeof(*reg));
556 vmcb->cpl = vmcb->ss.attr.fields.dpl;
557 break;
558 case x86_seg_tr:
559 memcpy(&vmcb->tr, reg, sizeof(*reg));
560 break;
561 case x86_seg_gdtr:
562 memcpy(&vmcb->gdtr, reg, sizeof(*reg));
563 break;
564 case x86_seg_idtr:
565 memcpy(&vmcb->idtr, reg, sizeof(*reg));
566 break;
567 case x86_seg_ldtr:
568 memcpy(&vmcb->ldtr, reg, sizeof(*reg));
569 break;
570 default:
571 BUG();
572 }
574 if ( sync )
575 svm_vmload(vmcb);
576 }
578 static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
579 {
580 v->arch.hvm_svm.vmcb->tsc_offset = offset;
581 }
583 static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
584 {
585 char *p;
586 int i;
588 for ( i = 0; i < (PAGE_SIZE / 32); i++ )
589 {
590 p = (char *)(hypercall_page + (i * 32));
591 *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */
592 *(u32 *)(p + 1) = i;
593 *(u8 *)(p + 5) = 0x0f; /* vmmcall */
594 *(u8 *)(p + 6) = 0x01;
595 *(u8 *)(p + 7) = 0xd9;
596 *(u8 *)(p + 8) = 0xc3; /* ret */
597 }
599 /* Don't support HYPERVISOR_iret at the moment */
600 *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
601 }
603 static void svm_ctxt_switch_from(struct vcpu *v)
604 {
605 int cpu = smp_processor_id();
607 svm_fpu_leave(v);
609 svm_save_dr(v);
611 svm_sync_vmcb(v);
612 svm_vmload(root_vmcb[cpu]);
614 #ifdef __x86_64__
615 /* Resume use of ISTs now that the host TR is reinstated. */
616 idt_tables[cpu][TRAP_double_fault].a |= IST_DF << 32;
617 idt_tables[cpu][TRAP_nmi].a |= IST_NMI << 32;
618 idt_tables[cpu][TRAP_machine_check].a |= IST_MCE << 32;
619 #endif
620 }
622 static void svm_ctxt_switch_to(struct vcpu *v)
623 {
624 int cpu = smp_processor_id();
626 #ifdef __x86_64__
627 /*
628 * This is required, because VMRUN does consistency check
629 * and some of the DOM0 selectors are pointing to
630 * invalid GDT locations, and cause AMD processors
631 * to shutdown.
632 */
633 set_segment_register(ds, 0);
634 set_segment_register(es, 0);
635 set_segment_register(ss, 0);
637 /*
638 * Cannot use ISTs for NMI/#MC/#DF while we are running with the guest TR.
639 * But this doesn't matter: the IST is only req'd to handle SYSCALL/SYSRET.
640 */
641 idt_tables[cpu][TRAP_double_fault].a &= ~(7UL << 32);
642 idt_tables[cpu][TRAP_nmi].a &= ~(7UL << 32);
643 idt_tables[cpu][TRAP_machine_check].a &= ~(7UL << 32);
644 #endif
646 svm_restore_dr(v);
648 svm_vmsave(root_vmcb[cpu]);
649 svm_vmload(v->arch.hvm_svm.vmcb);
650 }
652 static void svm_do_resume(struct vcpu *v)
653 {
654 bool_t debug_state = v->domain->debugger_attached;
656 if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) )
657 {
658 uint32_t mask = (1U << TRAP_debug) | (1U << TRAP_int3);
659 v->arch.hvm_vcpu.debug_state_latch = debug_state;
660 if ( debug_state )
661 v->arch.hvm_svm.vmcb->exception_intercepts |= mask;
662 else
663 v->arch.hvm_svm.vmcb->exception_intercepts &= ~mask;
664 }
666 if ( v->arch.hvm_svm.launch_core != smp_processor_id() )
667 {
668 v->arch.hvm_svm.launch_core = smp_processor_id();
669 hvm_migrate_timers(v);
671 /* Migrating to another ASID domain. Request a new ASID. */
672 svm_asid_init_vcpu(v);
673 }
675 /* Reflect the vlapic's TPR in the hardware vtpr */
676 v->arch.hvm_svm.vmcb->vintr.fields.tpr =
677 (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4;
679 hvm_do_resume(v);
680 reset_stack_and_jump(svm_asm_do_resume);
681 }
683 static int svm_domain_initialise(struct domain *d)
684 {
685 return 0;
686 }
688 static void svm_domain_destroy(struct domain *d)
689 {
690 }
692 static int svm_vcpu_initialise(struct vcpu *v)
693 {
694 int rc;
696 v->arch.schedule_tail = svm_do_resume;
697 v->arch.ctxt_switch_from = svm_ctxt_switch_from;
698 v->arch.ctxt_switch_to = svm_ctxt_switch_to;
700 v->arch.hvm_svm.launch_core = -1;
702 if ( (rc = svm_create_vmcb(v)) != 0 )
703 {
704 dprintk(XENLOG_WARNING,
705 "Failed to create VMCB for vcpu %d: err=%d.\n",
706 v->vcpu_id, rc);
707 return rc;
708 }
710 return 0;
711 }
713 static void svm_vcpu_destroy(struct vcpu *v)
714 {
715 svm_destroy_vmcb(v);
716 }
718 static void svm_inject_exception(
719 unsigned int trapnr, int errcode, unsigned long cr2)
720 {
721 struct vcpu *curr = current;
722 struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
723 eventinj_t event = vmcb->eventinj;
725 if ( unlikely(event.fields.v) &&
726 (event.fields.type == X86_EVENTTYPE_HW_EXCEPTION) )
727 {
728 trapnr = hvm_combine_hw_exceptions(event.fields.vector, trapnr);
729 if ( trapnr == TRAP_double_fault )
730 errcode = 0;
731 }
733 event.bytes = 0;
734 event.fields.v = 1;
735 event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
736 event.fields.vector = trapnr;
737 event.fields.ev = (errcode != HVM_DELIVER_NO_ERROR_CODE);
738 event.fields.errorcode = errcode;
740 vmcb->eventinj = event;
742 if ( trapnr == TRAP_page_fault )
743 {
744 vmcb->cr2 = curr->arch.hvm_vcpu.guest_cr[2] = cr2;
745 HVMTRACE_2D(PF_INJECT, curr, curr->arch.hvm_vcpu.guest_cr[2], errcode);
746 }
747 else
748 {
749 HVMTRACE_2D(INJ_EXC, curr, trapnr, errcode);
750 }
752 if ( (trapnr == TRAP_debug) &&
753 (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) )
754 {
755 __restore_debug_registers(curr);
756 vmcb->dr6 |= 0x4000;
757 }
758 }
760 static int svm_event_pending(struct vcpu *v)
761 {
762 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
763 return vmcb->eventinj.fields.v;
764 }
766 static int svm_do_pmu_interrupt(struct cpu_user_regs *regs)
767 {
768 return 0;
769 }
771 static struct hvm_function_table svm_function_table = {
772 .name = "SVM",
773 .cpu_down = svm_cpu_down,
774 .domain_initialise = svm_domain_initialise,
775 .domain_destroy = svm_domain_destroy,
776 .vcpu_initialise = svm_vcpu_initialise,
777 .vcpu_destroy = svm_vcpu_destroy,
778 .save_cpu_ctxt = svm_save_vmcb_ctxt,
779 .load_cpu_ctxt = svm_load_vmcb_ctxt,
780 .get_interrupt_shadow = svm_get_interrupt_shadow,
781 .set_interrupt_shadow = svm_set_interrupt_shadow,
782 .guest_x86_mode = svm_guest_x86_mode,
783 .get_segment_register = svm_get_segment_register,
784 .set_segment_register = svm_set_segment_register,
785 .update_host_cr3 = svm_update_host_cr3,
786 .update_guest_cr = svm_update_guest_cr,
787 .update_guest_efer = svm_update_guest_efer,
788 .flush_guest_tlbs = svm_flush_guest_tlbs,
789 .set_tsc_offset = svm_set_tsc_offset,
790 .inject_exception = svm_inject_exception,
791 .init_hypercall_page = svm_init_hypercall_page,
792 .event_pending = svm_event_pending,
793 .do_pmu_interrupt = svm_do_pmu_interrupt,
794 .cpuid_intercept = svm_cpuid_intercept,
795 .wbinvd_intercept = svm_wbinvd_intercept,
796 .fpu_dirty_intercept = svm_fpu_dirty_intercept,
797 .msr_read_intercept = svm_msr_read_intercept,
798 .msr_write_intercept = svm_msr_write_intercept,
799 .invlpg_intercept = svm_invlpg_intercept
800 };
802 int start_svm(struct cpuinfo_x86 *c)
803 {
804 u32 eax, ecx, edx;
805 u32 phys_hsa_lo, phys_hsa_hi;
806 u64 phys_hsa;
807 int cpu = smp_processor_id();
809 /* Xen does not fill x86_capability words except 0. */
810 ecx = cpuid_ecx(0x80000001);
811 boot_cpu_data.x86_capability[5] = ecx;
813 if ( !(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)) )
814 return 0;
816 /* Check whether SVM feature is disabled in BIOS */
817 rdmsr(MSR_K8_VM_CR, eax, edx);
818 if ( eax & K8_VMCR_SVME_DISABLE )
819 {
820 printk("AMD SVM Extension is disabled in BIOS.\n");
821 return 0;
822 }
824 if ( ((hsa[cpu] = alloc_host_save_area()) == NULL) ||
825 ((root_vmcb[cpu] = alloc_vmcb()) == NULL) )
826 return 0;
828 write_efer(read_efer() | EFER_SVME);
830 /* Initialize the HSA for this core. */
831 phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
832 phys_hsa_lo = (u32) phys_hsa;
833 phys_hsa_hi = (u32) (phys_hsa >> 32);
834 wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
836 /* Initialize core's ASID handling. */
837 svm_asid_init(c);
839 if ( cpu != 0 )
840 return 1;
842 setup_vmcb_dump();
844 svm_feature_flags = ((cpuid_eax(0x80000000) >= 0x8000000A) ?
845 cpuid_edx(0x8000000A) : 0);
847 svm_function_table.hap_supported = cpu_has_svm_npt;
849 hvm_enable(&svm_function_table);
851 return 1;
852 }
854 static void svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
855 {
856 p2m_type_t p2mt;
857 mfn_t mfn;
858 unsigned long gfn = gpa >> PAGE_SHIFT;
860 /* If this GFN is emulated MMIO, pass the fault to the mmio handler */
861 mfn = gfn_to_mfn_current(gfn, &p2mt);
862 if ( p2mt == p2m_mmio_dm )
863 {
864 if ( !handle_mmio() )
865 hvm_inject_exception(TRAP_gp_fault, 0, 0);
866 return;
867 }
869 /* Log-dirty: mark the page dirty and let the guest write it again */
870 paging_mark_dirty(current->domain, mfn_x(mfn));
871 p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
872 }
874 static void svm_fpu_dirty_intercept(void)
875 {
876 struct vcpu *curr = current;
877 struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
879 svm_fpu_enter(curr);
881 if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
882 vmcb->cr0 &= ~X86_CR0_TS;
883 }
885 #define bitmaskof(idx) (1U << ((idx) & 31))
886 static void svm_cpuid_intercept(
887 unsigned int *eax, unsigned int *ebx,
888 unsigned int *ecx, unsigned int *edx)
889 {
890 unsigned int input = *eax;
891 struct vcpu *v = current;
893 hvm_cpuid(input, eax, ebx, ecx, edx);
895 switch ( input )
896 {
897 case 0x00000001:
898 /* Mask Intel-only features. */
899 *ecx &= ~(bitmaskof(X86_FEATURE_SSSE3) |
900 bitmaskof(X86_FEATURE_SSE4_1) |
901 bitmaskof(X86_FEATURE_SSE4_2));
902 break;
904 case 0x80000001:
905 /* Filter features which are shared with 0x00000001:EDX. */
906 if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
907 __clear_bit(X86_FEATURE_APIC & 31, edx);
908 #if CONFIG_PAGING_LEVELS >= 3
909 if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
910 #endif
911 __clear_bit(X86_FEATURE_PAE & 31, edx);
912 __clear_bit(X86_FEATURE_PSE36 & 31, edx);
914 /* We always support MTRR MSRs. */
915 *edx |= bitmaskof(X86_FEATURE_MTRR);
917 /* Filter all other features according to a whitelist. */
918 *ecx &= (bitmaskof(X86_FEATURE_LAHF_LM) |
919 bitmaskof(X86_FEATURE_ALTMOVCR) |
920 bitmaskof(X86_FEATURE_ABM) |
921 bitmaskof(X86_FEATURE_SSE4A) |
922 bitmaskof(X86_FEATURE_MISALIGNSSE) |
923 bitmaskof(X86_FEATURE_3DNOWPF));
924 *edx &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
925 bitmaskof(X86_FEATURE_NX) |
926 bitmaskof(X86_FEATURE_LM) |
927 bitmaskof(X86_FEATURE_SYSCALL) |
928 bitmaskof(X86_FEATURE_MP) |
929 bitmaskof(X86_FEATURE_MMXEXT) |
930 bitmaskof(X86_FEATURE_FFXSR) |
931 bitmaskof(X86_FEATURE_3DNOW) |
932 bitmaskof(X86_FEATURE_3DNOWEXT));
933 break;
935 case 0x80000007:
936 case 0x8000000A:
937 /* Mask out features of power management and SVM extension. */
938 *eax = *ebx = *ecx = *edx = 0;
939 break;
941 case 0x80000008:
942 /* Make sure Number of CPU core is 1 when HTT=0 */
943 *ecx &= 0xFFFFFF00;
944 break;
945 }
947 HVMTRACE_3D(CPUID, v, input,
948 ((uint64_t)*eax << 32) | *ebx, ((uint64_t)*ecx << 32) | *edx);
949 }
951 static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
952 {
953 unsigned int eax, ebx, ecx, edx, inst_len;
955 inst_len = __get_instruction_length(current, INSTR_CPUID, NULL);
956 if ( inst_len == 0 )
957 return;
959 eax = regs->eax;
960 ebx = regs->ebx;
961 ecx = regs->ecx;
962 edx = regs->edx;
964 svm_cpuid_intercept(&eax, &ebx, &ecx, &edx);
966 regs->eax = eax;
967 regs->ebx = ebx;
968 regs->ecx = ecx;
969 regs->edx = edx;
971 __update_guest_eip(regs, inst_len);
972 }
974 static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs)
975 {
976 HVMTRACE_0D(DR_WRITE, v);
977 __restore_debug_registers(v);
978 }
980 static int svm_msr_read_intercept(struct cpu_user_regs *regs)
981 {
982 u64 msr_content = 0;
983 u32 ecx = regs->ecx, eax, edx;
984 struct vcpu *v = current;
985 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
987 switch ( ecx )
988 {
989 case MSR_EFER:
990 msr_content = v->arch.hvm_vcpu.guest_efer;
991 break;
993 case MSR_IA32_MC4_MISC: /* Threshold register */
994 case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:
995 /*
996 * MCA/MCE: We report that the threshold register is unavailable
997 * for OS use (locked by the BIOS).
998 */
999 msr_content = 1ULL << 61; /* MC4_MISC.Locked */
1000 break;
1002 case MSR_IA32_EBC_FREQUENCY_ID:
1003 /*
1004 * This Intel-only register may be accessed if this HVM guest
1005 * has been migrated from an Intel host. The value zero is not
1006 * particularly meaningful, but at least avoids the guest crashing!
1007 */
1008 msr_content = 0;
1009 break;
1011 case MSR_K8_VM_HSAVE_PA:
1012 goto gpf;
1014 case MSR_IA32_DEBUGCTLMSR:
1015 msr_content = vmcb->debugctlmsr;
1016 break;
1018 case MSR_IA32_LASTBRANCHFROMIP:
1019 msr_content = vmcb->lastbranchfromip;
1020 break;
1022 case MSR_IA32_LASTBRANCHTOIP:
1023 msr_content = vmcb->lastbranchtoip;
1024 break;
1026 case MSR_IA32_LASTINTFROMIP:
1027 msr_content = vmcb->lastintfromip;
1028 break;
1030 case MSR_IA32_LASTINTTOIP:
1031 msr_content = vmcb->lastinttoip;
1032 break;
1034 default:
1035 if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
1036 rdmsr_safe(ecx, eax, edx) == 0 )
1038 regs->eax = eax;
1039 regs->edx = edx;
1040 goto done;
1042 goto gpf;
1044 regs->eax = msr_content & 0xFFFFFFFF;
1045 regs->edx = msr_content >> 32;
1047 done:
1048 hvmtrace_msr_read(v, ecx, msr_content);
1049 HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
1050 ecx, (unsigned long)regs->eax, (unsigned long)regs->edx);
1051 return X86EMUL_OKAY;
1053 gpf:
1054 svm_inject_exception(TRAP_gp_fault, 0, 0);
1055 return X86EMUL_EXCEPTION;
1058 static int svm_msr_write_intercept(struct cpu_user_regs *regs)
1060 u64 msr_content = 0;
1061 u32 ecx = regs->ecx;
1062 struct vcpu *v = current;
1063 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1065 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
1067 hvmtrace_msr_write(v, ecx, msr_content);
1069 switch ( ecx )
1071 case MSR_K8_VM_HSAVE_PA:
1072 goto gpf;
1074 case MSR_IA32_DEBUGCTLMSR:
1075 vmcb->debugctlmsr = msr_content;
1076 if ( !msr_content || !cpu_has_svm_lbrv )
1077 break;
1078 vmcb->lbr_control.fields.enable = 1;
1079 svm_disable_intercept_for_msr(v, MSR_IA32_DEBUGCTLMSR);
1080 svm_disable_intercept_for_msr(v, MSR_IA32_LASTBRANCHFROMIP);
1081 svm_disable_intercept_for_msr(v, MSR_IA32_LASTBRANCHTOIP);
1082 svm_disable_intercept_for_msr(v, MSR_IA32_LASTINTFROMIP);
1083 svm_disable_intercept_for_msr(v, MSR_IA32_LASTINTTOIP);
1084 break;
1086 case MSR_IA32_LASTBRANCHFROMIP:
1087 vmcb->lastbranchfromip = msr_content;
1088 break;
1090 case MSR_IA32_LASTBRANCHTOIP:
1091 vmcb->lastbranchtoip = msr_content;
1092 break;
1094 case MSR_IA32_LASTINTFROMIP:
1095 vmcb->lastintfromip = msr_content;
1096 break;
1098 case MSR_IA32_LASTINTTOIP:
1099 vmcb->lastinttoip = msr_content;
1100 break;
1102 default:
1103 switch ( long_mode_do_msr_write(regs) )
1105 case HNDL_unhandled:
1106 wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
1107 break;
1108 case HNDL_exception_raised:
1109 return X86EMUL_EXCEPTION;
1110 case HNDL_done:
1111 break;
1113 break;
1116 return X86EMUL_OKAY;
1118 gpf:
1119 svm_inject_exception(TRAP_gp_fault, 0, 0);
1120 return X86EMUL_EXCEPTION;
1123 static void svm_do_msr_access(struct cpu_user_regs *regs)
1125 int rc, inst_len;
1126 struct vcpu *v = current;
1127 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1129 if ( vmcb->exitinfo1 == 0 )
1131 rc = hvm_msr_read_intercept(regs);
1132 inst_len = __get_instruction_length(v, INSTR_RDMSR, NULL);
1134 else
1136 rc = hvm_msr_write_intercept(regs);
1137 inst_len = __get_instruction_length(v, INSTR_WRMSR, NULL);
1140 if ( rc == X86EMUL_OKAY )
1141 __update_guest_eip(regs, inst_len);
1144 static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb,
1145 struct cpu_user_regs *regs)
1147 struct vcpu *curr = current;
1148 struct hvm_intack intack = hvm_vcpu_has_pending_irq(curr);
1149 unsigned int inst_len;
1151 inst_len = __get_instruction_length(curr, INSTR_HLT, NULL);
1152 if ( inst_len == 0 )
1153 return;
1154 __update_guest_eip(regs, inst_len);
1156 /* Check for pending exception or new interrupt. */
1157 if ( vmcb->eventinj.fields.v ||
1158 ((intack.source != hvm_intsrc_none) &&
1159 !hvm_interrupt_blocked(current, intack)) )
1161 HVMTRACE_1D(HLT, curr, /*int pending=*/ 1);
1162 return;
1165 HVMTRACE_1D(HLT, curr, /*int pending=*/ 0);
1166 hvm_hlt(regs->eflags);
1169 static void wbinvd_ipi(void *info)
1171 wbinvd();
1174 static void svm_wbinvd_intercept(void)
1176 if ( !list_empty(&(domain_hvm_iommu(current->domain)->pdev_list)) )
1177 on_each_cpu(wbinvd_ipi, NULL, 1, 1);
1180 static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)
1182 enum instruction_index list[] = { INSTR_INVD, INSTR_WBINVD };
1183 int inst_len;
1185 svm_wbinvd_intercept();
1187 inst_len = __get_instruction_length_from_list(
1188 current, list, ARRAY_SIZE(list), NULL, NULL);
1189 __update_guest_eip(regs, inst_len);
1192 static void svm_invlpg_intercept(unsigned long vaddr)
1194 struct vcpu *curr = current;
1195 HVMTRACE_2D(INVLPG, curr, 0, vaddr);
1196 paging_invlpg(curr, vaddr);
1197 svm_asid_g_invlpg(curr, vaddr);
1200 asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
1202 unsigned int exit_reason;
1203 struct vcpu *v = current;
1204 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
1205 eventinj_t eventinj;
1206 int inst_len, rc;
1208 /*
1209 * Before doing anything else, we need to sync up the VLAPIC's TPR with
1210 * SVM's vTPR. It's OK if the guest doesn't touch CR8 (e.g. 32-bit Windows)
1211 * because we update the vTPR on MMIO writes to the TPR.
1212 */
1213 vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,
1214 (vmcb->vintr.fields.tpr & 0x0F) << 4);
1216 exit_reason = vmcb->exitcode;
1218 hvmtrace_vmexit(v, regs->eip, exit_reason);
1220 if ( unlikely(exit_reason == VMEXIT_INVALID) )
1222 svm_dump_vmcb(__func__, vmcb);
1223 goto exit_and_crash;
1226 perfc_incra(svmexits, exit_reason);
1228 hvm_maybe_deassert_evtchn_irq();
1230 /* Event delivery caused this intercept? Queue for redelivery. */
1231 eventinj = vmcb->exitintinfo;
1232 if ( unlikely(eventinj.fields.v) &&
1233 hvm_event_needs_reinjection(eventinj.fields.type,
1234 eventinj.fields.vector) )
1235 vmcb->eventinj = eventinj;
1237 switch ( exit_reason )
1239 case VMEXIT_INTR:
1240 /* Asynchronous event, handled when we STGI'd after the VMEXIT. */
1241 HVMTRACE_0D(INTR, v);
1242 break;
1244 case VMEXIT_NMI:
1245 /* Asynchronous event, handled when we STGI'd after the VMEXIT. */
1246 HVMTRACE_0D(NMI, v);
1247 break;
1249 case VMEXIT_SMI:
1250 /* Asynchronous event, handled when we STGI'd after the VMEXIT. */
1251 HVMTRACE_0D(SMI, v);
1252 break;
1254 case VMEXIT_EXCEPTION_DB:
1255 if ( !v->domain->debugger_attached )
1256 goto exit_and_crash;
1257 domain_pause_for_debugger();
1258 break;
1260 case VMEXIT_EXCEPTION_BP:
1261 if ( !v->domain->debugger_attached )
1262 goto exit_and_crash;
1263 /* AMD Vol2, 15.11: INT3, INTO, BOUND intercepts do not update RIP. */
1264 inst_len = __get_instruction_length(v, INSTR_INT3, NULL);
1265 __update_guest_eip(regs, inst_len);
1266 domain_pause_for_debugger();
1267 break;
1269 case VMEXIT_EXCEPTION_NM:
1270 svm_fpu_dirty_intercept();
1271 break;
1273 case VMEXIT_EXCEPTION_PF: {
1274 unsigned long va;
1275 va = vmcb->exitinfo2;
1276 regs->error_code = vmcb->exitinfo1;
1277 HVM_DBG_LOG(DBG_LEVEL_VMMU,
1278 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
1279 (unsigned long)regs->eax, (unsigned long)regs->ebx,
1280 (unsigned long)regs->ecx, (unsigned long)regs->edx,
1281 (unsigned long)regs->esi, (unsigned long)regs->edi);
1283 if ( paging_fault(va, regs) )
1285 HVMTRACE_2D(PF_XEN, v, va, regs->error_code);
1286 break;
1289 svm_inject_exception(TRAP_page_fault, regs->error_code, va);
1290 break;
1293 /* Asynchronous event, handled when we STGI'd after the VMEXIT. */
1294 case VMEXIT_EXCEPTION_MC:
1295 HVMTRACE_0D(MCE, v);
1296 break;
1298 case VMEXIT_VINTR:
1299 vmcb->vintr.fields.irq = 0;
1300 vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR;
1301 break;
1303 case VMEXIT_INVD:
1304 case VMEXIT_WBINVD:
1305 svm_vmexit_do_invalidate_cache(regs);
1306 break;
1308 case VMEXIT_TASK_SWITCH: {
1309 enum hvm_task_switch_reason reason;
1310 int32_t errcode = -1;
1311 if ( (vmcb->exitinfo2 >> 36) & 1 )
1312 reason = TSW_iret;
1313 else if ( (vmcb->exitinfo2 >> 38) & 1 )
1314 reason = TSW_jmp;
1315 else
1316 reason = TSW_call_or_int;
1317 if ( (vmcb->exitinfo2 >> 44) & 1 )
1318 errcode = (uint32_t)vmcb->exitinfo2;
1319 hvm_task_switch((uint16_t)vmcb->exitinfo1, reason, errcode);
1320 break;
1323 case VMEXIT_CPUID:
1324 svm_vmexit_do_cpuid(regs);
1325 break;
1327 case VMEXIT_HLT:
1328 svm_vmexit_do_hlt(vmcb, regs);
1329 break;
1331 case VMEXIT_CR0_READ ... VMEXIT_CR15_READ:
1332 case VMEXIT_CR0_WRITE ... VMEXIT_CR15_WRITE:
1333 case VMEXIT_INVLPG:
1334 case VMEXIT_INVLPGA:
1335 case VMEXIT_IOIO:
1336 if ( !handle_mmio() )
1337 hvm_inject_exception(TRAP_gp_fault, 0, 0);
1338 break;
1340 case VMEXIT_VMMCALL:
1341 inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL);
1342 if ( inst_len == 0 )
1343 break;
1344 HVMTRACE_1D(VMMCALL, v, regs->eax);
1345 rc = hvm_do_hypercall(regs);
1346 if ( rc != HVM_HCALL_preempted )
1348 __update_guest_eip(regs, inst_len);
1349 if ( rc == HVM_HCALL_invalidate )
1350 send_invalidate_req();
1352 break;
1354 case VMEXIT_DR0_READ ... VMEXIT_DR7_READ:
1355 case VMEXIT_DR0_WRITE ... VMEXIT_DR7_WRITE:
1356 svm_dr_access(v, regs);
1357 break;
1359 case VMEXIT_MSR:
1360 svm_do_msr_access(regs);
1361 break;
1363 case VMEXIT_SHUTDOWN:
1364 hvm_triple_fault();
1365 break;
1367 case VMEXIT_RDTSCP:
1368 case VMEXIT_MONITOR:
1369 case VMEXIT_MWAIT:
1370 case VMEXIT_VMRUN:
1371 case VMEXIT_VMLOAD:
1372 case VMEXIT_VMSAVE:
1373 case VMEXIT_STGI:
1374 case VMEXIT_CLGI:
1375 case VMEXIT_SKINIT:
1376 svm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0);
1377 break;
1379 case VMEXIT_NPF:
1380 perfc_incra(svmexits, VMEXIT_NPF_PERFC);
1381 regs->error_code = vmcb->exitinfo1;
1382 svm_do_nested_pgfault(vmcb->exitinfo2, regs);
1383 break;
1385 default:
1386 exit_and_crash:
1387 gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, "
1388 "exitinfo1 = %"PRIx64", exitinfo2 = %"PRIx64"\n",
1389 exit_reason,
1390 (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2);
1391 domain_crash(v->domain);
1392 break;
1395 /* The exit may have updated the TPR: reflect this in the hardware vtpr */
1396 vmcb->vintr.fields.tpr =
1397 (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4;
1400 asmlinkage void svm_trace_vmentry(void)
1402 hvmtrace_vmentry(current);
1405 /*
1406 * Local variables:
1407 * mode: C
1408 * c-set-style: "BSD"
1409 * c-basic-offset: 4
1410 * tab-width: 4
1411 * indent-tabs-mode: nil
1412 * End:
1413 */