ia64/xen-unstable

view xen/arch/x86/hvm/vmx/vmcs.c @ 12226:45e34f00a78f

[HVM] Clean up VCPU initialisation in Xen. No longer
parse HVM e820 tables in Xen (add some extra HVM parameters as a
cleaner alternative). Lots of code removal.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Nov 02 15:55:51 2006 +0000 (2006-11-02)
parents 7b5115221dfc
children b21ff7716f87
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);
363 printk("%s(): GUEST_CR3<=%08lx, HOST_CR3<=%08lx\n",
364 __func__, v->arch.hvm_vcpu.hw_cr3, v->arch.cr3);
365 __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
366 __vmwrite(HOST_CR3, v->arch.cr3);
368 v->arch.schedule_tail = arch_vmx_do_resume;
369 }
371 /*
372 * Initially set the same environement as host.
373 */
374 static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
375 {
376 int error = 0;
377 union vmcs_arbytes arbytes;
378 unsigned long dr7;
379 unsigned long eflags;
381 /* MSR */
382 error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0);
383 error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0);
384 error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
385 error |= __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
386 error |= __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
388 error |= __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
390 error |= __vmwrite(CR0_GUEST_HOST_MASK, ~0UL);
391 error |= __vmwrite(CR4_GUEST_HOST_MASK, ~0UL);
393 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0);
394 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0);
396 error |= __vmwrite(CR3_TARGET_COUNT, 0);
398 error |= __vmwrite(GUEST_ACTIVITY_STATE, 0);
400 /* Guest Selectors */
401 error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS);
402 error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
403 error |= __vmwrite(GUEST_DS_SELECTOR, GUEST_LAUNCH_DS);
404 error |= __vmwrite(GUEST_FS_SELECTOR, GUEST_LAUNCH_DS);
405 error |= __vmwrite(GUEST_GS_SELECTOR, GUEST_LAUNCH_DS);
406 error |= __vmwrite(GUEST_CS_SELECTOR, GUEST_LAUNCH_CS);
408 /* Guest segment bases */
409 error |= __vmwrite(GUEST_ES_BASE, 0);
410 error |= __vmwrite(GUEST_SS_BASE, 0);
411 error |= __vmwrite(GUEST_DS_BASE, 0);
412 error |= __vmwrite(GUEST_FS_BASE, 0);
413 error |= __vmwrite(GUEST_GS_BASE, 0);
414 error |= __vmwrite(GUEST_CS_BASE, 0);
416 /* Guest segment Limits */
417 error |= __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT);
418 error |= __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT);
419 error |= __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT);
420 error |= __vmwrite(GUEST_FS_LIMIT, GUEST_SEGMENT_LIMIT);
421 error |= __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT);
422 error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
424 /* Guest segment AR bytes */
425 arbytes.bytes = 0;
426 arbytes.fields.seg_type = 0x3; /* type = 3 */
427 arbytes.fields.s = 1; /* code or data, i.e. not system */
428 arbytes.fields.dpl = 0; /* DPL = 3 */
429 arbytes.fields.p = 1; /* segment present */
430 arbytes.fields.default_ops_size = 1; /* 32-bit */
431 arbytes.fields.g = 1;
432 arbytes.fields.null_bit = 0; /* not null */
434 error |= __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes);
435 error |= __vmwrite(GUEST_SS_AR_BYTES, arbytes.bytes);
436 error |= __vmwrite(GUEST_DS_AR_BYTES, arbytes.bytes);
437 error |= __vmwrite(GUEST_FS_AR_BYTES, arbytes.bytes);
438 error |= __vmwrite(GUEST_GS_AR_BYTES, arbytes.bytes);
440 arbytes.fields.seg_type = 0xb; /* type = 0xb */
441 error |= __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes);
443 /* Guest GDT */
444 error |= __vmwrite(GUEST_GDTR_BASE, 0);
445 error |= __vmwrite(GUEST_GDTR_LIMIT, 0);
447 /* Guest IDT */
448 error |= __vmwrite(GUEST_IDTR_BASE, 0);
449 error |= __vmwrite(GUEST_IDTR_LIMIT, 0);
451 /* Guest LDT & TSS */
452 arbytes.fields.s = 0; /* not code or data segement */
453 arbytes.fields.seg_type = 0x2; /* LTD */
454 arbytes.fields.default_ops_size = 0; /* 16-bit */
455 arbytes.fields.g = 0;
456 error |= __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes);
458 arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */
459 error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
460 /* CR3 is set in vmx_final_setup_guest */
462 error |= __vmwrite(GUEST_RSP, 0);
463 error |= __vmwrite(GUEST_RIP, regs->eip);
465 /* Guest EFLAGS */
466 eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
467 eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
468 error |= __vmwrite(GUEST_RFLAGS, eflags);
470 error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
471 __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
472 error |= __vmwrite(GUEST_DR7, dr7);
473 error |= __vmwrite(VMCS_LINK_POINTER, ~0UL);
474 #if defined(__i386__)
475 error |= __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL);
476 #endif
478 return error;
479 }
481 static inline int construct_vmcs_host(void)
482 {
483 int error = 0;
484 #ifdef __x86_64__
485 unsigned long fs_base;
486 unsigned long gs_base;
487 #endif
488 unsigned long crn;
490 /* Host Selectors */
491 error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
492 error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
493 error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
494 #if defined(__i386__)
495 error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
496 error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
497 error |= __vmwrite(HOST_FS_BASE, 0);
498 error |= __vmwrite(HOST_GS_BASE, 0);
500 #else
501 rdmsrl(MSR_FS_BASE, fs_base);
502 rdmsrl(MSR_GS_BASE, gs_base);
503 error |= __vmwrite(HOST_FS_BASE, fs_base);
504 error |= __vmwrite(HOST_GS_BASE, gs_base);
506 #endif
507 error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
509 __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : );
510 error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
512 /* CR3 is set in vmx_final_setup_hostos */
513 __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
514 error |= __vmwrite(HOST_CR4, crn);
516 error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
518 return error;
519 }
521 /*
522 * the working VMCS pointer has been set properly
523 * just before entering this function.
524 */
525 static int construct_vmcs(struct vcpu *v,
526 cpu_user_regs_t *regs)
527 {
528 struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
529 int error;
531 if ( (error = construct_vmcs_controls(arch_vmx)) ) {
532 printk("construct_vmcs: construct_vmcs_controls failed.\n");
533 return error;
534 }
536 /* host selectors */
537 if ( (error = construct_vmcs_host()) ) {
538 printk("construct_vmcs: construct_vmcs_host failed.\n");
539 return error;
540 }
542 /* guest selectors */
543 if ( (error = construct_init_vmcs_guest(regs)) ) {
544 printk("construct_vmcs: construct_vmcs_guest failed.\n");
545 return error;
546 }
548 if ( (error = __vmwrite(EXCEPTION_BITMAP,
549 MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) {
550 printk("construct_vmcs: setting exception bitmap failed.\n");
551 return error;
552 }
554 if ( regs->eflags & EF_TF )
555 error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
556 else
557 error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
559 return error;
560 }
562 int vmx_create_vmcs(struct vcpu *v)
563 {
564 if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
565 return -ENOMEM;
566 __vmx_clear_vmcs(v);
567 return 0;
568 }
570 void vmx_destroy_vmcs(struct vcpu *v)
571 {
572 struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
574 if ( arch_vmx->vmcs == NULL )
575 return;
577 vmx_clear_vmcs(v);
579 vmx_free_vmcs(arch_vmx->vmcs);
580 arch_vmx->vmcs = NULL;
581 }
583 void vm_launch_fail(unsigned long eflags)
584 {
585 unsigned long error;
586 __vmread(VM_INSTRUCTION_ERROR, &error);
587 printk("<vm_launch_fail> error code %lx\n", error);
588 __hvm_bug(guest_cpu_user_regs());
589 }
591 void vm_resume_fail(unsigned long eflags)
592 {
593 unsigned long error;
594 __vmread(VM_INSTRUCTION_ERROR, &error);
595 printk("<vm_resume_fail> error code %lx\n", error);
596 __hvm_bug(guest_cpu_user_regs());
597 }
599 void arch_vmx_do_resume(struct vcpu *v)
600 {
601 if ( v->arch.hvm_vmx.active_cpu == smp_processor_id() )
602 {
603 vmx_load_vmcs(v);
604 }
605 else
606 {
607 vmx_clear_vmcs(v);
608 vmx_load_vmcs(v);
609 vmx_migrate_timers(v);
610 vmx_set_host_env(v);
611 }
613 hvm_do_resume(v);
614 reset_stack_and_jump(vmx_asm_do_vmentry);
615 }
617 void arch_vmx_do_launch(struct vcpu *v)
618 {
619 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
621 vmx_load_vmcs(v);
623 if ( construct_vmcs(v, regs) < 0 )
624 {
625 if ( v->vcpu_id == 0 ) {
626 printk("Failed to construct VMCS for BSP.\n");
627 } else {
628 printk("Failed to construct VMCS for AP %d.\n", v->vcpu_id);
629 }
630 domain_crash_synchronous();
631 }
633 vmx_do_launch(v);
634 reset_stack_and_jump(vmx_asm_do_vmentry);
635 }
638 /* Dump a section of VMCS */
639 static void print_section(char *header, uint32_t start,
640 uint32_t end, int incr)
641 {
642 uint32_t addr, j;
643 unsigned long val;
644 int code;
645 char *fmt[4] = {"0x%04lx ", "0x%016lx ", "0x%08lx ", "0x%016lx "};
646 char *err[4] = {"------ ", "------------------ ",
647 "---------- ", "------------------ "};
649 /* Find width of the field (encoded in bits 14:13 of address) */
650 code = (start>>13)&3;
652 if (header)
653 printk("\t %s", header);
655 for (addr=start, j=0; addr<=end; addr+=incr, j++) {
657 if (!(j&3))
658 printk("\n\t\t0x%08x: ", addr);
660 if (!__vmread(addr, &val))
661 printk(fmt[code], val);
662 else
663 printk("%s", err[code]);
664 }
666 printk("\n");
667 }
669 /* Dump current VMCS */
670 void vmcs_dump_vcpu(void)
671 {
672 print_section("16-bit Guest-State Fields", 0x800, 0x80e, 2);
673 print_section("16-bit Host-State Fields", 0xc00, 0xc0c, 2);
674 print_section("64-bit Control Fields", 0x2000, 0x2013, 1);
675 print_section("64-bit Guest-State Fields", 0x2800, 0x2803, 1);
676 print_section("32-bit Control Fields", 0x4000, 0x401c, 2);
677 print_section("32-bit RO Data Fields", 0x4400, 0x440e, 2);
678 print_section("32-bit Guest-State Fields", 0x4800, 0x482a, 2);
679 print_section("32-bit Host-State Fields", 0x4c00, 0x4c00, 2);
680 print_section("Natural 64-bit Control Fields", 0x6000, 0x600e, 2);
681 print_section("64-bit RO Data Fields", 0x6400, 0x640A, 2);
682 print_section("Natural 64-bit Guest-State Fields", 0x6800, 0x6826, 2);
683 print_section("Natural 64-bit Host-State Fields", 0x6c00, 0x6c16, 2);
684 }
687 static void vmcs_dump(unsigned char ch)
688 {
689 struct domain *d;
690 struct vcpu *v;
692 printk("*********** VMCS Areas **************\n");
693 for_each_domain ( d )
694 {
695 if ( !is_hvm_domain(d) )
696 continue;
697 printk("\n>>> Domain %d <<<\n", d->domain_id);
698 for_each_vcpu ( d, v )
699 {
700 printk("\tVCPU %d\n", v->vcpu_id);
701 vmx_vmcs_enter(v);
702 vmcs_dump_vcpu();
703 vmx_vmcs_exit(v);
704 }
705 }
707 printk("**************************************\n");
708 }
710 void setup_vmcs_dump(void)
711 {
712 register_keyhandler('v', vmcs_dump, "dump Intel's VMCS");
713 }
716 /*
717 * Local variables:
718 * mode: C
719 * c-set-style: "BSD"
720 * c-basic-offset: 4
721 * tab-width: 4
722 * indent-tabs-mode: nil
723 * End:
724 */