diff -r 6524e02edbeb xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Wed Feb 07 16:53:01 2007 -0800 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Thu Feb 08 15:35:28 2007 +0800 @@ -288,72 +288,15 @@ static void vmx_set_host_env(struct vcpu (unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code); } -static void construct_vmcs(struct vcpu *v) -{ - unsigned long cr0, cr4; +static inline void init_vmcs_guest_area(struct vcpu *v) +{ + unsigned long cr4; union vmcs_arbytes arbytes; - - vmx_vmcs_enter(v); v->arch.hvm_vmx.cpu_cr2 = 0; v->arch.hvm_vmx.cpu_cr3 = 0; memset(&v->arch.hvm_vmx.msr_state, 0, sizeof(v->arch.hvm_vmx.msr_state)); v->arch.hvm_vmx.vmxassist_enabled = 0; - - /* VMCS controls. */ - __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); - __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); - __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); - __vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control); - v->arch.hvm_vcpu.u.vmx.exec_control = vmx_cpu_based_exec_control; - - /* I/O access bitmap. */ - __vmwrite(IO_BITMAP_A, virt_to_maddr(hvm_io_bitmap)); - __vmwrite(IO_BITMAP_B, virt_to_maddr(hvm_io_bitmap + PAGE_SIZE)); - - /* Host data selectors. */ - __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS); - __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS); - __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS); -#if defined(__i386__) - __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS); - __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS); - __vmwrite(HOST_FS_BASE, 0); - __vmwrite(HOST_GS_BASE, 0); -#elif defined(__x86_64__) - { - unsigned long msr; - rdmsrl(MSR_FS_BASE, msr); __vmwrite(HOST_FS_BASE, msr); - rdmsrl(MSR_GS_BASE, msr); __vmwrite(HOST_GS_BASE, msr); - } -#endif - - /* Host control registers. */ - __vmwrite(HOST_CR0, read_cr0()); - __vmwrite(HOST_CR4, read_cr4()); - - /* Host CS:RIP. */ - __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS); - __vmwrite(HOST_RIP, (unsigned long)vmx_asm_vmexit_handler); - - /* MSR intercepts. */ - __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0); - __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0); - __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); - __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); - __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); - - __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); - - __vmwrite(CR0_GUEST_HOST_MASK, ~0UL); - __vmwrite(CR4_GUEST_HOST_MASK, ~0UL); - - __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); - __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); - - __vmwrite(CR3_TARGET_COUNT, 0); - - __vmwrite(GUEST_ACTIVITY_STATE, 0); /* Guest segment bases. */ __vmwrite(GUEST_ES_BASE, 0); @@ -405,20 +348,24 @@ static void construct_vmcs(struct vcpu * arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */ __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes); + __vmwrite(GUEST_LDTR_SELECTOR, 0); + __vmwrite(GUEST_LDTR_BASE, 0); + __vmwrite(GUEST_LDTR_LIMIT, 0); + + __vmwrite(GUEST_TR_BASE, 0); + __vmwrite(GUEST_TR_LIMIT, 0xff); + __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); __vmwrite(GUEST_DR7, 0); - __vmwrite(VMCS_LINK_POINTER, ~0UL); -#if defined(__i386__) - __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL); -#endif - - __vmwrite(EXCEPTION_BITMAP, MONITOR_DEFAULT_EXCEPTION_BITMAP); + + __vmwrite(CR3_TARGET_COUNT, 0); + __vmwrite(GUEST_ACTIVITY_STATE, 0); /* Guest CR0. */ - cr0 = read_cr0(); - v->arch.hvm_vmx.cpu_cr0 = cr0; + v->arch.hvm_vmx.cpu_cr0 = read_cr0(); __vmwrite(GUEST_CR0, v->arch.hvm_vmx.cpu_cr0); - v->arch.hvm_vmx.cpu_shadow_cr0 = cr0 & ~(X86_CR0_PG | X86_CR0_TS); + v->arch.hvm_vmx.cpu_shadow_cr0 = + v->arch.hvm_vmx.cpu_cr0 & ~(X86_CR0_PG | X86_CR0_TS); __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0); /* Guest CR4. */ @@ -428,23 +375,86 @@ static void construct_vmcs(struct vcpu * cr4 & ~(X86_CR4_PGE | X86_CR4_VMXE | X86_CR4_PAE); __vmwrite(CR4_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr4); -#ifdef __x86_64__ + __vmwrite(VMCS_LINK_POINTER, ~0UL); +#if defined(__i386__) + __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL); +#endif +} + +static inline void init_vmcs_host_area(void) +{ + /* Host data selectors. */ + __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS); + __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS); + __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS); +#if defined(__i386__) + __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS); + __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS); + __vmwrite(HOST_FS_BASE, 0); + __vmwrite(HOST_GS_BASE, 0); +#elif defined(__x86_64__) + { + unsigned long msr; + rdmsrl(MSR_FS_BASE, msr); __vmwrite(HOST_FS_BASE, msr); + rdmsrl(MSR_GS_BASE, msr); __vmwrite(HOST_GS_BASE, msr); + } +#endif + + /* Host control registers. */ + __vmwrite(HOST_CR0, read_cr0()); + __vmwrite(HOST_CR4, read_cr4()); + + /* Host CS:RIP. */ + __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS); + __vmwrite(HOST_RIP, (unsigned long)vmx_asm_vmexit_handler); +} + +static inline void init_vmcs_vmx_controls(struct vcpu *v) +{ + v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control; +#ifdef __x86_64__ /* VLAPIC TPR optimisation. */ - v->arch.hvm_vcpu.u.vmx.exec_control |= CPU_BASED_TPR_SHADOW; - v->arch.hvm_vcpu.u.vmx.exec_control &= + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, page_to_maddr(vcpu_vlapic(v)->regs_page)); + __vmwrite(TPR_THRESHOLD, 0); + v->arch.hvm_vmx.exec_control |= CPU_BASED_TPR_SHADOW; + v->arch.hvm_vmx.exec_control &= ~(CPU_BASED_CR8_STORE_EXITING | CPU_BASED_CR8_LOAD_EXITING); - __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vcpu.u.vmx.exec_control); - __vmwrite(VIRTUAL_APIC_PAGE_ADDR, - page_to_maddr(vcpu_vlapic(v)->regs_page)); - __vmwrite(TPR_THRESHOLD, 0); #endif - - __vmwrite(GUEST_LDTR_SELECTOR, 0); - __vmwrite(GUEST_LDTR_BASE, 0); - __vmwrite(GUEST_LDTR_LIMIT, 0); - - __vmwrite(GUEST_TR_BASE, 0); - __vmwrite(GUEST_TR_LIMIT, 0xff); + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); + + __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); + __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); + __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); + + __vmwrite(EXCEPTION_BITMAP, MONITOR_DEFAULT_EXCEPTION_BITMAP); + + __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); + __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); + + /* I/O access bitmap. */ + __vmwrite(IO_BITMAP_A, virt_to_maddr(hvm_io_bitmap)); + __vmwrite(IO_BITMAP_B, virt_to_maddr(hvm_io_bitmap + PAGE_SIZE)); + + /* MSR intercepts. */ + __vmwrite(CR0_GUEST_HOST_MASK, ~0UL); + __vmwrite(CR4_GUEST_HOST_MASK, ~0UL); + + __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0); + __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0); + __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); + __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); + __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); + + __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); +} + +static void initialise_vmcs(struct vcpu *v) +{ + vmx_vmcs_enter(v); + + init_vmcs_guest_area(v); + init_vmcs_host_area(); + init_vmcs_vmx_controls(v); vmx_vmcs_exit(v); @@ -461,7 +471,7 @@ int vmx_create_vmcs(struct vcpu *v) __vmx_clear_vmcs(v); } - construct_vmcs(v); + initialise_vmcs(v); return 0; }