diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-07-10 15:45:18 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-07-10 15:45:18 +0100 |
commit | 5fd92b77dce4525ca332a94d000d88f22f7e7411 (patch) | |
tree | 32da7457c1072f6ed56da7b782990ff2a2b09133 | |
parent | 49ecbb58e06f4ed07276ad222f20345229c0c1f1 (diff) | |
download | xen-5fd92b77dce4525ca332a94d000d88f22f7e7411.tar.gz xen-5fd92b77dce4525ca332a94d000d88f22f7e7411.tar.bz2 xen-5fd92b77dce4525ca332a94d000d88f22f7e7411.zip |
x86 hvm: New boot option 'softtsc' to cause RDTSC to be trapped-and-emulated.
Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r-- | xen/arch/x86/hvm/hvm.c | 19 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/svm.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/vmcb.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmcs.c | 3 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 5 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/support.h | 3 |
6 files changed, 35 insertions, 3 deletions
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 04e9da6e0e..4b58db1d67 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -57,6 +57,9 @@ int hvm_enabled __read_mostly; unsigned int opt_hvm_debug_level __read_mostly; integer_param("hvm_debug", opt_hvm_debug_level); +int opt_softtsc; +boolean_param("softtsc", opt_softtsc); + struct hvm_function_table hvm_funcs __read_mostly; /* I/O permission bitmap is globally shared by all HVM guests. */ @@ -148,7 +151,11 @@ 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; } @@ -1651,6 +1658,16 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, } } +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 --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 86a4767737..ea72939413 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1340,6 +1340,10 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) hvm_triple_fault(); break; + case VMEXIT_RDTSC: + hvm_rdtsc_intercept(regs); + break; + case VMEXIT_RDTSCP: case VMEXIT_MONITOR: case VMEXIT_MWAIT: diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 0cf8347d85..73894f881c 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -165,7 +165,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 --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index bda2ec953e..4341859bce 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -95,7 +95,8 @@ static void vmx_init_vmcs_config(void) CPU_BASED_MWAIT_EXITING | CPU_BASED_MOV_DR_EXITING | CPU_BASED_ACTIVATE_IO_BITMAP | - CPU_BASED_USE_TSC_OFFSETING); + CPU_BASED_USE_TSC_OFFSETING | + (opt_softtsc ? CPU_BASED_RDTSC_EXITING : 0)); opt = (CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 8114a93ad2..fbefbd7f75 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2205,6 +2205,11 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) 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 --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 38a0025855..9e3ef99e9b 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -125,6 +125,9 @@ int hvm_do_hypercall(struct cpu_user_regs *pregs); void hvm_hlt(unsigned long rflags); void hvm_triple_fault(void); +extern int opt_softtsc; +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); |