|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XTF PATCH v1 10/15] x86: introduce simple time management
From: Denis Mukhin <dmukhin@xxxxxxxx>
Some tests needs some estimation on certain operations longevity.
On x86 systems Xen conveniently exposes TSC frequency via
CPUID[ECX] 0x40000003.
Add TSC-based primitives into XTF to allow time measurements, including
TSC to time conversion routines.
Add common xtf_init_time() so that it can be called on demand if
the test needs time management.
Signed-off-by: Denis Mukhin <dmukhin@xxxxxxxx>
---
arch/x86/include/arch/time.h | 48 ++++++++++++++++++++++++++++++++++++
arch/x86/tsc.c | 32 ++++++++++++++++++++++++
build/files.mk | 2 ++
common/time.c | 6 +++++
include/xen/arch-x86/cpuid.h | 26 +++++++++++++++++++
include/xtf/time.h | 8 ++++++
6 files changed, 122 insertions(+)
create mode 100644 arch/x86/include/arch/time.h
create mode 100644 arch/x86/tsc.c
create mode 100644 common/time.c
create mode 100644 include/xtf/time.h
diff --git a/arch/x86/include/arch/time.h b/arch/x86/include/arch/time.h
new file mode 100644
index 000000000000..3a244a2a6eda
--- /dev/null
+++ b/arch/x86/include/arch/time.h
@@ -0,0 +1,48 @@
+#ifndef __X86_TIME_H_
+#define __X86_TIME_H_
+
+#include <stdint.h>
+
+extern uint32_t tsc_khz;
+
+void arch_init_time(void);
+
+static inline uint64_t rdtsc_ordered(void)
+{
+ uint32_t lo, hi;
+
+ asm volatile (
+ "lfence;"
+ "rdtsc;"
+ : "=a" (lo), "=d" (hi)
+ :
+ : "memory"
+ );
+
+ return ((uint64_t)hi << 32) | lo;
+}
+
+static inline uint64_t cycles_to_time_units(uint64_t cycles, uint64_t mult)
+{
+ if ( !tsc_khz )
+ return 0;
+
+ return cycles * mult / tsc_khz;
+}
+
+static inline uint64_t cycles_to_ns(uint64_t cycles)
+{
+ return cycles_to_time_units(cycles, 1000000ULL);
+}
+
+static inline uint64_t cycles_to_us(uint64_t cycles)
+{
+ return cycles_to_time_units(cycles, 1000ULL);
+}
+
+static inline uint64_t cycles_to_ms(uint64_t cycles)
+{
+ return cycles_to_time_units(cycles, 1ULL);
+}
+
+#endif /* __X86_TIME_H_ */
diff --git a/arch/x86/tsc.c b/arch/x86/tsc.c
new file mode 100644
index 000000000000..93c4de197984
--- /dev/null
+++ b/arch/x86/tsc.c
@@ -0,0 +1,32 @@
+#include <arch/cpuid.h>
+#include <arch/time.h>
+
+#include <xtf.h>
+
+uint32_t tsc_khz;
+
+void arch_init_time(void)
+{
+ uint32_t eax, ebx, ecx, edx;
+ bool emulated, reliable;
+
+ cpuid_count(XEN_CPUID_LEAF(3), 0, &eax, &ebx, &ecx, &edx);
+
+ tsc_khz = ecx;
+ emulated = !!(eax & XEN_CPUID_TSC_EMULATED);
+ reliable = !!(eax & XEN_CPUID_HOST_TSC_RELIABLE);
+
+ printk("Xen TSC: emulated=%u reliable=%u mode=%u "
+ "guest=%u kHz incarnation=%u\n",
+ emulated, reliable,
+ ebx, ecx, edx);
+
+ cpuid_count(XEN_CPUID_LEAF(3), 2,
+ &eax, &ebx, &ecx, &edx);
+
+ printk("Xen TSC: host=%u kHz\n", eax);
+
+ if ( emulated || !reliable )
+ xtf_warning("Xen TSC: time measurements are not reliable\n");
+}
+
diff --git a/build/files.mk b/build/files.mk
index 8a7d6f8d588f..ad39c00751b7 100644
--- a/build/files.mk
+++ b/build/files.mk
@@ -14,6 +14,7 @@ obj-perbits += $(ROOT)/common/libc/string.o
obj-perbits += $(ROOT)/common/libc/vsnprintf.o
obj-perbits += $(ROOT)/common/report.o
obj-perbits += $(ROOT)/common/setup.o
+obj-perbits += $(ROOT)/common/time.o
obj-perbits += $(ROOT)/common/xenbus.o
obj-perbits += $(ROOT)/common/weak-defaults.o
@@ -25,6 +26,7 @@ obj-perenv += $(ROOT)/arch/x86/hypercall_page.o
obj-perenv += $(ROOT)/arch/x86/msr.o
obj-perenv += $(ROOT)/arch/x86/setup.o
obj-perenv += $(ROOT)/arch/x86/traps.o
+obj-perenv += $(ROOT)/arch/x86/tsc.o
# HVM specific objects
diff --git a/common/time.c b/common/time.c
new file mode 100644
index 000000000000..c6e5136a1567
--- /dev/null
+++ b/common/time.c
@@ -0,0 +1,6 @@
+#include <xtf/time.h>
+
+void xtf_init_time(void)
+{
+ arch_init_time();
+}
diff --git a/include/xen/arch-x86/cpuid.h b/include/xen/arch-x86/cpuid.h
index 2fbc8eb656a0..9e1e7e6ac51b 100644
--- a/include/xen/arch-x86/cpuid.h
+++ b/include/xen/arch-x86/cpuid.h
@@ -15,6 +15,7 @@
*/
#define XEN_CPUID_FIRST_LEAF 0x40000000
+#define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i))
/*
* Leaf 1 (0x40000x00)
@@ -36,6 +37,31 @@
* EDX: Features 2. Unused bits are set to zero.
*/
+/*
+ * Leaf 4 (0x40000x03)
+ * Sub-leaf 0: EAX: bit 0: emulated tsc
+ * bit 1: host tsc is known to be reliable
+ * bit 2: RDTSCP instruction available
+ * EBX: tsc_mode: 0=default (emulate if necessary), 1=emulate,
+ * 2=no emulation, 3=no emulation + TSC_AUX support
+ * ECX: guest tsc frequency in kHz
+ * EDX: guest tsc incarnation (migration count)
+ * Sub-leaf 1: EAX: tsc offset low part
+ * EBX: tsc offset high part
+ * ECX: multiplicator for tsc->ns conversion
+ * EDX: shift amount for tsc->ns conversion
+ * Sub-leaf 2: EAX: host tsc frequency in kHz
+ */
+
+#define XEN_CPUID_TSC_EMULATED (1u << 0)
+#define XEN_CPUID_HOST_TSC_RELIABLE (1u << 1)
+#define XEN_CPUID_RDTSCP_INSTR_AVAIL (1u << 2)
+
+#define XEN_CPUID_TSC_MODE_DEFAULT (0)
+#define XEN_CPUID_TSC_MODE_ALWAYS_EMULATE (1u)
+#define XEN_CPUID_TSC_MODE_NEVER_EMULATE (2u)
+#define XEN_CPUID_TSC_MODE_PVRDTSCP (3u)
+
/*
* Leaf 5 (0x40000x04)
* HVM-specific features
diff --git a/include/xtf/time.h b/include/xtf/time.h
new file mode 100644
index 000000000000..1e5895122a34
--- /dev/null
+++ b/include/xtf/time.h
@@ -0,0 +1,8 @@
+#ifndef __XTF_TIME_H_
+#define __XTF_TIME_H_
+
+#include <arch/time.h>
+
+void xtf_init_time(void);
+
+#endif /* __XTF_TIME_H_ */
--
2.55.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |