Implement hypercall for rdtsc. This provides a better
performing alternative for guests for which rdtsc emulation
is enabled (which may soon be the default). Three forms:
1) Read the raw physical cpu TSC
2) Read monotonically-increasing Xen system time (nsec since
guest boot)
3) Determine if rdtsc emulation is enabled for this guest
Form 3 can be used (once) to determine if rdtsc emulation
is enabled. If it is not, the normal pvclock algorithm
can be used as if it can be done in a vsyscall (in user
space) it is, by far, the fastest. If it is, form 1 can
be used to avoid the trap from rdtsc; or form 2 can be
used directly as it should return the same result as
applying the pvclock algorithm to the value returned by
Form 1 EXCEPT form 2 enforces monotonicity.
Signed-off-by: Dan Magenheimer <dan.magenheimer@xxxxxxxxxx>
--- a/xen/arch/x86/time.c Wed Sep 09 16:39:41 2009 +0100
+++ b/xen/arch/x86/time.c Fri Sep 11 09:52:18 2009 -0600
@@ -22,6 +22,7 @@
#include <xen/irq.h>
#include <xen/softirq.h>
#include <xen/keyhandler.h>
+#include <public/xen.h>
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/mpspec.h>
@@ -1435,6 +1436,43 @@ struct tm wallclock_time(void)
/*
+ * rdtsc hypercall
+ */
+
+#ifdef __x86_64__
+uint64_t do_rdtsc_op(unsigned long subop)
+{
+ struct vcpu *v = current;
+ unsigned long eax, edx;
+ s_time_t now = 0;
+
+ BUG_ON(is_pv_32on64_vcpu(v));
+ switch (subop)
+ {
+ case RDTSC_READ_XEN_TSC:
+
+ spin_lock(&v->domain->arch.vtsc_lock);
+ now = get_s_time() + v->domain->arch.vtsc_stime_offset;
+ if ( (int64_t)(now - v->domain->arch.vtsc_last) > 0 )
+ v->domain->arch.vtsc_last = now;
+ else
+ now = ++v->domain->arch.vtsc_last;
+ spin_unlock(&v->domain->arch.vtsc_lock);
+ break;
+ case RDTSC_READ_RAW_TSC:
+ rdtsc(eax, edx);
+ now = ((uint64_t)edx << 32) | (uint32_t)eax;
+ break;
+ case RDTSC_IS_EMULATED:
+ now = v->domain->arch.vtsc ? 1 : 0;
+ break;
+ }
+ return now;
+}
+#endif
+
+
+/*
* PV SoftTSC Emulation.
*/
diff -r d2a32e24fe50 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S Wed Sep 09 16:39:41 2009 +0100
+++ b/xen/arch/x86/x86_32/entry.S Fri Sep 11 09:52:18 2009 -0600
@@ -704,6 +704,7 @@ ENTRY(hypercall_table)
.long do_domctl
.long do_kexec_op
.long do_tmem_op
+ .long do_ni_hypercall /* reserved for x86_64 do_rdtsc_op */
.rept __HYPERVISOR_arch_0-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
@@ -752,6 +753,7 @@ ENTRY(hypercall_args_table)
.byte 1 /* do_domctl */
.byte 2 /* do_kexec_op */
.byte 1 /* do_tmem_op */
+ .byte 0 /* x86_64-only do_rdtsc_op */
.rept __HYPERVISOR_arch_0-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
diff -r d2a32e24fe50 xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S Wed Sep 09 16:39:41 2009 +0100
+++ b/xen/arch/x86/x86_64/compat/entry.S Fri Sep 11 09:52:18 2009 -0600
@@ -409,6 +409,7 @@ ENTRY(compat_hypercall_table)
.quad do_domctl
.quad compat_kexec_op
.quad do_tmem_op
+ .quad compat_ni_hypercall /* reserved for x86_64 do_rdtsc_op */
.rept __HYPERVISOR_arch_0-((.-compat_hypercall_table)/8)
.quad compat_ni_hypercall
.endr
@@ -457,6 +458,7 @@ ENTRY(compat_hypercall_args_table)
.byte 1 /* do_domctl */
.byte 2 /* compat_kexec_op */
.byte 1 /* do_tmem_op */
+ .byte 0 /* x86_64-only do_rdtsc_op */
.rept __HYPERVISOR_arch_0-(.-compat_hypercall_args_table)
.byte 0 /* compat_ni_hypercall */
.endr
diff -r d2a32e24fe50 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S Wed Sep 09 16:39:41 2009 +0100
+++ b/xen/arch/x86/x86_64/entry.S Fri Sep 11 09:52:18 2009 -0600
@@ -693,6 +693,7 @@ ENTRY(hypercall_table)
.quad do_domctl
.quad do_kexec_op
.quad do_tmem_op
+ .quad do_rdtsc_op
.rept __HYPERVISOR_arch_0-((.-hypercall_table)/8)
.quad do_ni_hypercall
.endr
@@ -741,6 +742,7 @@ ENTRY(hypercall_args_table)
.byte 1 /* do_domctl */
.byte 2 /* do_kexec */
.byte 1 /* do_tmem_op */
+ .byte 1 /* do_rdtsc */
.rept __HYPERVISOR_arch_0-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
diff -r d2a32e24fe50 xen/include/public/xen.h
--- a/xen/include/public/xen.h Wed Sep 09 16:39:41 2009 +0100
+++ b/xen/include/public/xen.h Fri Sep 11 09:52:18 2009 -0600
@@ -92,6 +92,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
#define __HYPERVISOR_domctl 36
#define __HYPERVISOR_kexec_op 37
#define __HYPERVISOR_tmem_op 38
+#define __HYPERVISOR_rdtsc_op 39 /* x86/64 only */
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
@@ -333,6 +334,17 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
#define VMASST_TYPE_pae_extended_cr3 3
#define MAX_VMASST_TYPE 3
+
+/*
+ * Commands to HYPERVISOR_rdtsc_op() (x86/64 only)
+ */
+
+/* read raw physical cpu TSC value (approx 2-3x faster than trap/emulate) */
+#define RDTSC_READ_RAW_TSC 0
+/* read monotonically-increasing Xen system time (nsec since guest boot) */
+#define RDTSC_READ_XEN_TSC 1
+/* is rdtsc emulation enabled for this guest? */
+#define RDTSC_IS_EMULATED 2
#ifndef __ASSEMBLY__
hyp-rdtsc-090911.patch
Description: Binary data
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|