[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vms: A cleanup to vmx.c:
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1183802937 -3600 # Node ID 41c8284cfc0cfaa773771a2d9be85cad1fbd4079 # Parent 8528da5be577d0eab1dfc8a8a85d07e041a1f758 vms: A cleanup to vmx.c: 1) move some functions from vmx.h to vmx.c, since they are private. 2) adjust vmx_set_cr0 handling. 3) majorly coding style tidying. Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/vmx/vmx.c | 426 ++++++++++++++++++++------------------ xen/include/asm-x86/hvm/vmx/vmx.h | 22 - 2 files changed, 230 insertions(+), 218 deletions(-) diff -r 8528da5be577 -r 41c8284cfc0c xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sat Jul 07 10:31:15 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sat Jul 07 11:08:57 2007 +0100 @@ -98,7 +98,62 @@ static void vmx_vcpu_destroy(struct vcpu vmx_destroy_vmcs(v); } +static int vmx_paging_enabled(struct vcpu *v) +{ + unsigned long cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; + return (cr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG); +} + +static int vmx_pgbit_test(struct vcpu *v) +{ + unsigned long cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; + return cr0 & X86_CR0_PG; +} + +static int vmx_pae_enabled(struct vcpu *v) +{ + unsigned long cr4 = v->arch.hvm_vmx.cpu_shadow_cr4; + return vmx_paging_enabled(v) && (cr4 & X86_CR4_PAE); +} + +static int vmx_nx_enabled(struct vcpu *v) +{ + return v->arch.hvm_vmx.efer & EFER_NX; +} + #ifdef __x86_64__ + +static int vmx_lme_is_set(struct vcpu *v) +{ + return v->arch.hvm_vmx.efer & EFER_LME; +} + +static int vmx_long_mode_enabled(struct vcpu *v) +{ + return v->arch.hvm_vmx.efer & EFER_LMA; +} + +static void vmx_enable_long_mode(struct vcpu *v) +{ + unsigned long vm_entry_value; + + vm_entry_value = __vmread(VM_ENTRY_CONTROLS); + vm_entry_value |= VM_ENTRY_IA32E_MODE; + __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); + + v->arch.hvm_vmx.efer |= EFER_LMA; +} + +static void vmx_disable_long_mode(struct vcpu *v) +{ + unsigned long vm_entry_value; + + vm_entry_value = __vmread(VM_ENTRY_CONTROLS); + vm_entry_value &= ~VM_ENTRY_IA32E_MODE; + __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); + + v->arch.hvm_vmx.efer &= ~EFER_LMA; +} static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state); @@ -123,7 +178,7 @@ static void vmx_save_host_msrs(void) set_bit(VMX_INDEX_MSR_ ## address, &host_msr_state->flags); \ break -static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) +static int long_mode_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; u32 ecx = regs->ecx; @@ -181,7 +236,7 @@ static inline int long_mode_do_msr_read( return 1; } -static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) +static int long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); u32 ecx = regs->ecx; @@ -300,6 +355,7 @@ static void vmx_restore_host_msrs(void) wrmsrl(msr_index[i], host_msr_state->msrs[i]); clear_bit(i, &host_msr_state->flags); } + if ( cpu_has_nx && !(read_efer() & EFER_NX) ) write_efer(read_efer() | EFER_NX); } @@ -323,7 +379,8 @@ static void vmx_restore_guest_msrs(struc guest_flags = guest_msr_state->flags; - while ( guest_flags ) { + while ( guest_flags ) + { i = find_first_set_bit(guest_flags); HVM_DBG_LOG(DBG_LEVEL_2, @@ -334,17 +391,26 @@ static void vmx_restore_guest_msrs(struc clear_bit(i, &guest_flags); } - if ( (v->arch.hvm_vmx.efer ^ read_efer()) & (EFER_NX|EFER_SCE) ) + if ( (v->arch.hvm_vmx.efer ^ read_efer()) & (EFER_NX | EFER_SCE) ) { HVM_DBG_LOG(DBG_LEVEL_2, "restore guest's EFER with value %lx", v->arch.hvm_vmx.efer); - write_efer((read_efer() & ~(EFER_NX|EFER_SCE)) | - (v->arch.hvm_vmx.efer & (EFER_NX|EFER_SCE))); + write_efer((read_efer() & ~(EFER_NX | EFER_SCE)) | + (v->arch.hvm_vmx.efer & (EFER_NX | EFER_SCE))); } } #else /* __i386__ */ + +static int vmx_lme_is_set(struct vcpu *v) +{ return 0; } +static int vmx_long_mode_enabled(struct vcpu *v) +{ return 0; } +static void vmx_enable_long_mode(struct vcpu *v) +{ BUG(); } +static void vmx_disable_long_mode(struct vcpu *v) +{ BUG(); } #define vmx_save_host_msrs() ((void)0) @@ -368,7 +434,7 @@ static void vmx_restore_guest_msrs(struc } } -static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) +static int long_mode_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; struct vcpu *v = current; @@ -388,7 +454,7 @@ static inline int long_mode_do_msr_read( return 1; } -static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) +static int long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = regs->eax | ((u64)regs->edx << 32); struct vcpu *v = current; @@ -426,7 +492,24 @@ static inline int long_mode_do_msr_write #define savedebug(_v,_reg) \ __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg])) -static inline void vmx_save_dr(struct vcpu *v) +static int vmx_guest_x86_mode(struct vcpu *v) +{ + unsigned int cs_ar_bytes; + + ASSERT(v == current); + + if ( unlikely(!(v->arch.hvm_vmx.cpu_shadow_cr0 & X86_CR0_PE)) ) + return 0; + if ( unlikely(__vmread(GUEST_RFLAGS) & X86_EFLAGS_VM) ) + return 1; + cs_ar_bytes = __vmread(GUEST_CS_AR_BYTES); + if ( vmx_long_mode_enabled(v) && + likely(cs_ar_bytes & X86_SEG_AR_CS_LM_ACTIVE) ) + return 8; + return (likely(cs_ar_bytes & X86_SEG_AR_DEF_OP_SIZE) ? 4 : 2); +} + +static void vmx_save_dr(struct vcpu *v) { if ( !v->arch.hvm_vcpu.flag_dr_dirty ) return; @@ -444,7 +527,7 @@ static inline void vmx_save_dr(struct vc v->arch.guest_context.debugreg[7] = __vmread(GUEST_DR7); } -static inline void __restore_debug_registers(struct vcpu *v) +static void __restore_debug_registers(struct vcpu *v) { loaddebug(&v->arch.guest_context, 0); loaddebug(&v->arch.guest_context, 1); @@ -455,9 +538,11 @@ static inline void __restore_debug_regis /* DR7 is loaded from the VMCS. */ } -int vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) -{ +void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) +{ uint32_t ev; + + vmx_vmcs_enter(v); c->rip = __vmread(GUEST_RIP); c->rsp = __vmread(GUEST_RSP); @@ -468,11 +553,11 @@ int vmx_vmcs_save(struct vcpu *v, struct c->cr3 = v->arch.hvm_vmx.cpu_cr3; c->cr4 = v->arch.hvm_vmx.cpu_shadow_cr4; + c->msr_efer = v->arch.hvm_vmx.efer; + #ifdef HVM_DEBUG_SUSPEND - printk("vmx_vmcs_save: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", - c->cr3, - c->cr0, - c->cr4); + printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", + __func__, c->cr3, c->cr0, c->cr4); #endif c->idtr_limit = __vmread(GUEST_IDTR_LIMIT); @@ -525,29 +610,31 @@ int vmx_vmcs_save(struct vcpu *v, struct c->sysenter_esp = __vmread(GUEST_SYSENTER_ESP); c->sysenter_eip = __vmread(GUEST_SYSENTER_EIP); - /* Save any event/interrupt that was being injected when we last - * exited. IDT_VECTORING_INFO_FIELD has priority, as anything in + /* + * Save any event/interrupt that was being injected when we last + * exited. IDT_VECTORING_INFO_FIELD has priority, as anything in * VM_ENTRY_INTR_INFO_FIELD is either a fault caused by the first * event, which will happen the next time, or an interrupt, which we - * never inject when IDT_VECTORING_INFO_FIELD is valid.*/ - if ( (ev = __vmread(IDT_VECTORING_INFO_FIELD)) & INTR_INFO_VALID_MASK ) + * never inject when IDT_VECTORING_INFO_FIELD is valid. + */ + if ( (ev = __vmread(IDT_VECTORING_INFO_FIELD)) & INTR_INFO_VALID_MASK ) { c->pending_event = ev; c->error_code = __vmread(IDT_VECTORING_ERROR_CODE); } - else if ( (ev = __vmread(VM_ENTRY_INTR_INFO_FIELD)) - & INTR_INFO_VALID_MASK ) + else if ( (ev = __vmread(VM_ENTRY_INTR_INFO_FIELD)) & + INTR_INFO_VALID_MASK ) { c->pending_event = ev; c->error_code = __vmread(VM_ENTRY_EXCEPTION_ERROR_CODE); } - else + else { c->pending_event = 0; c->error_code = 0; } - return 1; + vmx_vmcs_exit(v); } int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) @@ -560,47 +647,47 @@ int vmx_vmcs_restore(struct vcpu *v, str __vmwrite(GUEST_RSP, c->rsp); __vmwrite(GUEST_RFLAGS, c->rflags); - v->arch.hvm_vmx.cpu_cr0 = (c->cr0 | X86_CR0_PE | X86_CR0_PG - | X86_CR0_NE | X86_CR0_WP | X86_CR0_ET); + v->arch.hvm_vmx.cpu_cr0 = (c->cr0 | X86_CR0_PE | X86_CR0_PG | + X86_CR0_NE | X86_CR0_WP | X86_CR0_ET); __vmwrite(GUEST_CR0, v->arch.hvm_vmx.cpu_cr0); v->arch.hvm_vmx.cpu_shadow_cr0 = c->cr0; __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0); v->arch.hvm_vmx.cpu_cr2 = c->cr2; + v->arch.hvm_vmx.efer = c->msr_efer; + #ifdef HVM_DEBUG_SUSPEND - printk("vmx_vmcs_restore: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", - c->cr3, - c->cr0, - c->cr4); + printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", + __func__, c->cr3, c->cr0, c->cr4); #endif - if (!vmx_paging_enabled(v)) { - printk("vmx_vmcs_restore: paging not enabled."); + if ( !vmx_paging_enabled(v) ) + { + HVM_DBG_LOG(DBG_LEVEL_VMMU, "%s: paging not enabled.", __func__); goto skip_cr3; } - HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64, c->cr3); + HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 = %"PRIx64, c->cr3); /* current!=vcpu as not called by arch_vmx_do_launch */ mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT); - if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) { - goto bad_cr3; - } + if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) + { + gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64".\n", c->cr3); + vmx_vmcs_exit(v); + return -EINVAL; + } + old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); - if (old_base_mfn) + if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); + v->arch.hvm_vmx.cpu_cr3 = c->cr3; skip_cr3: -#if defined(__x86_64__) - if (vmx_long_mode_enabled(v)) { - unsigned long vm_entry_value; - vm_entry_value = __vmread(VM_ENTRY_CONTROLS); - vm_entry_value |= VM_ENTRY_IA32E_MODE; - __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); - } -#endif + if ( vmx_long_mode_enabled(v) ) + vmx_enable_long_mode(v); __vmwrite(GUEST_CR4, (c->cr4 | HVM_CR4_HOST_MASK)); v->arch.hvm_vmx.cpu_shadow_cr4 = c->cr4; @@ -662,53 +749,53 @@ int vmx_vmcs_restore(struct vcpu *v, str paging_update_paging_modes(v); - if ( c->pending_valid ) + if ( c->pending_valid ) { vmx_vmcs_enter(v); + gdprintk(XENLOG_INFO, "Re-injecting 0x%"PRIx32", 0x%"PRIx32"\n", c->pending_event, c->error_code); /* SVM uses type 3 ("Exception") for #OF and #BP; VMX uses type 6 */ - if ( c->pending_type == 3 - && (c->pending_vector == 3 || c->pending_vector == 4) ) + if ( (c->pending_type == 3) && + ((c->pending_vector == 3) || (c->pending_vector == 4)) ) c->pending_type = 6; - /* For software exceptions, we need to tell the hardware the + /* For software exceptions, we need to tell the hardware the * instruction length as well (hmmm). */ - if ( c->pending_type > 4 ) + if ( c->pending_type > 4 ) { - int addrbytes, ilen; - if ( (c->cs_arbytes & (1u<<13)) && (c->msr_efer & EFER_LMA) ) + int addrbytes, ilen; + if ( (c->cs_arbytes & X86_SEG_AR_CS_LM_ACTIVE) && + (c->msr_efer & EFER_LMA) ) addrbytes = 8; - else if ( (c->cs_arbytes & (1u<<14)) ) + else if ( c->cs_arbytes & X86_SEG_AR_DEF_OP_SIZE ) addrbytes = 4; - else + else addrbytes = 2; + ilen = hvm_instruction_length(c->rip, addrbytes); __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen); } /* Sanity check */ - if ( c->pending_type == 1 || c->pending_type > 6 - || c->pending_reserved != 0 ) + if ( (c->pending_type == 1) || (c->pending_type > 6) || + (c->pending_reserved != 0) ) { - gdprintk(XENLOG_ERR, "Invalid pending event 0x%"PRIx32"\n", + gdprintk(XENLOG_ERR, "Invalid pending event 0x%"PRIx32".\n", c->pending_event); return -EINVAL; } + /* Re-inject the exception */ __vmwrite(VM_ENTRY_INTR_INFO_FIELD, c->pending_event); __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, c->error_code); v->arch.hvm_vmx.vector_injected = 1; + vmx_vmcs_exit(v); } return 0; - - bad_cr3: - gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"", c->cr3); - vmx_vmcs_exit(v); - return -EINVAL; } #if defined(__x86_64__) && defined(HVM_DEBUG_SUSPEND) @@ -717,14 +804,14 @@ static void dump_msr_state(struct vmx_ms int i = 0; printk("**** msr state ****\n"); printk("shadow_gs=0x%lx, flags=0x%lx, msr_items:", m->shadow_gs, m->flags); - for (i = 0; i < VMX_MSR_COUNT; i++) + for ( i = 0; i < VMX_MSR_COUNT; i++ ) printk("0x%lx,", m->msrs[i]); printk("\n"); } #else #define dump_msr_state(m) ((void)0) #endif - + static void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) { #ifdef __x86_64__ @@ -741,10 +828,8 @@ static void vmx_save_cpu_state(struct vc data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK]; #endif - data->msr_efer = v->arch.hvm_vmx.efer; - data->tsc = hvm_get_guest_time(v); - + dump_msr_state(guest_state); } @@ -763,8 +848,6 @@ static void vmx_load_cpu_state(struct vc v->arch.hvm_vmx.shadow_gs = data->shadow_gs; #endif - v->arch.hvm_vmx.efer = data->msr_efer; - v->arch.hvm_vmx.vmxassist_enabled = !(data->cr0 & X86_CR0_PE); hvm_set_guest_time(v, data->tsc); @@ -776,16 +859,16 @@ static void vmx_save_vmcs_ctxt(struct vc static void vmx_save_vmcs_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) { vmx_save_cpu_state(v, ctxt); - vmx_vmcs_enter(v); vmx_vmcs_save(v, ctxt); - vmx_vmcs_exit(v); } static int vmx_load_vmcs_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) { vmx_load_cpu_state(v, ctxt); - if (vmx_vmcs_restore(v, ctxt)) { - printk("vmx_vmcs restore failed!\n"); + + if ( vmx_vmcs_restore(v, ctxt) ) + { + gdprintk(XENLOG_ERR, "vmx_vmcs restore failed!\n"); domain_crash(v->domain); return -EINVAL; } @@ -801,7 +884,7 @@ static int vmx_load_vmcs_ctxt(struct vcp */ #define DR7_ACTIVE_MASK 0xff -static inline void vmx_restore_dr(struct vcpu *v) +static void vmx_restore_dr(struct vcpu *v) { /* NB. __vmread() is not usable here, so we cannot read from the VMCS. */ if ( unlikely(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) ) @@ -915,11 +998,9 @@ static unsigned long vmx_get_segment_bas ASSERT(v == current); -#ifdef __x86_64__ if ( vmx_long_mode_enabled(v) && (__vmread(GUEST_CS_AR_BYTES) & X86_SEG_AR_CS_LM_ACTIVE) ) long_mode = 1; -#endif switch ( seg ) { @@ -1072,34 +1153,6 @@ static void vmx_init_hypercall_page(stru *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */ } -static int vmx_guest_x86_mode(struct vcpu *v) -{ - unsigned int cs_ar_bytes; - - ASSERT(v == current); - - if ( unlikely(!(v->arch.hvm_vmx.cpu_shadow_cr0 & X86_CR0_PE)) ) - return 0; - if ( unlikely(__vmread(GUEST_RFLAGS) & X86_EFLAGS_VM) ) - return 1; - cs_ar_bytes = __vmread(GUEST_CS_AR_BYTES); - if ( vmx_long_mode_enabled(v) && likely(cs_ar_bytes & - X86_SEG_AR_CS_LM_ACTIVE) ) - return 8; - return (likely(cs_ar_bytes & X86_SEG_AR_DEF_OP_SIZE) ? 4 : 2); -} - -static int vmx_pae_enabled(struct vcpu *v) -{ - unsigned long cr4 = v->arch.hvm_vmx.cpu_shadow_cr4; - return (vmx_paging_enabled(v) && (cr4 & X86_CR4_PAE)); -} - -static int vmx_nx_enabled(struct vcpu *v) -{ - return v->arch.hvm_vmx.efer & EFER_NX; -} - static int vmx_interrupts_enabled(struct vcpu *v, enum hvm_intack type) { unsigned long intr_shadow, eflags; @@ -1137,7 +1190,7 @@ static void vmx_update_guest_cr3(struct static void vmx_flush_guest_tlbs(void) { - /* No tagged TLB support on VMX yet. The fact that we're in Xen + /* No tagged TLB support on VMX yet. The fact that we're in Xen * at all means any guest will have a clean TLB when it's next run, * because VMRESUME will flush it for us. */ } @@ -1302,7 +1355,7 @@ static int __get_instruction_length(void return len; } -static void inline __update_guest_eip(unsigned long inst_len) +static void __update_guest_eip(unsigned long inst_len) { unsigned long x; @@ -1605,10 +1658,10 @@ static int vmx_str_pio_check_descriptor( } -static inline void vmx_str_pio_check_limit(u32 limit, unsigned int size, - u32 ar_bytes, unsigned long addr, - unsigned long base, int df, - unsigned long *count) +static void vmx_str_pio_check_limit(u32 limit, unsigned int size, + u32 ar_bytes, unsigned long addr, + unsigned long base, int df, + unsigned long *count) { unsigned long ea = addr - base; @@ -1664,10 +1717,10 @@ static inline void vmx_str_pio_check_lim } #ifdef __x86_64__ -static inline void vmx_str_pio_lm_check_limit(struct cpu_user_regs *regs, - unsigned int size, - unsigned long addr, - unsigned long *count) +static void vmx_str_pio_lm_check_limit(struct cpu_user_regs *regs, + unsigned int size, + unsigned long addr, + unsigned long *count) { if ( !is_canonical_address(addr) || !is_canonical_address(addr + size - 1) ) @@ -1693,12 +1746,12 @@ static inline void vmx_str_pio_lm_check_ } #endif -static inline void vmx_send_str_pio(struct cpu_user_regs *regs, - struct hvm_io_op *pio_opp, - unsigned long inst_len, unsigned int port, - int sign, unsigned int size, int dir, - int df, unsigned long addr, - unsigned long paddr, unsigned long count) +static void vmx_send_str_pio(struct cpu_user_regs *regs, + struct hvm_io_op *pio_opp, + unsigned long inst_len, unsigned int port, + int sign, unsigned int size, int dir, + int df, unsigned long addr, + unsigned long paddr, unsigned long count) { /* * Handle string pio instructions that cross pages or that @@ -1754,10 +1807,10 @@ static inline void vmx_send_str_pio(stru } } -static void vmx_str_pio_handler(unsigned long exit_qualification, - unsigned long inst_len, - struct cpu_user_regs *regs, - struct hvm_io_op *pio_opp) +static void vmx_do_str_pio(unsigned long exit_qualification, + unsigned long inst_len, + struct cpu_user_regs *regs, + struct hvm_io_op *pio_opp) { unsigned int port, size; int dir, df, vm86; @@ -1786,11 +1839,9 @@ static void vmx_str_pio_handler(unsigned sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1; ar_bytes = __vmread(GUEST_CS_AR_BYTES); -#ifdef __x86_64__ if ( vmx_long_mode_enabled(current) && (ar_bytes & X86_SEG_AR_CS_LM_ACTIVE) ) long_mode = 1; -#endif addr = __vmread(GUEST_LINEAR_ADDRESS); if ( test_bit(5, &exit_qualification) ) { /* "rep" prefix */ @@ -1874,7 +1925,7 @@ static void vmx_io_instruction(unsigned regs->cs, (unsigned long)regs->eip, exit_qualification); if ( test_bit(4, &exit_qualification) ) /* string instrucation */ - vmx_str_pio_handler(exit_qualification, inst_len, regs, pio_opp); + vmx_do_str_pio(exit_qualification, inst_len, regs, pio_opp); else { unsigned int port, size; @@ -2000,7 +2051,7 @@ static int vmx_world_restore(struct vcpu goto bad_cr3; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); - if (old_base_mfn) + if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); v->arch.hvm_vmx.cpu_cr3 = c->cr3; } @@ -2078,13 +2129,13 @@ static int vmx_assist(struct vcpu *v, in u32 magic, cp; /* make sure vmxassist exists (this is not an error) */ - if (hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET, - sizeof(magic))) + if ( hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET, + sizeof(magic)) ) return 0; - if (magic != VMXASSIST_MAGIC) + if ( magic != VMXASSIST_MAGIC ) return 0; - switch (mode) { + switch ( mode ) { /* * Transfer control to vmxassist. * Store the current context in VMXASSIST_OLD_CONTEXT and load @@ -2093,19 +2144,19 @@ static int vmx_assist(struct vcpu *v, in */ case VMX_ASSIST_INVOKE: /* save the old context */ - if (hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp))) + if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp)) ) goto error; - if (cp != 0) { + if ( cp != 0 ) { vmx_world_save(v, &c); - if (hvm_copy_to_guest_phys(cp, &c, sizeof(c))) + if ( hvm_copy_to_guest_phys(cp, &c, sizeof(c))) goto error; } /* restore the new context, this should activate vmxassist */ - if (hvm_copy_from_guest_phys(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp))) + if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp)) ) goto error; - if (cp != 0) { - if (hvm_copy_from_guest_phys(&c, cp, sizeof(c))) + if ( cp != 0 ) { + if ( hvm_copy_from_guest_phys(&c, cp, sizeof(c)) ) goto error; if ( vmx_world_restore(v, &c) != 0 ) goto error; @@ -2124,10 +2175,10 @@ static int vmx_assist(struct vcpu *v, in */ case VMX_ASSIST_RESTORE: /* save the old context */ - if (hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp))) + if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp)) ) goto error; - if (cp != 0) { - if (hvm_copy_from_guest_phys(&c, cp, sizeof(c))) + if ( cp != 0 ) { + if ( hvm_copy_from_guest_phys(&c, cp, sizeof(c)) ) goto error; if ( vmx_world_restore(v, &c) != 0 ) goto error; @@ -2156,7 +2207,6 @@ static int vmx_set_cr0(unsigned long val unsigned long mfn; unsigned long eip; int paging_enabled; - unsigned long vm_entry_value; unsigned long old_cr0; unsigned long old_base_mfn; @@ -2181,30 +2231,17 @@ static int vmx_set_cr0(unsigned long val old_cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; paging_enabled = old_cr0 & X86_CR0_PG; - v->arch.hvm_vmx.cpu_cr0 = (value | X86_CR0_PE | X86_CR0_PG + v->arch.hvm_vmx.cpu_cr0 = (value | X86_CR0_PE | X86_CR0_PG | X86_CR0_NE | X86_CR0_WP); __vmwrite(GUEST_CR0, v->arch.hvm_vmx.cpu_cr0); v->arch.hvm_vmx.cpu_shadow_cr0 = value; __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0); + /* Trying to enable paging. */ if ( (value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled ) { - /* - * Trying to enable guest paging. - * The guest CR3 must be pointing to the guest physical. - */ - mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT); - if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) - { - gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", - v->arch.hvm_vmx.cpu_cr3, mfn); - domain_crash(v->domain); - return 0; - } - -#if defined(__x86_64__) - if ( vmx_lme_is_set(v) ) + if ( vmx_lme_is_set(v) && !vmx_long_mode_enabled(v) ) { if ( !(v->arch.hvm_vmx.cpu_shadow_cr4 & X86_CR4_PAE) ) { @@ -2215,21 +2252,30 @@ static int vmx_set_cr0(unsigned long val else { HVM_DBG_LOG(DBG_LEVEL_1, "Enabling long mode"); - v->arch.hvm_vmx.efer |= EFER_LMA; - vm_entry_value = __vmread(VM_ENTRY_CONTROLS); - vm_entry_value |= VM_ENTRY_IA32E_MODE; - __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); + vmx_enable_long_mode(v); } } -#endif + + /* + * The guest CR3 must be pointing to the guest physical. + */ + mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT); + if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) + { + gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", + v->arch.hvm_vmx.cpu_cr3, mfn); + domain_crash(v->domain); + return 0; + } /* * Now arch.guest_table points to machine physical. */ old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); - if (old_base_mfn) + if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", @@ -2239,12 +2285,20 @@ static int vmx_set_cr0(unsigned long val v->arch.hvm_vmx.cpu_cr3, mfn); } - if ( !((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled ) - if ( v->arch.hvm_vmx.cpu_cr3 ) { + /* Trying to disable paging. */ + if ( ((value & (X86_CR0_PE | X86_CR0_PG)) != (X86_CR0_PE | X86_CR0_PG)) && + paging_enabled ) + { + if ( v->arch.hvm_vmx.cpu_cr3 ) + { put_page(mfn_to_page(get_mfn_from_gpfn( v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT))); v->arch.guest_table = pagetable_null(); } + + if ( vmx_long_mode_enabled(v) ) + vmx_disable_long_mode(v); + } /* * VMX does not implement real-mode virtualization. We emulate @@ -2257,18 +2311,6 @@ static int vmx_set_cr0(unsigned long val /* inject GP here */ vmx_inject_hw_exception(v, TRAP_gp_fault, 0); return 0; - } else { - /* - * Disable paging here. - * Same to PE == 1 && PG == 0 - */ - if ( vmx_long_mode_enabled(v) ) - { - v->arch.hvm_vmx.efer &= ~EFER_LMA; - vm_entry_value = __vmread(VM_ENTRY_CONTROLS); - vm_entry_value &= ~VM_ENTRY_IA32E_MODE; - __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); - } } if ( vmx_assist(v, VMX_ASSIST_INVOKE) ) @@ -2292,16 +2334,7 @@ static int vmx_set_cr0(unsigned long val } } else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE ) - { - if ( vmx_long_mode_enabled(v) ) - { - v->arch.hvm_vmx.efer &= ~EFER_LMA; - vm_entry_value = __vmread(VM_ENTRY_CONTROLS); - vm_entry_value &= ~VM_ENTRY_IA32E_MODE; - __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); - } paging_update_paging_modes(v); - } return 1; } @@ -2370,7 +2403,7 @@ static int mov_to_cr(int gp, int cr, str /* * If paging is not enabled yet, simply copy the value to CR3. */ - if (!vmx_paging_enabled(v)) { + if ( !vmx_paging_enabled(v) ) { v->arch.hvm_vmx.cpu_cr3 = value; break; } @@ -2378,14 +2411,14 @@ static int mov_to_cr(int gp, int cr, str /* * We make a new one if the shadow does not exist. */ - if (value == v->arch.hvm_vmx.cpu_cr3) { + if ( value == v->arch.hvm_vmx.cpu_cr3 ) { /* * This is simple TLB flush, implying the guest has * removed some translation or changed page attributes. * We simply invalidate the shadow. */ mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); - if (mfn != pagetable_get_pfn(v->arch.guest_table)) + if ( mfn != pagetable_get_pfn(v->arch.guest_table) ) goto bad_cr3; paging_update_cr3(v); } else { @@ -2399,7 +2432,7 @@ static int mov_to_cr(int gp, int cr, str goto bad_cr3; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); - if (old_base_mfn) + if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); v->arch.hvm_vmx.cpu_cr3 = value; update_cr3(v); @@ -2443,7 +2476,7 @@ static int mov_to_cr(int gp, int cr, str HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); - HVM_DBG_LOG(DBG_LEVEL_VMMU, + HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", v->arch.hvm_vmx.cpu_cr3, mfn); #endif @@ -2469,6 +2502,7 @@ static int mov_to_cr(int gp, int cr, str */ if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) ) paging_update_paging_modes(v); + break; case 8: @@ -2545,7 +2579,7 @@ static int vmx_cr_access(unsigned long e unsigned long value; struct vcpu *v = current; - switch (exit_qualification & CONTROL_REG_ACCESS_TYPE) { + switch ( exit_qualification & CONTROL_REG_ACCESS_TYPE ) { case TYPE_MOV_TO_CR: gp = exit_qualification & CONTROL_REG_ACCESS_REG; cr = exit_qualification & CONTROL_REG_ACCESS_NUM; @@ -2578,7 +2612,7 @@ static int vmx_cr_access(unsigned long e return 1; } -static inline int vmx_do_msr_read(struct cpu_user_regs *regs) +static int vmx_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; u32 ecx = regs->ecx, eax, edx; @@ -2699,7 +2733,7 @@ void vmx_vlapic_msr_changed(struct vcpu vmx_vmcs_exit(v); } -static inline int vmx_do_msr_write(struct cpu_user_regs *regs) +static int vmx_do_msr_write(struct cpu_user_regs *regs) { u32 ecx = regs->ecx; u64 msr_content; @@ -2752,7 +2786,7 @@ static void vmx_do_hlt(void) hvm_hlt(rflags); } -static inline void vmx_do_extint(struct cpu_user_regs *regs) +static void vmx_do_extint(struct cpu_user_regs *regs) { unsigned int vector; diff -r 8528da5be577 -r 41c8284cfc0c xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Sat Jul 07 10:31:15 2007 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Sat Jul 07 11:08:57 2007 +0100 @@ -263,28 +263,6 @@ static inline int __vmxon (u64 addr) return rc; } -static inline int vmx_paging_enabled(struct vcpu *v) -{ - unsigned long cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; - return ((cr0 & (X86_CR0_PE|X86_CR0_PG)) == (X86_CR0_PE|X86_CR0_PG)); -} - -static inline int vmx_long_mode_enabled(struct vcpu *v) -{ - return v->arch.hvm_vmx.efer & EFER_LMA; -} - -static inline int vmx_lme_is_set(struct vcpu *v) -{ - return v->arch.hvm_vmx.efer & EFER_LME; -} - -static inline int vmx_pgbit_test(struct vcpu *v) -{ - unsigned long cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; - return (cr0 & X86_CR0_PG); -} - static inline void __vmx_inject_exception(struct vcpu *v, int trap, int type, int error_code, int ilen) { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |