aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-07-10 15:45:18 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-07-10 15:45:18 +0100
commit5fd92b77dce4525ca332a94d000d88f22f7e7411 (patch)
tree32da7457c1072f6ed56da7b782990ff2a2b09133
parent49ecbb58e06f4ed07276ad222f20345229c0c1f1 (diff)
downloadxen-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.c19
-rw-r--r--xen/arch/x86/hvm/svm/svm.c4
-rw-r--r--xen/arch/x86/hvm/svm/vmcb.c4
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c3
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c5
-rw-r--r--xen/include/asm-x86/hvm/support.h3
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);