[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add RDTSCP instruction support for HVM VMX guest.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1260776817 0 # Node ID c61953922215ecde526468d5a2ebe5147eee7529 # Parent 2d072636c4f8b80ac62f49aaeabb04fcdf74760c Add RDTSCP instruction support for HVM VMX guest. RDTSCP is introduced in Nehalem processor on Intel platform. Like RDTSC, RDTSCP will return the TSC value, besides, it will return the low 32bit of TSC_AUX MSR. Currently Linux kernel will write (node_id << 12 | process_id) into that MSR, so that when guest execs RDTSCP, it will also get processor information. - This instruction is supported for HVM only when the hardware has this capability (indicated by cpuid). Signed-off-by: Dongxiao Xu <dongxiao.xu@xxxxxxxxx> --- xen/arch/x86/hvm/vmx/vmcs.c | 5 ++ xen/arch/x86/hvm/vmx/vmx.c | 76 ++++++++++++++++++++++++++++++++- xen/include/asm-x86/cpufeature.h | 2 xen/include/asm-x86/hvm/vmx/vmcs.h | 2 xen/include/asm-x86/hvm/vmx/vmx.h | 1 xen/include/asm-x86/msr-index.h | 1 xen/include/public/arch-x86/hvm/save.h | 1 7 files changed, 86 insertions(+), 2 deletions(-) diff -r 2d072636c4f8 -r c61953922215 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Mon Dec 14 07:46:57 2009 +0000 @@ -593,6 +593,11 @@ static int construct_vmcs(struct vcpu *v __vmwrite(PLE_GAP, ple_gap); __vmwrite(PLE_WINDOW, ple_window); } + +#ifdef __x86_64__ + if ( cpu_has_rdtscp ) + v->arch.hvm_vmx.secondary_exec_control |= SECONDARY_EXEC_ENABLE_RDTSCP; +#endif if ( cpu_has_vmx_secondary_exec_control ) __vmwrite(SECONDARY_VM_EXEC_CONTROL, diff -r 2d072636c4f8 -r c61953922215 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Dec 14 07:46:57 2009 +0000 @@ -136,18 +136,31 @@ static void vmx_vcpu_destroy(struct vcpu static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state); -static u32 msr_index[VMX_MSR_COUNT] = +static u32 msr_index[] = { MSR_LSTAR, MSR_STAR, MSR_SYSCALL_MASK }; +#define MSR_INDEX_SIZE (ARRAY_SIZE(msr_index)) + static void vmx_save_host_msrs(void) { struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state); int i; - for ( i = 0; i < VMX_MSR_COUNT; i++ ) + /* + * If new MSR is needed to add into msr_index[] and VMX_INDEX_MSR_*** enum, + * please note that elements in msr_index[] and VMX_INDEX_MSR_*** enum + * are not the same. Currently we only save three MSRs(MSR_LSTAR, MSR_STAR, + * and MSR_SYSCALL_MASK into host state. + */ + BUILD_BUG_ON(MSR_INDEX_SIZE != VMX_INDEX_MSR_TSC_AUX || + VMX_INDEX_MSR_TSC_AUX != VMX_MSR_COUNT - 1); + for ( i = 0; i < MSR_INDEX_SIZE; i++ ) rdmsrl(msr_index[i], host_msr_state->msrs[i]); + + if ( cpu_has_rdtscp ) + rdmsrl(MSR_TSC_AUX, host_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]); } #define WRITE_MSR(address) \ @@ -198,6 +211,21 @@ static enum handler_return long_mode_do_ msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK]; break; + case MSR_TSC_AUX: + if ( cpu_has_rdtscp ) + { + msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]; + break; + } + else + { + HVM_DBG_LOG(DBG_LEVEL_0, "Reading from nonexistence msr 0x%x\n", + ecx); + vmx_inject_hw_exception(TRAP_gp_fault, 0); + return HNDL_exception_raised; + } + + default: return HNDL_unhandled; } @@ -258,6 +286,20 @@ static enum handler_return long_mode_do_ case MSR_SYSCALL_MASK: WRITE_MSR(SYSCALL_MASK); + + case MSR_TSC_AUX: + if ( cpu_has_rdtscp ) + { + struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state; + guest_state->msrs[VMX_INDEX_MSR_TSC_AUX] = msr_content; + wrmsrl(MSR_TSC_AUX, msr_content); + } + else + { + HVM_DBG_LOG(DBG_LEVEL_0, "Writing to nonexistence msr 0x%x\n", ecx); + vmx_inject_hw_exception(TRAP_gp_fault, 0); + return HNDL_exception_raised; + } default: return HNDL_unhandled; @@ -289,15 +331,21 @@ 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_rdtscp ) + wrmsrl(MSR_TSC_AUX, host_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]); } static void vmx_save_guest_msrs(struct vcpu *v) { + struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state; /* * We cannot cache SHADOW_GS_BASE while the VCPU runs, as it can * be updated at any time via SWAPGS, which we cannot trap. */ rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.shadow_gs); + if ( cpu_has_rdtscp ) + rdmsrl(MSR_TSC_AUX, guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]); } static void vmx_restore_guest_msrs(struct vcpu *v) @@ -333,6 +381,9 @@ static void vmx_restore_guest_msrs(struc write_efer((read_efer() & ~EFER_SCE) | (v->arch.hvm_vcpu.guest_efer & EFER_SCE)); } + + if ( cpu_has_rdtscp ) + wrmsrl(MSR_TSC_AUX, guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]); } #else /* __i386__ */ @@ -574,6 +625,8 @@ static void vmx_save_cpu_state(struct vc data->msr_lstar = guest_state->msrs[VMX_INDEX_MSR_LSTAR]; data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR]; data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK]; + if ( cpu_has_rdtscp ) + data->msr_tsc_aux = guest_state->msrs[VMX_INDEX_MSR_TSC_AUX]; #endif data->tsc = hvm_get_guest_tsc(v); @@ -592,6 +645,8 @@ static void vmx_load_cpu_state(struct vc v->arch.hvm_vmx.cstar = data->msr_cstar; v->arch.hvm_vmx.shadow_gs = data->shadow_gs; + if ( cpu_has_rdtscp ) + guest_state->msrs[VMX_INDEX_MSR_TSC_AUX] = data->msr_tsc_aux; #endif hvm_set_guest_tsc(v, data->tsc); @@ -1507,6 +1562,14 @@ static void vmx_cpuid_intercept( *edx |= bitmaskof(X86_FEATURE_SYSCALL); else *edx &= ~(bitmaskof(X86_FEATURE_SYSCALL)); + +#ifdef __x86_64__ + if ( cpu_has_rdtscp ) + *edx |= bitmaskof(X86_FEATURE_RDTSCP); + else + *edx &= ~(bitmaskof(X86_FEATURE_RDTSCP)); +#endif + break; } @@ -2495,6 +2558,15 @@ asmlinkage void vmx_vmexit_handler(struc __update_guest_eip(inst_len); hvm_rdtsc_intercept(regs); break; + case EXIT_REASON_RDTSCP: + { + struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state; + inst_len = __get_instruction_length(); + __update_guest_eip(inst_len); + hvm_rdtsc_intercept(regs); + regs->ecx = (uint32_t)(guest_state->msrs[VMX_INDEX_MSR_TSC_AUX]); + break; + } case EXIT_REASON_VMCALL: { int rc; diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/cpufeature.h --- a/xen/include/asm-x86/cpufeature.h Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/include/asm-x86/cpufeature.h Mon Dec 14 07:46:57 2009 +0000 @@ -196,6 +196,8 @@ #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) +#define cpu_has_rdtscp boot_cpu_has(X86_FEATURE_RDTSCP) + #endif /* __ASM_I386_CPUFEATURE_H */ /* diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Dec 14 07:46:57 2009 +0000 @@ -44,6 +44,7 @@ enum { VMX_INDEX_MSR_LSTAR = 0, VMX_INDEX_MSR_STAR, VMX_INDEX_MSR_SYSCALL_MASK, + VMX_INDEX_MSR_TSC_AUX, VMX_MSR_COUNT }; @@ -166,6 +167,7 @@ extern u32 vmx_vmentry_control; #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 #define SECONDARY_EXEC_ENABLE_EPT 0x00000002 +#define SECONDARY_EXEC_ENABLE_RDTSCP 0x00000008 #define SECONDARY_EXEC_ENABLE_VPID 0x00000020 #define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 #define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Mon Dec 14 07:46:57 2009 +0000 @@ -110,6 +110,7 @@ void vmx_update_debug_state(struct vcpu #define EXIT_REASON_APIC_ACCESS 44 #define EXIT_REASON_EPT_VIOLATION 48 #define EXIT_REASON_EPT_MISCONFIG 49 +#define EXIT_REASON_RDTSCP 51 #define EXIT_REASON_WBINVD 54 #define EXIT_REASON_XSETBV 55 diff -r 2d072636c4f8 -r c61953922215 xen/include/asm-x86/msr-index.h --- a/xen/include/asm-x86/msr-index.h Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/include/asm-x86/msr-index.h Mon Dec 14 07:46:57 2009 +0000 @@ -12,6 +12,7 @@ #define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ #define MSR_GS_BASE 0xc0000101 /* 64bit GS base */ #define MSR_SHADOW_GS_BASE 0xc0000102 /* SwapGS GS shadow */ +#define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */ /* EFER bits: */ #define _EFER_SCE 0 /* SYSCALL/SYSRET */ diff -r 2d072636c4f8 -r c61953922215 xen/include/public/arch-x86/hvm/save.h --- a/xen/include/public/arch-x86/hvm/save.h Mon Dec 14 07:45:04 2009 +0000 +++ b/xen/include/public/arch-x86/hvm/save.h Mon Dec 14 07:46:57 2009 +0000 @@ -137,6 +137,7 @@ struct hvm_hw_cpu { uint64_t msr_cstar; uint64_t msr_syscall_mask; uint64_t msr_efer; + uint64_t msr_tsc_aux; /* guest's idea of what rdtsc() would return */ uint64_t tsc; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |