xen-vtx-unstable

annotate xen/arch/x86/vmx_vmcs.c @ 5608:6daf7357a9df

bitkeeper revision 1.1773 (42c3a841nLib9kdSmthr05jouqiNeg)

[PATCH] Device model cleanup.

Device model cleanup.

- Single config file for xen and device models
(Shell script doesn't source xmdefconfig anymore)
- No more device-model shell script by default. You can
have one if needed (qemu-dm.debug)
- All logic in the script device-model is moved to python
- $DISPLAY is passed from xm to xend
- Don't fork vncviewer on dryruns
- Add support for killing device models on domain destroy
- info vmxiopage command added to the monitor
- Refactor shared io page into global and per vcpu state
- Remove the hard coding of IOPACKET_PORT
- move the virtual_platform_def up to domain struct from vcpu
- xm create -n:

(vm
(name ExampleVMXDomain)
(memory 128)
(ssidref -1)
(image
(vmx
(kernel /usr/lib/xen/boot/vmxloader)
(root '/dev/hda1 ro')
(vcpus 1)
)
)
(memmap )
(device_model /tmp/foo)
(hda /var/images/min-el3-i386.img)
(hdb )
(hdc )
(hdd )
(cdrom )
(boot c)
(fda )
(fdb )
(localtime 0)
(serial )
(macaddr )
(stdvga 0)
(isa 0)
(nographic 0)
(vnc 0)
(sdl 0)
(display localhost:10.0)
)

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