[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] hvm: Clean ups and fix MSR access functions.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1184000663 -3600 # Node ID 1d1ccf6b861405805f46b5f17b973a05e138c871 # Parent aa640601575fb4b509befd9f032f0f3d577a46fc hvm: Clean ups and fix MSR access functions. Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/svm/svm.c | 37 +++++----- xen/arch/x86/hvm/vmx/vmx.c | 158 ++++++++++++++++++++++++++------------------- 2 files changed, 113 insertions(+), 82 deletions(-) diff -r aa640601575f -r 1d1ccf6b8614 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Mon Jul 09 14:51:44 2007 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Mon Jul 09 18:04:23 2007 +0100 @@ -53,6 +53,8 @@ #define set_segment_register(name, value) \ asm volatile ( "movw %%ax ,%%" STR(name) "" : : "a" (value) ) +enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised }; + int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len); asmlinkage void do_IRQ(struct cpu_user_regs *); @@ -173,7 +175,7 @@ static void svm_store_cpu_guest_regs( } } -static int long_mode_do_msr_write(struct cpu_user_regs *regs) +static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); u32 ecx = regs->ecx; @@ -237,14 +239,14 @@ static int long_mode_do_msr_write(struct break; default: - return 0; - } - - return 1; + return HNDL_unhandled; + } + + return HNDL_done; gp_fault: svm_inject_exception(v, TRAP_gp_fault, 1, 0); - return 0; + return HNDL_exception_raised; } @@ -1716,8 +1718,8 @@ static int svm_set_cr0(unsigned long val if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); - HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", - (unsigned long) (mfn << PAGE_SHIFT)); + HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", + v->arch.hvm_vmx.cpu_cr3, mfn); } } else if ( !(value & X86_CR0_PG) && (old_value & X86_CR0_PG) ) @@ -1744,8 +1746,7 @@ static int svm_set_cr0(unsigned long val if ( (value ^ old_value) & X86_CR0_PG ) { paging_update_paging_modes(v); - /* signal paging update to ASID handler */ - svm_asid_g_update_paging (v); + svm_asid_g_update_paging(v); } return 1; @@ -1894,8 +1895,8 @@ static int mov_to_cr(int gpreg, int cr, { if ( svm_pgbit_test(v) ) { +#if CONFIG_PAGING_LEVELS >= 3 /* The guest is a 32-bit PAE guest. */ -#if CONFIG_PAGING_LEVELS >= 3 unsigned long mfn, old_base_mfn; mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); if ( !mfn_valid(mfn) || @@ -1905,7 +1906,6 @@ static int mov_to_cr(int gpreg, int cr, /* * 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 ) @@ -1913,9 +1913,6 @@ static int mov_to_cr(int gpreg, int cr, paging_update_paging_modes(v); /* signal paging update to ASID handler */ svm_asid_g_update_paging (v); - - HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", - (unsigned long) (mfn << PAGE_SHIFT)); HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", @@ -2201,8 +2198,16 @@ static void svm_do_msr_access( break; default: - if ( !long_mode_do_msr_write(regs) ) + switch ( long_mode_do_msr_write(regs) ) + { + case HNDL_unhandled: wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx); + break; + case HNDL_exception_raised: + return; + case HNDL_done: + break; + } break; } diff -r aa640601575f -r 1d1ccf6b8614 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Jul 09 14:51:44 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Jul 09 18:04:23 2007 +0100 @@ -51,6 +51,8 @@ #include <public/hvm/save.h> #include <asm/hvm/trace.h> +enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised }; + char *vmx_msr_bitmap; static void vmx_ctxt_switch_from(struct vcpu *v); @@ -178,14 +180,15 @@ static void vmx_save_host_msrs(void) set_bit(VMX_INDEX_MSR_ ## address, &host_msr_state->flags); \ break -static int long_mode_do_msr_read(struct cpu_user_regs *regs) +static enum handler_return long_mode_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; u32 ecx = regs->ecx; struct vcpu *v = current; struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state; - switch ( ecx ) { + switch ( ecx ) + { case MSR_EFER: msr_content = v->arch.hvm_vmx.efer; break; @@ -204,7 +207,7 @@ static int long_mode_do_msr_read(struct if ( !(vmx_long_mode_enabled(v)) ) { vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; + return HNDL_exception_raised; } break; @@ -225,7 +228,7 @@ static int long_mode_do_msr_read(struct break; default: - return 0; + return HNDL_unhandled; } HVM_DBG_LOG(DBG_LEVEL_0, "msr 0x%x content 0x%"PRIx64, ecx, msr_content); @@ -233,10 +236,10 @@ static int long_mode_do_msr_read(struct regs->eax = (u32)(msr_content >> 0); regs->edx = (u32)(msr_content >> 32); - return 1; -} - -static int long_mode_do_msr_write(struct cpu_user_regs *regs) + return HNDL_done; +} + +static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); u32 ecx = regs->ecx; @@ -326,16 +329,16 @@ static int long_mode_do_msr_write(struct WRITE_MSR(SYSCALL_MASK); default: - return 0; - } - - return 1; + return HNDL_unhandled; + } + + return HNDL_done; uncanonical_address: HVM_DBG_LOG(DBG_LEVEL_0, "Not cano address of msr write %x", ecx); gp_fault: vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; + return HNDL_exception_raised; } /* @@ -434,7 +437,7 @@ static void vmx_restore_guest_msrs(struc } } -static int long_mode_do_msr_read(struct cpu_user_regs *regs) +static enum handler_return long_mode_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; struct vcpu *v = current; @@ -445,16 +448,16 @@ static int long_mode_do_msr_read(struct break; default: - return 0; + return HNDL_unhandled; } regs->eax = msr_content >> 0; regs->edx = msr_content >> 32; - return 1; -} - -static int long_mode_do_msr_write(struct cpu_user_regs *regs) + return HNDL_done; +} + +static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = regs->eax | ((u64)regs->edx << 32); struct vcpu *v = current; @@ -469,7 +472,7 @@ static int long_mode_do_msr_write(struct gdprintk(XENLOG_WARNING, "Trying to set reserved bit in " "EFER: %"PRIx64"\n", msr_content); vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; + return HNDL_exception_raised; } if ( (msr_content ^ v->arch.hvm_vmx.efer) & EFER_NX ) @@ -479,10 +482,10 @@ static int long_mode_do_msr_write(struct break; default: - return 0; - } - - return 1; + return HNDL_unhandled; + } + + return HNDL_done; } #endif /* __i386__ */ @@ -683,9 +686,9 @@ int vmx_vmcs_restore(struct vcpu *v, str if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); + skip_cr3: v->arch.hvm_vmx.cpu_cr3 = c->cr3; - skip_cr3: if ( vmx_long_mode_enabled(v) ) vmx_enable_long_mode(v); @@ -1663,10 +1666,10 @@ static int vmx_str_pio_check_descriptor( } -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) +static int 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; @@ -1675,10 +1678,7 @@ static void vmx_str_pio_check_limit(u32 if ( (u32)(ea + size - 1) < (u32)ea || (ar_bytes & 0xc) != 0x4 ? ea + size - 1 > limit : ea <= limit ) - { - vmx_inject_hw_exception(current, TRAP_gp_fault, 0); - return; - } + return 0; /* Check the limit for repeated instructions, as above we checked only the first instance. Truncate the count if a limit violation @@ -1719,22 +1719,23 @@ static void vmx_str_pio_check_limit(u32 } ASSERT(*count); } + + return 1; } #ifdef __x86_64__ -static void vmx_str_pio_lm_check_limit(struct cpu_user_regs *regs, - unsigned int size, - unsigned long addr, - unsigned long *count) +static int 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) ) - { - vmx_inject_hw_exception(current, TRAP_gp_fault, 0); - return; - } + return 0; + if ( *count > (1UL << 48) / size ) *count = (1UL << 48) / size; + if ( !(regs->eflags & EF_DF) ) { if ( addr + *count * size - 1 < addr || @@ -1747,7 +1748,10 @@ static void vmx_str_pio_lm_check_limit(s !is_canonical_address(addr + (*count - 1) * size) ) *count = (addr & ~((1UL << 48) - 1)) / size + 1; } + ASSERT(*count); + + return 1; } #endif @@ -1875,18 +1879,21 @@ static void vmx_do_str_pio(unsigned long if ( !long_mode ) { /* Segment must be readable for outs and writeable for ins. */ - if ( dir == IOREQ_WRITE ? (ar_bytes & 0xa) == 0x8 - : (ar_bytes & 0xa) != 0x2 ) { + if ( ((dir == IOREQ_WRITE) + ? ((ar_bytes & 0xa) == 0x8) + : ((ar_bytes & 0xa) != 0x2)) || + !vmx_str_pio_check_limit(limit, size, ar_bytes, + addr, base, df, &count) ) + { vmx_inject_hw_exception(current, TRAP_gp_fault, 0); return; } - - vmx_str_pio_check_limit(limit, size, ar_bytes, addr, base, df, &count); } #ifdef __x86_64__ - else - { - vmx_str_pio_lm_check_limit(regs, size, addr, &count); + else if ( !vmx_str_pio_lm_check_limit(regs, size, addr, &count) ) + { + vmx_inject_hw_exception(current, TRAP_gp_fault, 0); + return; } #endif @@ -2133,12 +2140,20 @@ static int vmx_assist(struct vcpu *v, in struct hvm_hw_vpic *vpic = v->domain->arch.hvm_domain.vpic; u32 magic, cp; - /* make sure vmxassist exists (this is not an error) */ if ( hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic)) ) + { + gdprintk(XENLOG_ERR, "No vmxassist: can't execute real mode code\n"); + domain_crash(v->domain); return 0; + } + if ( magic != VMXASSIST_MAGIC ) + { + gdprintk(XENLOG_ERR, "vmxassist magic number not match\n"); + domain_crash(v->domain); return 0; + } switch ( mode ) { /* @@ -2280,28 +2295,26 @@ static int vmx_set_cr0(unsigned long val 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", - (unsigned long) (mfn << PAGE_SHIFT)); - HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", v->arch.hvm_vmx.cpu_cr3, mfn); + + paging_update_paging_modes(v); } /* Trying to disable paging. */ if ( ((value & (X86_CR0_PE | X86_CR0_PG)) != (X86_CR0_PE | X86_CR0_PG)) && paging_enabled ) { + /* When CR0.PG is cleared, LMA is cleared immediately. */ + if ( vmx_long_mode_enabled(v) ) + vmx_disable_long_mode(v); + 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); } /* @@ -2461,8 +2474,8 @@ static int mov_to_cr(int gp, int cr, str { if ( vmx_pgbit_test(v) ) { +#if CONFIG_PAGING_LEVELS >= 3 /* The guest is a 32-bit PAE guest. */ -#if CONFIG_PAGING_LEVELS >= 3 unsigned long mfn, old_base_mfn; mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT); if ( !mfn_valid(mfn) || @@ -2476,9 +2489,6 @@ static int mov_to_cr(int gp, int cr, str v->arch.guest_table = pagetable_from_pfn(mfn); if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); - - HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", - (unsigned long) (mfn << PAGE_SHIFT)); HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", @@ -2645,8 +2655,15 @@ static int vmx_do_msr_read(struct cpu_us case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2: goto gp_fault; default: - if ( long_mode_do_msr_read(regs) ) - goto done; + switch ( long_mode_do_msr_read(regs) ) + { + case HNDL_unhandled: + break; + case HNDL_exception_raised: + return 0; + case HNDL_done: + goto done; + } if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) || rdmsr_safe(ecx, eax, edx) == 0 ) @@ -2771,8 +2788,16 @@ static int vmx_do_msr_write(struct cpu_u case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2: goto gp_fault; default: - if ( !long_mode_do_msr_write(regs) ) - wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx); + switch ( long_mode_do_msr_write(regs) ) + { + case HNDL_unhandled: + wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx); + break; + case HNDL_exception_raised: + return 0; + case HNDL_done: + break; + } break; } @@ -2812,7 +2837,8 @@ static void vmx_do_extint(struct cpu_use vector &= INTR_INFO_VECTOR_MASK; HVMTRACE_1D(INTR, current, vector); - switch(vector) { + switch ( vector ) + { case LOCAL_TIMER_VECTOR: smp_apic_timer_interrupt(regs); break; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |