xen-vtx-unstable

annotate xen/arch/x86/vmx_vmcs.c @ 5820:07884fe7c5ce

Save per cpu IDT information into the VMCS host area.

Without this, we may be saving the IDT info from the wrong cpu into the
vmcs.
This makes domU work in the presence of VMX domains on SMP/HT enabled
machines.

Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
Signed-off-by: Xiaofeng Ling <xiaofeng.ling@intel.com>=20
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jul 21 13:59:49 2005 +0000 (2005-07-21)
parents a83ac0806d6b
children 6e11af443eb1
rev   line source
iap10@3290 1 /*
iap10@3290 2 * vmx_vmcs.c: VMCS management
iap10@3290 3 * Copyright (c) 2004, Intel Corporation.
iap10@3290 4 *
iap10@3290 5 * This program is free software; you can redistribute it and/or modify it
iap10@3290 6 * under the terms and conditions of the GNU General Public License,
iap10@3290 7 * version 2, as published by the Free Software Foundation.
iap10@3290 8 *
iap10@3290 9 * This program is distributed in the hope it will be useful, but WITHOUT
iap10@3290 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
iap10@3290 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
iap10@3290 12 * more details.
iap10@3290 13 *
iap10@3290 14 * You should have received a copy of the GNU General Public License along with
iap10@3290 15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
iap10@3290 16 * Place - Suite 330, Boston, MA 02111-1307 USA.
iap10@3290 17 *
iap10@3290 18 */
iap10@3290 19
iap10@3290 20 #include <xen/config.h>
iap10@3290 21 #include <xen/init.h>
iap10@3290 22 #include <xen/mm.h>
iap10@3290 23 #include <xen/lib.h>
iap10@3290 24 #include <xen/errno.h>
kaf24@5356 25 #include <xen/domain_page.h>
cl349@5291 26 #include <asm/current.h>
iap10@3290 27 #include <asm/cpufeature.h>
iap10@3290 28 #include <asm/processor.h>
iap10@3290 29 #include <asm/msr.h>
iap10@3290 30 #include <asm/vmx.h>
kaf24@5722 31 #include <asm/flushtlb.h>
iap10@3290 32 #include <xen/event.h>
iap10@3290 33 #include <xen/kernel.h>
iap10@3290 34 #include <public/io/ioreq.h>
kaf24@5722 35 #if CONFIG_PAGING_LEVELS >= 4
kaf24@5722 36 #include <asm/shadow_64.h>
kaf24@5722 37 #endif
mafetter@3717 38 #ifdef CONFIG_VMX
mafetter@3717 39
iap10@3290 40 struct vmcs_struct *alloc_vmcs(void)
iap10@3290 41 {
iap10@3290 42 struct vmcs_struct *vmcs;
kaf24@5059 43 u32 vmx_msr_low, vmx_msr_high;
iap10@3290 44
kaf24@5059 45 rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
kaf24@5059 46 vmcs_size = vmx_msr_high & 0x1fff;
kaf24@5398 47 vmcs = alloc_xenheap_pages(get_order(vmcs_size));
kaf24@5398 48 memset((char *)vmcs, 0, vmcs_size); /* don't remove this */
iap10@3290 49
kaf24@5059 50 vmcs->vmcs_revision_id = vmx_msr_low;
iap10@3290 51 return vmcs;
iap10@3290 52 }
iap10@3290 53
iap10@3290 54 void free_vmcs(struct vmcs_struct *vmcs)
iap10@3290 55 {
iap10@3290 56 int order;
iap10@3290 57
kaf24@5775 58 order = get_order(vmcs_size);
kaf24@5398 59 free_xenheap_pages(vmcs, order);
iap10@3290 60 }
iap10@3290 61
iap10@3290 62 static inline int construct_vmcs_controls(void)
iap10@3290 63 {
iap10@3290 64 int error = 0;
kaf24@5775 65
iap10@3290 66 error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL,
iap10@3290 67 MONITOR_PIN_BASED_EXEC_CONTROLS);
iap10@3290 68
iap10@3290 69 error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
iap10@3290 70 MONITOR_CPU_BASED_EXEC_CONTROLS);
kaf24@5775 71
iap10@3290 72 error |= __vmwrite(VM_EXIT_CONTROLS, MONITOR_VM_EXIT_CONTROLS);
kaf24@5775 73
iap10@3290 74 error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS);
iap10@3290 75
iap10@3290 76 return error;
iap10@3290 77 }
iap10@3290 78
iap10@3290 79 #define GUEST_SEGMENT_LIMIT 0xffffffff
iap10@3290 80 #define HOST_SEGMENT_LIMIT 0xffffffff
iap10@3290 81
iap10@3290 82 struct host_execution_env {
iap10@3290 83 /* selectors */
iap10@3290 84 unsigned short ldtr_selector;
iap10@3290 85 unsigned short tr_selector;
iap10@3290 86 unsigned short ds_selector;
iap10@3290 87 unsigned short cs_selector;
iap10@3290 88 /* limits */
iap10@3290 89 unsigned short gdtr_limit;
iap10@3290 90 unsigned short ldtr_limit;
iap10@3290 91 unsigned short idtr_limit;
iap10@3290 92 unsigned short tr_limit;
iap10@3290 93 /* base */
iap10@3290 94 unsigned long gdtr_base;
iap10@3290 95 unsigned long ldtr_base;
iap10@3290 96 unsigned long idtr_base;
iap10@3290 97 unsigned long tr_base;
iap10@3290 98 unsigned long ds_base;
iap10@3290 99 unsigned long cs_base;
kaf24@5658 100 #ifdef __x86_64__
kaf24@5658 101 unsigned long fs_base;
kaf24@5658 102 unsigned long gs_base;
kaf24@5658 103 #endif
kaf24@5658 104
iap10@3290 105 /* control registers */
iap10@3290 106 unsigned long cr3;
iap10@3290 107 unsigned long cr0;
iap10@3290 108 unsigned long cr4;
iap10@3290 109 unsigned long dr7;
iap10@3290 110 };
iap10@3290 111
iap10@3290 112 #define round_pgdown(_p) ((_p)&PAGE_MASK) /* coped from domain.c */
iap10@3290 113
kaf24@5289 114 int vmx_setup_platform(struct vcpu *d, struct cpu_user_regs *regs)
iap10@3290 115 {
iap10@3290 116 int i;
iap10@3290 117 unsigned int n;
iap10@3290 118 unsigned long *p, mpfn, offset, addr;
iap10@3290 119 struct e820entry *e820p;
iap10@3290 120 unsigned long gpfn = 0;
iap10@3290 121
kaf24@5727 122 local_flush_tlb_pge();
kaf24@4683 123 regs->ebx = 0; /* Linux expects ebx to be 0 for boot proc */
iap10@3290 124
kaf24@4683 125 n = regs->ecx;
iap10@3290 126 if (n > 32) {
maf46@3855 127 VMX_DBG_LOG(DBG_LEVEL_1, "Too many e820 entries: %d", n);
iap10@3290 128 return -1;
iap10@3290 129 }
iap10@3290 130
kaf24@4683 131 addr = regs->edi;
iap10@3290 132 offset = (addr & ~PAGE_MASK);
iap10@3290 133 addr = round_pgdown(addr);
kaf24@5356 134
iap10@3707 135 mpfn = phys_to_machine_mapping(addr >> PAGE_SHIFT);
kaf24@5356 136 p = map_domain_page(mpfn);
iap10@3290 137
iap10@3290 138 e820p = (struct e820entry *) ((unsigned long) p + offset);
iap10@3290 139
maf46@3880 140 #ifndef NDEBUG
maf46@3880 141 print_e820_memory_map(e820p, n);
maf46@3880 142 #endif
maf46@3880 143
kaf24@5356 144 for ( i = 0; i < n; i++ )
kaf24@5356 145 {
kaf24@5356 146 if ( e820p[i].type == E820_SHARED_PAGE )
kaf24@5356 147 {
iap10@3290 148 gpfn = (e820p[i].addr >> PAGE_SHIFT);
iap10@3290 149 break;
iap10@3290 150 }
iap10@3290 151 }
iap10@3290 152
kaf24@5356 153 if ( gpfn == 0 )
kaf24@5356 154 {
kaf24@5356 155 unmap_domain_page(p);
iap10@3290 156 return -1;
iap10@3290 157 }
iap10@3290 158
kaf24@5356 159 unmap_domain_page(p);
iap10@3748 160
iap10@3748 161 /* Initialise shared page */
kaf24@5356 162 mpfn = phys_to_machine_mapping(gpfn);
kaf24@5356 163 p = map_domain_page(mpfn);
arun@5608 164 d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p;
arun@5608 165
arun@5615 166 VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d->domain));
arun@5615 167
arun@5608 168 clear_bit(iopacket_port(d->domain),
arun@5608 169 &d->domain->shared_info->evtchn_mask[0]);
iap10@3290 170
iap10@3290 171 return 0;
iap10@3290 172 }
iap10@3290 173
kaf24@5289 174 void vmx_do_launch(struct vcpu *v)
iap10@3290 175 {
iap10@3290 176 /* Update CR3, GDT, LDT, TR */
iap10@3290 177 unsigned int tr, cpu, error = 0;
iap10@3290 178 struct host_execution_env host_env;
iap10@3290 179 struct Xgt_desc_struct desc;
kaf24@4633 180 unsigned long pfn = 0;
iap10@3290 181 struct pfn_info *page;
kaf24@4923 182 struct cpu_user_regs *regs = guest_cpu_user_regs();
iap10@3290 183
cl349@4856 184 vmx_stts();
cl349@4856 185
kaf24@4633 186 cpu = smp_processor_id();
iap10@3290 187
iap10@3290 188 page = (struct pfn_info *) alloc_domheap_page(NULL);
iap10@3290 189 pfn = (unsigned long) (page - frame_table);
iap10@3290 190
kaf24@5289 191 vmx_setup_platform(v, regs);
iap10@3290 192
kaf24@5820 193 __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory");
kaf24@5820 194 host_env.idtr_limit = desc.size;
kaf24@5820 195 host_env.idtr_base = desc.address;
kaf24@5820 196 error |= __vmwrite(HOST_IDTR_BASE, host_env.idtr_base);
kaf24@5820 197
arun@4585 198 __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&desc) : "memory");
iap10@3290 199 host_env.gdtr_limit = desc.size;
iap10@3290 200 host_env.gdtr_base = desc.address;
iap10@3290 201 error |= __vmwrite(HOST_GDTR_BASE, host_env.gdtr_base);
iap10@3290 202
iap10@3290 203 error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
iap10@3290 204 error |= __vmwrite(GUEST_LDTR_BASE, 0);
iap10@3290 205 error |= __vmwrite(GUEST_LDTR_LIMIT, 0);
iap10@3290 206
arun@4585 207 __asm__ __volatile__ ("str (%0) \n" :: "a"(&tr) : "memory");
iap10@3290 208 host_env.tr_selector = tr;
iap10@3290 209 host_env.tr_limit = sizeof(struct tss_struct);
iap10@3290 210 host_env.tr_base = (unsigned long) &init_tss[cpu];
iap10@3290 211
iap10@3290 212 error |= __vmwrite(HOST_TR_SELECTOR, host_env.tr_selector);
iap10@3290 213 error |= __vmwrite(HOST_TR_BASE, host_env.tr_base);
iap10@3290 214 error |= __vmwrite(GUEST_TR_BASE, 0);
iap10@3290 215 error |= __vmwrite(GUEST_TR_LIMIT, 0xff);
iap10@3290 216
kaf24@5289 217 __vmwrite(GUEST_CR3, pagetable_get_paddr(v->arch.guest_table));
kaf24@5289 218 __vmwrite(HOST_CR3, pagetable_get_paddr(v->arch.monitor_table));
kaf24@5414 219 __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
iap10@3290 220
kaf24@5289 221 v->arch.schedule_tail = arch_vmx_do_resume;
iap10@3290 222 }
iap10@3290 223
iap10@3290 224 /*
iap10@3290 225 * Initially set the same environement as host.
iap10@3290 226 */
iap10@3290 227 static inline int
kaf24@4683 228 construct_init_vmcs_guest(struct cpu_user_regs *regs,
kaf24@4683 229 struct vcpu_guest_context *ctxt,
iap10@3290 230 struct host_execution_env *host_env)
iap10@3290 231 {
iap10@3290 232 int error = 0;
iap10@3290 233 union vmcs_arbytes arbytes;
iap10@3290 234 unsigned long dr7;
iap10@3290 235 unsigned long eflags, shadow_cr;
iap10@3290 236
iap10@3290 237 /* MSR */
iap10@3290 238 error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0);
iap10@3290 239 error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0);
iap10@3290 240
iap10@3290 241 error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
iap10@3290 242 error |= __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
iap10@3290 243 error |= __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
iap10@3290 244 /* interrupt */
iap10@3290 245 error |= __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
iap10@3290 246 /* mask */
kaf24@5658 247 error |= __vmwrite(CR0_GUEST_HOST_MASK, -1UL);
kaf24@5658 248 error |= __vmwrite(CR4_GUEST_HOST_MASK, -1UL);
iap10@3290 249
iap10@3290 250 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0);
iap10@3290 251 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0);
iap10@3290 252
iap10@3290 253 /* TSC */
iap10@3290 254 error |= __vmwrite(TSC_OFFSET, 0);
iap10@3290 255 error |= __vmwrite(CR3_TARGET_COUNT, 0);
iap10@3290 256
iap10@3290 257 /* Guest Selectors */
kaf24@4683 258 error |= __vmwrite(GUEST_CS_SELECTOR, regs->cs);
kaf24@4683 259 error |= __vmwrite(GUEST_ES_SELECTOR, regs->es);
kaf24@4683 260 error |= __vmwrite(GUEST_SS_SELECTOR, regs->ss);
kaf24@4683 261 error |= __vmwrite(GUEST_DS_SELECTOR, regs->ds);
kaf24@4683 262 error |= __vmwrite(GUEST_FS_SELECTOR, regs->fs);
kaf24@4683 263 error |= __vmwrite(GUEST_GS_SELECTOR, regs->gs);
iap10@3290 264
iap10@3290 265 /* Guest segment Limits */
iap10@3290 266 error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
iap10@3290 267 error |= __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT);
iap10@3290 268 error |= __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT);
iap10@3290 269 error |= __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT);
iap10@3290 270 error |= __vmwrite(GUEST_FS_LIMIT, GUEST_SEGMENT_LIMIT);
iap10@3290 271 error |= __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT);
iap10@3290 272
iap10@3290 273 error |= __vmwrite(GUEST_IDTR_LIMIT, host_env->idtr_limit);
iap10@3290 274
iap10@3290 275 /* AR bytes */
iap10@3290 276 arbytes.bytes = 0;
iap10@3290 277 arbytes.fields.seg_type = 0x3; /* type = 3 */
iap10@3290 278 arbytes.fields.s = 1; /* code or data, i.e. not system */
iap10@3290 279 arbytes.fields.dpl = 0; /* DPL = 3 */
iap10@3290 280 arbytes.fields.p = 1; /* segment present */
iap10@3290 281 arbytes.fields.default_ops_size = 1; /* 32-bit */
iap10@3290 282 arbytes.fields.g = 1;
iap10@3290 283 arbytes.fields.null_bit = 0; /* not null */
iap10@3290 284
iap10@3290 285 error |= __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes);
iap10@3290 286 error |= __vmwrite(GUEST_SS_AR_BYTES, arbytes.bytes);
iap10@3290 287 error |= __vmwrite(GUEST_DS_AR_BYTES, arbytes.bytes);
iap10@3290 288 error |= __vmwrite(GUEST_FS_AR_BYTES, arbytes.bytes);
iap10@3290 289 error |= __vmwrite(GUEST_GS_AR_BYTES, arbytes.bytes);
iap10@3290 290
iap10@3290 291 arbytes.fields.seg_type = 0xb; /* type = 0xb */
iap10@3290 292 error |= __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes);
iap10@3290 293
kaf24@4683 294 error |= __vmwrite(GUEST_GDTR_BASE, regs->edx);
kaf24@4683 295 regs->edx = 0;
kaf24@4683 296 error |= __vmwrite(GUEST_GDTR_LIMIT, regs->eax);
kaf24@4683 297 regs->eax = 0;
iap10@3290 298
iap10@3290 299 arbytes.fields.s = 0; /* not code or data segement */
iap10@3290 300 arbytes.fields.seg_type = 0x2; /* LTD */
iap10@3290 301 arbytes.fields.default_ops_size = 0; /* 16-bit */
iap10@3290 302 arbytes.fields.g = 0;
iap10@3290 303 error |= __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes);
iap10@3290 304
iap10@3290 305 arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */
iap10@3290 306 error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
iap10@3290 307
iap10@3290 308 error |= __vmwrite(GUEST_CR0, host_env->cr0); /* same CR0 */
iap10@3290 309
iap10@3290 310 /* Initally PG, PE are not set*/
iap10@3290 311 shadow_cr = host_env->cr0;
arun@5186 312 shadow_cr &= ~X86_CR0_PG;
iap10@3290 313 error |= __vmwrite(CR0_READ_SHADOW, shadow_cr);
kaf24@3755 314 /* CR3 is set in vmx_final_setup_guest */
kaf24@5658 315 #ifdef __x86_64__
kaf24@5727 316 error |= __vmwrite(GUEST_CR4, host_env->cr4 & ~X86_CR4_PSE);
kaf24@5658 317 #else
iap10@3290 318 error |= __vmwrite(GUEST_CR4, host_env->cr4);
kaf24@5658 319 #endif
iap10@3290 320 shadow_cr = host_env->cr4;
kaf24@5658 321
kaf24@5658 322 #ifdef __x86_64__
kaf24@5658 323 shadow_cr &= ~(X86_CR4_PGE | X86_CR4_VMXE | X86_CR4_PAE);
kaf24@5658 324 #else
iap10@3290 325 shadow_cr &= ~(X86_CR4_PGE | X86_CR4_VMXE);
kaf24@5658 326 #endif
iap10@3290 327 error |= __vmwrite(CR4_READ_SHADOW, shadow_cr);
iap10@3290 328
iap10@3290 329 error |= __vmwrite(GUEST_ES_BASE, host_env->ds_base);
iap10@3290 330 error |= __vmwrite(GUEST_CS_BASE, host_env->cs_base);
iap10@3290 331 error |= __vmwrite(GUEST_SS_BASE, host_env->ds_base);
iap10@3290 332 error |= __vmwrite(GUEST_DS_BASE, host_env->ds_base);
iap10@3290 333 error |= __vmwrite(GUEST_FS_BASE, host_env->ds_base);
iap10@3290 334 error |= __vmwrite(GUEST_GS_BASE, host_env->ds_base);
iap10@3290 335 error |= __vmwrite(GUEST_IDTR_BASE, host_env->idtr_base);
iap10@3290 336
kaf24@5414 337 error |= __vmwrite(GUEST_RSP, regs->esp);
kaf24@5414 338 error |= __vmwrite(GUEST_RIP, regs->eip);
iap10@3290 339
kaf24@4683 340 eflags = regs->eflags & ~VMCS_EFLAGS_RESERVED_0; /* clear 0s */
iap10@3290 341 eflags |= VMCS_EFLAGS_RESERVED_1; /* set 1s */
iap10@3290 342
kaf24@5414 343 error |= __vmwrite(GUEST_RFLAGS, eflags);
iap10@3290 344
iap10@3290 345 error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
iap10@3290 346 __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
iap10@3290 347 error |= __vmwrite(GUEST_DR7, dr7);
kaf24@5414 348 error |= __vmwrite(VMCS_LINK_POINTER, 0xffffffff);
kaf24@5414 349 error |= __vmwrite(VMCS_LINK_POINTER_HIGH, 0xffffffff);
iap10@3290 350
iap10@3290 351 return error;
iap10@3290 352 }
iap10@3290 353
iap10@3290 354 static inline int construct_vmcs_host(struct host_execution_env *host_env)
iap10@3290 355 {
iap10@3290 356 int error = 0;
iap10@3290 357 unsigned long crn;
iap10@3290 358
iap10@3290 359 /* Host Selectors */
iap10@3290 360 host_env->ds_selector = __HYPERVISOR_DS;
iap10@3290 361 error |= __vmwrite(HOST_ES_SELECTOR, host_env->ds_selector);
iap10@3290 362 error |= __vmwrite(HOST_SS_SELECTOR, host_env->ds_selector);
iap10@3290 363 error |= __vmwrite(HOST_DS_SELECTOR, host_env->ds_selector);
kaf24@5658 364 #if defined (__i386__)
iap10@3290 365 error |= __vmwrite(HOST_FS_SELECTOR, host_env->ds_selector);
iap10@3290 366 error |= __vmwrite(HOST_GS_SELECTOR, host_env->ds_selector);
kaf24@5658 367 error |= __vmwrite(HOST_FS_BASE, host_env->ds_base);
kaf24@5658 368 error |= __vmwrite(HOST_GS_BASE, host_env->ds_base);
iap10@3290 369
kaf24@5658 370 #else
kaf24@5658 371 rdmsrl(MSR_FS_BASE, host_env->fs_base);
kaf24@5658 372 rdmsrl(MSR_GS_BASE, host_env->gs_base);
kaf24@5658 373 error |= __vmwrite(HOST_FS_BASE, host_env->fs_base);
kaf24@5658 374 error |= __vmwrite(HOST_GS_BASE, host_env->gs_base);
kaf24@5658 375
kaf24@5658 376 #endif
iap10@3290 377 host_env->cs_selector = __HYPERVISOR_CS;
iap10@3290 378 error |= __vmwrite(HOST_CS_SELECTOR, host_env->cs_selector);
iap10@3290 379
iap10@3290 380 host_env->ds_base = 0;
iap10@3290 381 host_env->cs_base = 0;
iap10@3290 382
kaf24@5193 383 __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : );
iap10@3290 384 host_env->cr0 = crn;
iap10@3290 385 error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
iap10@3290 386
iap10@3290 387 /* CR3 is set in vmx_final_setup_hostos */
kaf24@5193 388 __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
iap10@3290 389 host_env->cr4 = crn;
iap10@3290 390 error |= __vmwrite(HOST_CR4, crn);
kaf24@5820 391
kaf24@5414 392 error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
kaf24@5658 393 #ifdef __x86_64__
kaf24@5658 394 /* TBD: support cr8 for 64-bit guest */
kaf24@5658 395 __vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0);
kaf24@5658 396 __vmwrite(TPR_THRESHOLD, 0);
kaf24@5658 397 __vmwrite(SECONDARY_VM_EXEC_CONTROL, 0);
kaf24@5658 398 #endif
iap10@3290 399
iap10@3290 400 return error;
iap10@3290 401 }
iap10@3290 402
iap10@3290 403 /*
iap10@3290 404 * Need to extend to support full virtualization.
iap10@3290 405 * The variable use_host_env indicates if the new VMCS needs to use
iap10@3290 406 * the same setups as the host has (xenolinux).
iap10@3290 407 */
iap10@3290 408
iap10@3290 409 int construct_vmcs(struct arch_vmx_struct *arch_vmx,
kaf24@4683 410 struct cpu_user_regs *regs,
kaf24@4683 411 struct vcpu_guest_context *ctxt,
iap10@3290 412 int use_host_env)
iap10@3290 413 {
iap10@3290 414 int error;
iap10@3290 415 u64 vmcs_phys_ptr;
iap10@3290 416
iap10@3290 417 struct host_execution_env host_env;
iap10@3290 418
iap10@3290 419 if (use_host_env != VMCS_USE_HOST_ENV)
iap10@3290 420 return -EINVAL;
iap10@3290 421
iap10@3290 422 memset(&host_env, 0, sizeof(struct host_execution_env));
iap10@3290 423
iap10@3290 424 vmcs_phys_ptr = (u64) virt_to_phys(arch_vmx->vmcs);
iap10@3290 425
iap10@3290 426 if ((error = __vmpclear (vmcs_phys_ptr))) {
iap10@3290 427 printk("construct_vmcs: VMCLEAR failed\n");
iap10@3290 428 return -EINVAL;
iap10@3290 429 }
iap10@3290 430 if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) {
iap10@3290 431 printk("construct_vmcs: load_vmcs failed: VMCS = %lx\n",
iap10@3290 432 (unsigned long) vmcs_phys_ptr);
iap10@3290 433 return -EINVAL;
iap10@3290 434 }
iap10@3290 435 if ((error = construct_vmcs_controls())) {
iap10@3290 436 printk("construct_vmcs: construct_vmcs_controls failed\n");
iap10@3290 437 return -EINVAL;
iap10@3290 438 }
iap10@3290 439 /* host selectors */
iap10@3290 440 if ((error = construct_vmcs_host(&host_env))) {
iap10@3290 441 printk("construct_vmcs: construct_vmcs_host failed\n");
iap10@3290 442 return -EINVAL;
iap10@3290 443 }
iap10@3290 444 /* guest selectors */
kaf24@4683 445 if ((error = construct_init_vmcs_guest(regs, ctxt, &host_env))) {
iap10@3290 446 printk("construct_vmcs: construct_vmcs_guest failed\n");
iap10@3290 447 return -EINVAL;
iap10@3290 448 }
iap10@3290 449
iap10@3290 450 if ((error |= __vmwrite(EXCEPTION_BITMAP,
iap10@3290 451 MONITOR_DEFAULT_EXCEPTION_BITMAP))) {
iap10@3290 452 printk("construct_vmcs: setting Exception bitmap failed\n");
iap10@3290 453 return -EINVAL;
iap10@3290 454 }
iap10@3290 455
iap10@3290 456 return 0;
iap10@3290 457 }
iap10@3290 458
iap10@3290 459 int load_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
iap10@3290 460 {
iap10@3290 461 int error;
iap10@3290 462
iap10@3290 463 if ((error = __vmptrld(phys_ptr))) {
iap10@3290 464 clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
iap10@3290 465 return error;
iap10@3290 466 }
iap10@3290 467 set_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
iap10@3290 468 return 0;
iap10@3290 469 }
iap10@3290 470
iap10@3290 471 int store_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
iap10@3290 472 {
iap10@3290 473 /* take the current VMCS */
iap10@3290 474 __vmptrst(phys_ptr);
iap10@3290 475 clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
iap10@3290 476 return 0;
iap10@3290 477 }
iap10@3290 478
iap10@3290 479 void vm_launch_fail(unsigned long eflags)
iap10@3290 480 {
arun@5382 481 __vmx_bug(guest_cpu_user_regs());
iap10@3290 482 }
iap10@3290 483
iap10@3290 484 void vm_resume_fail(unsigned long eflags)
iap10@3290 485 {
arun@5382 486 __vmx_bug(guest_cpu_user_regs());
iap10@3290 487 }
iap10@3290 488
mafetter@3717 489 #endif /* CONFIG_VMX */
kaf24@3914 490
kaf24@3914 491 /*
kaf24@3914 492 * Local variables:
kaf24@3914 493 * mode: C
kaf24@3914 494 * c-set-style: "BSD"
kaf24@3914 495 * c-basic-offset: 4
kaf24@3914 496 * tab-width: 4
kaf24@3914 497 * indent-tabs-mode: nil
kaf24@3988 498 * End:
kaf24@3914 499 */