direct-io.hg

view xen/arch/x86/hvm/vmx/vmcs.c @ 12235:b21ff7716f87

[HVM] More printk cleanups.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Nov 03 12:32:26 2006 +0000 (2006-11-03)
parents 45e34f00a78f
children 2368e779f89f
line source
1 /*
2 * vmcs.c: VMCS management
3 * Copyright (c) 2004, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 */
19 #include <xen/config.h>
20 #include <xen/init.h>
21 #include <xen/mm.h>
22 #include <xen/lib.h>
23 #include <xen/errno.h>
24 #include <xen/domain_page.h>
25 #include <asm/current.h>
26 #include <asm/cpufeature.h>
27 #include <asm/processor.h>
28 #include <asm/msr.h>
29 #include <asm/hvm/hvm.h>
30 #include <asm/hvm/io.h>
31 #include <asm/hvm/support.h>
32 #include <asm/hvm/vmx/vmx.h>
33 #include <asm/hvm/vmx/vmcs.h>
34 #include <asm/flushtlb.h>
35 #include <xen/event.h>
36 #include <xen/kernel.h>
37 #include <xen/keyhandler.h>
38 #include <asm/shadow.h>
40 /* Basic flags for Pin-based VM-execution controls. */
41 #define MONITOR_PIN_BASED_EXEC_CONTROLS \
42 ( PIN_BASED_EXT_INTR_MASK | \
43 PIN_BASED_NMI_EXITING )
45 /* Basic flags for CPU-based VM-execution controls. */
46 #ifdef __x86_64__
47 #define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH \
48 ( CPU_BASED_CR8_LOAD_EXITING | \
49 CPU_BASED_CR8_STORE_EXITING )
50 #else
51 #define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH 0
52 #endif
53 #define MONITOR_CPU_BASED_EXEC_CONTROLS \
54 ( MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH | \
55 CPU_BASED_HLT_EXITING | \
56 CPU_BASED_INVDPG_EXITING | \
57 CPU_BASED_MWAIT_EXITING | \
58 CPU_BASED_MOV_DR_EXITING | \
59 CPU_BASED_UNCOND_IO_EXITING | \
60 CPU_BASED_USE_TSC_OFFSETING )
62 /* Basic flags for VM-Exit controls. */
63 #ifdef __x86_64__
64 #define MONITOR_VM_EXIT_CONTROLS_SUBARCH VM_EXIT_IA32E_MODE
65 #else
66 #define MONITOR_VM_EXIT_CONTROLS_SUBARCH 0
67 #endif
68 #define MONITOR_VM_EXIT_CONTROLS \
69 ( MONITOR_VM_EXIT_CONTROLS_SUBARCH | \
70 VM_EXIT_ACK_INTR_ON_EXIT )
72 /* Basic flags for VM-Entry controls. */
73 #define MONITOR_VM_ENTRY_CONTROLS 0x00000000
75 /* Dynamic (run-time adjusted) execution control flags. */
76 static u32 vmx_pin_based_exec_control;
77 static u32 vmx_cpu_based_exec_control;
78 static u32 vmx_vmexit_control;
79 static u32 vmx_vmentry_control;
81 static u32 vmcs_revision_id;
83 static u32 adjust_vmx_controls(u32 ctrls, u32 msr)
84 {
85 u32 vmx_msr_low, vmx_msr_high;
87 rdmsr(msr, vmx_msr_low, vmx_msr_high);
89 /* Bit == 0 means must be zero. */
90 BUG_ON(ctrls & ~vmx_msr_high);
92 /* Bit == 1 means must be one. */
93 ctrls |= vmx_msr_low;
95 return ctrls;
96 }
98 void vmx_init_vmcs_config(void)
99 {
100 u32 vmx_msr_low, vmx_msr_high;
101 u32 _vmx_pin_based_exec_control;
102 u32 _vmx_cpu_based_exec_control;
103 u32 _vmx_vmexit_control;
104 u32 _vmx_vmentry_control;
106 _vmx_pin_based_exec_control =
107 adjust_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS,
108 MSR_IA32_VMX_PINBASED_CTLS_MSR);
109 _vmx_cpu_based_exec_control =
110 adjust_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS,
111 MSR_IA32_VMX_PROCBASED_CTLS_MSR);
112 _vmx_vmexit_control =
113 adjust_vmx_controls(MONITOR_VM_EXIT_CONTROLS,
114 MSR_IA32_VMX_EXIT_CTLS_MSR);
115 _vmx_vmentry_control =
116 adjust_vmx_controls(MONITOR_VM_ENTRY_CONTROLS,
117 MSR_IA32_VMX_ENTRY_CTLS_MSR);
119 rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
121 if ( smp_processor_id() == 0 )
122 {
123 vmcs_revision_id = vmx_msr_low;
124 vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
125 vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
126 vmx_vmexit_control = _vmx_vmexit_control;
127 vmx_vmentry_control = _vmx_vmentry_control;
128 }
129 else
130 {
131 BUG_ON(vmcs_revision_id != vmx_msr_low);
132 BUG_ON(vmx_pin_based_exec_control != _vmx_pin_based_exec_control);
133 BUG_ON(vmx_cpu_based_exec_control != _vmx_cpu_based_exec_control);
134 BUG_ON(vmx_vmexit_control != _vmx_vmexit_control);
135 BUG_ON(vmx_vmentry_control != _vmx_vmentry_control);
136 }
138 /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
139 BUG_ON((vmx_msr_high & 0x1fff) > PAGE_SIZE);
140 }
142 static struct vmcs_struct *vmx_alloc_vmcs(void)
143 {
144 struct vmcs_struct *vmcs;
146 if ( (vmcs = alloc_xenheap_page()) == NULL )
147 {
148 gdprintk(XENLOG_WARNING, "Failed to allocate VMCS.\n");
149 return NULL;
150 }
152 memset(vmcs, 0, PAGE_SIZE);
153 vmcs->vmcs_revision_id = vmcs_revision_id;
155 return vmcs;
156 }
158 static void vmx_free_vmcs(struct vmcs_struct *vmcs)
159 {
160 free_xenheap_page(vmcs);
161 }
163 static void __vmx_clear_vmcs(void *info)
164 {
165 struct vcpu *v = info;
167 __vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs));
169 v->arch.hvm_vmx.active_cpu = -1;
170 v->arch.hvm_vmx.launched = 0;
171 }
173 static void vmx_clear_vmcs(struct vcpu *v)
174 {
175 int cpu = v->arch.hvm_vmx.active_cpu;
177 if ( cpu == -1 )
178 return;
180 if ( cpu == smp_processor_id() )
181 return __vmx_clear_vmcs(v);
183 on_selected_cpus(cpumask_of_cpu(cpu), __vmx_clear_vmcs, v, 1, 1);
184 }
186 static void vmx_load_vmcs(struct vcpu *v)
187 {
188 __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs));
189 v->arch.hvm_vmx.active_cpu = smp_processor_id();
190 }
192 void vmx_vmcs_enter(struct vcpu *v)
193 {
194 /*
195 * NB. We must *always* run an HVM VCPU on its own VMCS, except for
196 * vmx_vmcs_enter/exit critical regions. This leads to some XXX TODOs XXX:
197 * 1. Move construct_vmcs() much earlier, to domain creation or
198 * context initialisation.
199 * 2. VMPTRLD as soon as we context-switch to a HVM VCPU.
200 * 3. VMCS destruction needs to happen later (from domain_destroy()).
201 * We can relax this a bit if a paused VCPU always commits its
202 * architectural state to a software structure.
203 */
204 if ( v == current )
205 return;
207 vcpu_pause(v);
208 spin_lock(&v->arch.hvm_vmx.vmcs_lock);
210 vmx_clear_vmcs(v);
211 vmx_load_vmcs(v);
212 }
214 void vmx_vmcs_exit(struct vcpu *v)
215 {
216 if ( v == current )
217 return;
219 /* Don't confuse arch_vmx_do_resume (for @v or @current!) */
220 vmx_clear_vmcs(v);
221 if ( is_hvm_vcpu(current) )
222 vmx_load_vmcs(current);
224 spin_unlock(&v->arch.hvm_vmx.vmcs_lock);
225 vcpu_unpause(v);
226 }
228 struct vmcs_struct *vmx_alloc_host_vmcs(void)
229 {
230 return vmx_alloc_vmcs();
231 }
233 void vmx_free_host_vmcs(struct vmcs_struct *vmcs)
234 {
235 vmx_free_vmcs(vmcs);
236 }
238 static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
239 {
240 int error = 0;
242 error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
243 error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
244 error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control);
246 return error;
247 }
249 #define GUEST_LAUNCH_DS 0x08
250 #define GUEST_LAUNCH_CS 0x10
251 #define GUEST_SEGMENT_LIMIT 0xffffffff
252 #define HOST_SEGMENT_LIMIT 0xffffffff
254 struct host_execution_env {
255 /* selectors */
256 unsigned short ldtr_selector;
257 unsigned short tr_selector;
258 unsigned short ds_selector;
259 unsigned short cs_selector;
260 /* limits */
261 unsigned short gdtr_limit;
262 unsigned short ldtr_limit;
263 unsigned short idtr_limit;
264 unsigned short tr_limit;
265 /* base */
266 unsigned long gdtr_base;
267 unsigned long ldtr_base;
268 unsigned long idtr_base;
269 unsigned long tr_base;
270 unsigned long ds_base;
271 unsigned long cs_base;
272 #ifdef __x86_64__
273 unsigned long fs_base;
274 unsigned long gs_base;
275 #endif
276 };
278 static void vmx_set_host_env(struct vcpu *v)
279 {
280 unsigned int tr, cpu, error = 0;
281 struct host_execution_env host_env;
282 struct Xgt_desc_struct desc;
284 cpu = smp_processor_id();
285 __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory");
286 host_env.idtr_limit = desc.size;
287 host_env.idtr_base = desc.address;
288 error |= __vmwrite(HOST_IDTR_BASE, host_env.idtr_base);
290 __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&desc) : "memory");
291 host_env.gdtr_limit = desc.size;
292 host_env.gdtr_base = desc.address;
293 error |= __vmwrite(HOST_GDTR_BASE, host_env.gdtr_base);
295 __asm__ __volatile__ ("str (%0) \n" :: "a"(&tr) : "memory");
296 host_env.tr_selector = tr;
297 host_env.tr_limit = sizeof(struct tss_struct);
298 host_env.tr_base = (unsigned long) &init_tss[cpu];
299 error |= __vmwrite(HOST_TR_SELECTOR, host_env.tr_selector);
300 error |= __vmwrite(HOST_TR_BASE, host_env.tr_base);
301 error |= __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
302 }
304 /* Update CR3, CR0, CR4, GDT, LDT, TR */
305 static void vmx_do_launch(struct vcpu *v)
306 {
307 unsigned int error = 0;
308 unsigned long cr0, cr4;
310 if ( v->vcpu_id == 0 )
311 hvm_setup_platform(v->domain);
312 else {
313 /* Sync AP's TSC with BSP's */
314 v->arch.hvm_vcpu.cache_tsc_offset =
315 v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
316 hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
317 }
319 __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : );
321 error |= __vmwrite(GUEST_CR0, cr0);
322 cr0 &= ~X86_CR0_PG;
323 error |= __vmwrite(CR0_READ_SHADOW, cr0);
324 error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control);
325 v->arch.hvm_vcpu.u.vmx.exec_control = vmx_cpu_based_exec_control;
327 __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (cr4) : );
329 error |= __vmwrite(GUEST_CR4, cr4 & ~X86_CR4_PSE);
330 cr4 &= ~(X86_CR4_PGE | X86_CR4_VMXE | X86_CR4_PAE);
332 error |= __vmwrite(CR4_READ_SHADOW, cr4);
334 hvm_stts(v);
336 if( hvm_apic_support(v->domain) && (vlapic_init(v) == 0) )
337 {
338 #ifdef __x86_64__
339 u32 *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control;
340 u64 vapic_page_addr =
341 page_to_maddr(v->arch.hvm_vcpu.vlapic->regs_page);
343 *cpu_exec_control |= CPU_BASED_TPR_SHADOW;
344 *cpu_exec_control &= ~CPU_BASED_CR8_STORE_EXITING;
345 *cpu_exec_control &= ~CPU_BASED_CR8_LOAD_EXITING;
346 error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control);
347 error |= __vmwrite(VIRTUAL_APIC_PAGE_ADDR, vapic_page_addr);
348 error |= __vmwrite(TPR_THRESHOLD, 0);
349 #endif
350 }
352 vmx_set_host_env(v);
353 init_timer(&v->arch.hvm_vcpu.hlt_timer, hlt_timer_fn, v, v->processor);
355 error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
356 error |= __vmwrite(GUEST_LDTR_BASE, 0);
357 error |= __vmwrite(GUEST_LDTR_LIMIT, 0);
359 error |= __vmwrite(GUEST_TR_BASE, 0);
360 error |= __vmwrite(GUEST_TR_LIMIT, 0xff);
362 shadow_update_paging_modes(v);
364 __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
365 __vmwrite(HOST_CR3, v->arch.cr3);
367 v->arch.schedule_tail = arch_vmx_do_resume;
368 }
370 /*
371 * Initially set the same environement as host.
372 */
373 static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
374 {
375 int error = 0;
376 union vmcs_arbytes arbytes;
377 unsigned long dr7;
378 unsigned long eflags;
380 /* MSR */
381 error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0);
382 error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0);
383 error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
384 error |= __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
385 error |= __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
387 error |= __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
389 error |= __vmwrite(CR0_GUEST_HOST_MASK, ~0UL);
390 error |= __vmwrite(CR4_GUEST_HOST_MASK, ~0UL);
392 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0);
393 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0);
395 error |= __vmwrite(CR3_TARGET_COUNT, 0);
397 error |= __vmwrite(GUEST_ACTIVITY_STATE, 0);
399 /* Guest Selectors */
400 error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS);
401 error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
402 error |= __vmwrite(GUEST_DS_SELECTOR, GUEST_LAUNCH_DS);
403 error |= __vmwrite(GUEST_FS_SELECTOR, GUEST_LAUNCH_DS);
404 error |= __vmwrite(GUEST_GS_SELECTOR, GUEST_LAUNCH_DS);
405 error |= __vmwrite(GUEST_CS_SELECTOR, GUEST_LAUNCH_CS);
407 /* Guest segment bases */
408 error |= __vmwrite(GUEST_ES_BASE, 0);
409 error |= __vmwrite(GUEST_SS_BASE, 0);
410 error |= __vmwrite(GUEST_DS_BASE, 0);
411 error |= __vmwrite(GUEST_FS_BASE, 0);
412 error |= __vmwrite(GUEST_GS_BASE, 0);
413 error |= __vmwrite(GUEST_CS_BASE, 0);
415 /* Guest segment Limits */
416 error |= __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT);
417 error |= __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT);
418 error |= __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT);
419 error |= __vmwrite(GUEST_FS_LIMIT, GUEST_SEGMENT_LIMIT);
420 error |= __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT);
421 error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
423 /* Guest segment AR bytes */
424 arbytes.bytes = 0;
425 arbytes.fields.seg_type = 0x3; /* type = 3 */
426 arbytes.fields.s = 1; /* code or data, i.e. not system */
427 arbytes.fields.dpl = 0; /* DPL = 3 */
428 arbytes.fields.p = 1; /* segment present */
429 arbytes.fields.default_ops_size = 1; /* 32-bit */
430 arbytes.fields.g = 1;
431 arbytes.fields.null_bit = 0; /* not null */
433 error |= __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes);
434 error |= __vmwrite(GUEST_SS_AR_BYTES, arbytes.bytes);
435 error |= __vmwrite(GUEST_DS_AR_BYTES, arbytes.bytes);
436 error |= __vmwrite(GUEST_FS_AR_BYTES, arbytes.bytes);
437 error |= __vmwrite(GUEST_GS_AR_BYTES, arbytes.bytes);
439 arbytes.fields.seg_type = 0xb; /* type = 0xb */
440 error |= __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes);
442 /* Guest GDT */
443 error |= __vmwrite(GUEST_GDTR_BASE, 0);
444 error |= __vmwrite(GUEST_GDTR_LIMIT, 0);
446 /* Guest IDT */
447 error |= __vmwrite(GUEST_IDTR_BASE, 0);
448 error |= __vmwrite(GUEST_IDTR_LIMIT, 0);
450 /* Guest LDT & TSS */
451 arbytes.fields.s = 0; /* not code or data segement */
452 arbytes.fields.seg_type = 0x2; /* LTD */
453 arbytes.fields.default_ops_size = 0; /* 16-bit */
454 arbytes.fields.g = 0;
455 error |= __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes);
457 arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */
458 error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
459 /* CR3 is set in vmx_final_setup_guest */
461 error |= __vmwrite(GUEST_RSP, 0);
462 error |= __vmwrite(GUEST_RIP, regs->eip);
464 /* Guest EFLAGS */
465 eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
466 eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
467 error |= __vmwrite(GUEST_RFLAGS, eflags);
469 error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
470 __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
471 error |= __vmwrite(GUEST_DR7, dr7);
472 error |= __vmwrite(VMCS_LINK_POINTER, ~0UL);
473 #if defined(__i386__)
474 error |= __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL);
475 #endif
477 return error;
478 }
480 static inline int construct_vmcs_host(void)
481 {
482 int error = 0;
483 #ifdef __x86_64__
484 unsigned long fs_base;
485 unsigned long gs_base;
486 #endif
487 unsigned long crn;
489 /* Host Selectors */
490 error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
491 error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
492 error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
493 #if defined(__i386__)
494 error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
495 error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
496 error |= __vmwrite(HOST_FS_BASE, 0);
497 error |= __vmwrite(HOST_GS_BASE, 0);
499 #else
500 rdmsrl(MSR_FS_BASE, fs_base);
501 rdmsrl(MSR_GS_BASE, gs_base);
502 error |= __vmwrite(HOST_FS_BASE, fs_base);
503 error |= __vmwrite(HOST_GS_BASE, gs_base);
505 #endif
506 error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
508 __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : );
509 error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
511 /* CR3 is set in vmx_final_setup_hostos */
512 __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
513 error |= __vmwrite(HOST_CR4, crn);
515 error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
517 return error;
518 }
520 /*
521 * the working VMCS pointer has been set properly
522 * just before entering this function.
523 */
524 static int construct_vmcs(struct vcpu *v,
525 cpu_user_regs_t *regs)
526 {
527 struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
528 int error;
530 if ( (error = construct_vmcs_controls(arch_vmx)) ) {
531 printk("construct_vmcs: construct_vmcs_controls failed.\n");
532 return error;
533 }
535 /* host selectors */
536 if ( (error = construct_vmcs_host()) ) {
537 printk("construct_vmcs: construct_vmcs_host failed.\n");
538 return error;
539 }
541 /* guest selectors */
542 if ( (error = construct_init_vmcs_guest(regs)) ) {
543 printk("construct_vmcs: construct_vmcs_guest failed.\n");
544 return error;
545 }
547 if ( (error = __vmwrite(EXCEPTION_BITMAP,
548 MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) {
549 printk("construct_vmcs: setting exception bitmap failed.\n");
550 return error;
551 }
553 if ( regs->eflags & EF_TF )
554 error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
555 else
556 error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
558 return error;
559 }
561 int vmx_create_vmcs(struct vcpu *v)
562 {
563 if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
564 return -ENOMEM;
565 __vmx_clear_vmcs(v);
566 return 0;
567 }
569 void vmx_destroy_vmcs(struct vcpu *v)
570 {
571 struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
573 if ( arch_vmx->vmcs == NULL )
574 return;
576 vmx_clear_vmcs(v);
578 vmx_free_vmcs(arch_vmx->vmcs);
579 arch_vmx->vmcs = NULL;
580 }
582 void vm_launch_fail(unsigned long eflags)
583 {
584 unsigned long error;
585 __vmread(VM_INSTRUCTION_ERROR, &error);
586 printk("<vm_launch_fail> error code %lx\n", error);
587 __hvm_bug(guest_cpu_user_regs());
588 }
590 void vm_resume_fail(unsigned long eflags)
591 {
592 unsigned long error;
593 __vmread(VM_INSTRUCTION_ERROR, &error);
594 printk("<vm_resume_fail> error code %lx\n", error);
595 __hvm_bug(guest_cpu_user_regs());
596 }
598 void arch_vmx_do_resume(struct vcpu *v)
599 {
600 if ( v->arch.hvm_vmx.active_cpu == smp_processor_id() )
601 {
602 vmx_load_vmcs(v);
603 }
604 else
605 {
606 vmx_clear_vmcs(v);
607 vmx_load_vmcs(v);
608 vmx_migrate_timers(v);
609 vmx_set_host_env(v);
610 }
612 hvm_do_resume(v);
613 reset_stack_and_jump(vmx_asm_do_vmentry);
614 }
616 void arch_vmx_do_launch(struct vcpu *v)
617 {
618 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
620 vmx_load_vmcs(v);
622 if ( construct_vmcs(v, regs) < 0 )
623 {
624 if ( v->vcpu_id == 0 ) {
625 printk("Failed to construct VMCS for BSP.\n");
626 } else {
627 printk("Failed to construct VMCS for AP %d.\n", v->vcpu_id);
628 }
629 domain_crash_synchronous();
630 }
632 vmx_do_launch(v);
633 reset_stack_and_jump(vmx_asm_do_vmentry);
634 }
637 /* Dump a section of VMCS */
638 static void print_section(char *header, uint32_t start,
639 uint32_t end, int incr)
640 {
641 uint32_t addr, j;
642 unsigned long val;
643 int code;
644 char *fmt[4] = {"0x%04lx ", "0x%016lx ", "0x%08lx ", "0x%016lx "};
645 char *err[4] = {"------ ", "------------------ ",
646 "---------- ", "------------------ "};
648 /* Find width of the field (encoded in bits 14:13 of address) */
649 code = (start>>13)&3;
651 if (header)
652 printk("\t %s", header);
654 for (addr=start, j=0; addr<=end; addr+=incr, j++) {
656 if (!(j&3))
657 printk("\n\t\t0x%08x: ", addr);
659 if (!__vmread(addr, &val))
660 printk(fmt[code], val);
661 else
662 printk("%s", err[code]);
663 }
665 printk("\n");
666 }
668 /* Dump current VMCS */
669 void vmcs_dump_vcpu(void)
670 {
671 print_section("16-bit Guest-State Fields", 0x800, 0x80e, 2);
672 print_section("16-bit Host-State Fields", 0xc00, 0xc0c, 2);
673 print_section("64-bit Control Fields", 0x2000, 0x2013, 1);
674 print_section("64-bit Guest-State Fields", 0x2800, 0x2803, 1);
675 print_section("32-bit Control Fields", 0x4000, 0x401c, 2);
676 print_section("32-bit RO Data Fields", 0x4400, 0x440e, 2);
677 print_section("32-bit Guest-State Fields", 0x4800, 0x482a, 2);
678 print_section("32-bit Host-State Fields", 0x4c00, 0x4c00, 2);
679 print_section("Natural 64-bit Control Fields", 0x6000, 0x600e, 2);
680 print_section("64-bit RO Data Fields", 0x6400, 0x640A, 2);
681 print_section("Natural 64-bit Guest-State Fields", 0x6800, 0x6826, 2);
682 print_section("Natural 64-bit Host-State Fields", 0x6c00, 0x6c16, 2);
683 }
686 static void vmcs_dump(unsigned char ch)
687 {
688 struct domain *d;
689 struct vcpu *v;
691 printk("*********** VMCS Areas **************\n");
692 for_each_domain ( d )
693 {
694 if ( !is_hvm_domain(d) )
695 continue;
696 printk("\n>>> Domain %d <<<\n", d->domain_id);
697 for_each_vcpu ( d, v )
698 {
699 printk("\tVCPU %d\n", v->vcpu_id);
700 vmx_vmcs_enter(v);
701 vmcs_dump_vcpu();
702 vmx_vmcs_exit(v);
703 }
704 }
706 printk("**************************************\n");
707 }
709 void setup_vmcs_dump(void)
710 {
711 register_keyhandler('v', vmcs_dump, "dump Intel's VMCS");
712 }
715 /*
716 * Local variables:
717 * mode: C
718 * c-set-style: "BSD"
719 * c-basic-offset: 4
720 * tab-width: 4
721 * indent-tabs-mode: nil
722 * End:
723 */