diff -r bd97e45e073a xen/arch/x86/cpu/amd.c --- a/xen/arch/x86/cpu/amd.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/cpu/amd.c Wed Jul 09 15:13:55 2008 -0600 @@ -327,8 +327,10 @@ static void __init init_amd(struct cpuin if (cpuid_eax(0x80000000) >= 0x80000007) { c->x86_power = cpuid_edx(0x80000007); - if (c->x86_power & (1<<8)) + if (c->x86_power & (1<<8)) { set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + constant_tsc = 1; + } } #ifdef CONFIG_X86_HT diff -r bd97e45e073a xen/arch/x86/cpu/common.c --- a/xen/arch/x86/cpu/common.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/cpu/common.c Wed Jul 09 15:13:55 2008 -0600 @@ -16,6 +16,8 @@ #define tsc_disable 0 #define disable_pse 0 + +int constant_tsc = 0; static int cachesize_override __cpuinitdata = -1; static int disable_x86_fxsr __cpuinitdata; diff -r bd97e45e073a xen/arch/x86/cpu/intel.c --- a/xen/arch/x86/cpu/intel.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/cpu/intel.c Wed Jul 09 15:13:55 2008 -0600 @@ -184,8 +184,10 @@ static void __devinit init_intel(struct if (c->x86 == 6) set_bit(X86_FEATURE_P3, c->x86_capability); if ((c->x86 == 0xf && c->x86_model >= 0x03) || - (c->x86 == 0x6 && c->x86_model >= 0x0e)) + (c->x86 == 0x6 && c->x86_model >= 0x0e)) { set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + constant_tsc = 1; + } start_vmx(); } diff -r bd97e45e073a xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/hvm/hvm.c Wed Jul 09 15:13:55 2008 -0600 @@ -56,6 +56,8 @@ int hvm_enabled __read_mostly; unsigned int opt_hvm_debug_level __read_mostly; integer_param("hvm_debug", opt_hvm_debug_level); +int opt_softtsc = 0; +boolean_param("softtsc", opt_softtsc); struct hvm_function_table hvm_funcs __read_mostly; @@ -148,7 +150,10 @@ u64 hvm_get_guest_tsc(struct vcpu *v) { u64 host_tsc; - rdtscll(host_tsc); + if ( opt_softtsc ) + host_tsc = hvm_get_guest_time(v); + else + rdtscll(host_tsc); return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset; } @@ -1640,6 +1645,16 @@ void hvm_cpuid(unsigned int input, unsig } } +void hvm_rdtsc_intercept(struct cpu_user_regs *regs) +{ + uint64_t tsc; + struct vcpu *v = current; + + tsc = hvm_get_guest_tsc(v); + regs->eax = (uint32_t)tsc; + regs->edx = (uint32_t)(tsc >> 32); +} + int hvm_msr_read_intercept(struct cpu_user_regs *regs) { uint32_t ecx = regs->ecx; diff -r bd97e45e073a xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Jul 09 15:13:55 2008 -0600 @@ -52,6 +52,8 @@ #include u32 svm_feature_flags; + +extern int opt_softtsc; #define set_segment_register(name, value) \ asm volatile ( "movw %%ax ,%%" STR(name) "" : : "a" (value) ) @@ -1340,6 +1342,13 @@ asmlinkage void svm_vmexit_handler(struc hvm_triple_fault(); break; + case VMEXIT_RDTSC: + if ( opt_softtsc ) + { + hvm_rdtsc_intercept(regs); + break; + } + /* else fall through */ case VMEXIT_RDTSCP: case VMEXIT_MONITOR: case VMEXIT_MWAIT: diff -r bd97e45e073a xen/arch/x86/hvm/svm/vmcb.c --- a/xen/arch/x86/hvm/svm/vmcb.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/hvm/svm/vmcb.c Wed Jul 09 15:13:55 2008 -0600 @@ -39,6 +39,8 @@ #include extern int svm_dbg_on; + +extern int opt_softtsc; #define IOPM_SIZE (12 * 1024) #define MSRPM_SIZE (8 * 1024) @@ -165,6 +167,9 @@ static int construct_vmcb(struct vcpu *v /* TSC. */ vmcb->tsc_offset = 0; + if ( opt_softtsc ) + vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC; + /* Guest EFER: *must* contain SVME or VMRUN will fail. */ vmcb->efer = EFER_SVME; diff -r bd97e45e073a xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Wed Jul 09 15:13:55 2008 -0600 @@ -40,6 +40,7 @@ static int opt_vpid_enabled = 1; boolean_param("vpid", opt_vpid_enabled); +extern int opt_softtsc; /* Dynamic (run-time adjusted) execution control flags. */ u32 vmx_pin_based_exec_control __read_mostly; @@ -96,6 +97,8 @@ static void vmx_init_vmcs_config(void) CPU_BASED_MOV_DR_EXITING | CPU_BASED_ACTIVATE_IO_BITMAP | CPU_BASED_USE_TSC_OFFSETING); + if (opt_softtsc) + min |= CPU_BASED_RDTSC_EXITING; opt = (CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); diff -r bd97e45e073a xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jul 09 15:13:55 2008 -0600 @@ -2202,6 +2202,11 @@ asmlinkage void vmx_vmexit_handler(struc vmx_invlpg_intercept(exit_qualification); break; } + case EXIT_REASON_RDTSC: + inst_len = __get_instruction_length(); + __update_guest_eip(inst_len); + hvm_rdtsc_intercept(regs); + break; case EXIT_REASON_VMCALL: { int rc; diff -r bd97e45e073a xen/arch/x86/time.c --- a/xen/arch/x86/time.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/arch/x86/time.c Wed Jul 09 15:13:55 2008 -0600 @@ -68,7 +68,7 @@ static DEFINE_PER_CPU(struct cpu_time, c static DEFINE_PER_CPU(struct cpu_time, cpu_time); /* TSC is invariant on C state entry? */ -static bool_t tsc_invariant; +bool_t tsc_invariant; /* * We simulate a 32-bit platform timer from the 16-bit PIT ch2 counter. diff -r bd97e45e073a xen/common/keyhandler.c --- a/xen/common/keyhandler.c Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/common/keyhandler.c Wed Jul 09 15:13:55 2008 -0600 @@ -251,6 +251,8 @@ static void read_clocks(unsigned char ke unsigned int cpu = smp_processor_id(), min_cpu, max_cpu; u64 min, max, dif, difus; static DEFINE_SPINLOCK(lock); + extern int opt_softtsc, constant_tsc; + extern bool_t tsc_invariant; spin_lock(&lock); @@ -284,6 +286,8 @@ static void read_clocks(unsigned char ke printk("Min = %"PRIu64" ; Max = %"PRIu64" ; Diff = %"PRIu64 " (%"PRIu64" microseconds)\n", min, max, dif, difus); + printk("softtsc = %d, constant_tsc = %d, tsc_invariant = %d\n", + opt_softtsc, constant_tsc, (int)tsc_invariant); } extern void dump_runq(unsigned char key); diff -r bd97e45e073a xen/include/asm-x86/cpufeature.h --- a/xen/include/asm-x86/cpufeature.h Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/include/asm-x86/cpufeature.h Wed Jul 09 15:13:55 2008 -0600 @@ -74,6 +74,8 @@ #define X86_FEATURE_P3 (3*32+ 6) /* P3 */ #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ + +extern int constant_tsc; /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ diff -r bd97e45e073a xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Tue Jul 08 09:28:50 2008 +0100 +++ b/xen/include/asm-x86/hvm/support.h Wed Jul 09 15:13:55 2008 -0600 @@ -125,6 +125,8 @@ void hvm_hlt(unsigned long rflags); void hvm_hlt(unsigned long rflags); void hvm_triple_fault(void); +void hvm_rdtsc_intercept(struct cpu_user_regs *regs); + /* These functions all return X86EMUL return codes. */ int hvm_set_efer(uint64_t value); int hvm_set_cr0(unsigned long value);