X86: Prefer TSC-deadline timer in Xen
The new TSC Deadline Timer offers system software a low overhead
per-logical-thread deadline timer in TSC units.
The timer is implemented via a new architectural 64-bit register,
IA32_TSC_DEADLINE_MSR. Reads and writes of this MSR occur in program order,
but are non-serializing.
The support for this feature is indicated by
CPUID.01H:ECX.TSC_Deadline[bit 24] = 1 as documented in the Intel Architectures
Software Developer's Manual.
The LOCAL APIC on new processors has a mode where its underlying hardware timer
can now be accessed via the non-serializing IA32_TSC_DEADLINE_MSR in TSC tick
units.
If this mode is present, prefer it over the traditional LAPIC timer mode.
KERN_DEBUG dmesg will print "TSC deadline timer enabled" when TDT is used.
Bootparam "tdt_off" is available to revert to LAPIC timer mode.
This patch is based on original work by Len Brown for Linux kernel.
cc: Len Brown <len.brown@xxxxxxxxx>
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
diff -r 00b92112b055 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c Wed Oct 20 17:26:51 2010 +0100
+++ b/xen/arch/x86/apic.c Fri Oct 29 19:24:56 2010 +0800
@@ -37,6 +37,15 @@
#include <asm/asm_defns.h> /* for BUILD_SMP_INTERRUPT */
#include <mach_apic.h>
#include <io_ports.h>
+
+#define APIC_TIMER_MODE_ONESHOT (0 << 17)
+#define APIC_TIMER_MODE_PERIODIC (1 << 17)
+#define APIC_TIMER_MODE_TSC_DEADLINE (2 << 17)
+#define APIC_TIMER_MODE_MASK (3 << 17)
+
+static int tdt_enabled;
+static int tdt_disable;
+boolean_param("tdt_off", tdt_disable);
static struct {
int active;
@@ -1198,6 +1207,13 @@ static void __setup_APIC_LVTT(unsigned i
lvtt_value = /*APIC_LVT_TIMER_PERIODIC |*/ LOCAL_TIMER_VECTOR;
if (!APIC_INTEGRATED(ver))
lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
+
+ if (tdt_enabled)
+ {
+ lvtt_value &= (~APIC_TIMER_MODE_MASK);
+ lvtt_value |= APIC_TIMER_MODE_TSC_DEADLINE;
+ }
+
apic_write_around(APIC_LVTT, lvtt_value);
tmp_value = apic_read(APIC_TDCR);
@@ -1311,6 +1327,12 @@ void __init setup_boot_APIC_clock(void)
calibrate_APIC_clock();
+ if (!tdt_disable && boot_cpu_has(X86_FEATURE_TSC_DEADLINE))
+ {
+ printk(KERN_DEBUG "TSC deadline timer enabled\n");
+ tdt_enabled = 1;
+ }
+
setup_APIC_timer();
local_irq_restore(flags);
@@ -1360,12 +1382,24 @@ int reprogram_timer(s_time_t timeout)
if ( !cpu_has_apic )
return 1;
- if ( timeout && ((expire = timeout - NOW()) > 0) )
- apic_tmict = min_t(u64, (bus_scale * expire) >> 18, UINT_MAX);
-
- apic_write(APIC_TMICT, (unsigned long)apic_tmict);
-
- return apic_tmict || !timeout;
+ if ( tdt_enabled )
+ {
+ u64 tsc = 0;
+
+ if ( timeout )
+ tsc = stime2tsc(timeout);
+
+ wrmsrl(MSR_IA32_TSC_DEADLINE, tsc);
+ }
+ else
+ {
+ if ( timeout && ((expire = timeout - NOW()) > 0) )
+ apic_tmict = min_t(u64, (bus_scale * expire) >> 18, UINT_MAX);
+
+ apic_write(APIC_TMICT, (unsigned long)apic_tmict);
+ }
+
+ return apic_tmict || !timeout || tdt_enabled;
}
fastcall void smp_apic_timer_interrupt(struct cpu_user_regs * regs)
diff -r 00b92112b055 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Wed Oct 20 17:26:51 2010 +0100
+++ b/xen/arch/x86/time.c Fri Oct 29 19:28:07 2010 +0800
@@ -662,26 +662,31 @@ static void __init init_platform_timer(v
freq_string(pts->frequency), pts->name);
}
-void cstate_restore_tsc(void)
+u64 stime2tsc(s_time_t stime)
{
struct cpu_time *t;
struct time_scale sys_to_tsc;
s_time_t stime_delta;
- u64 new_tsc;
-
+ u64 tsc;
+
+ t = &this_cpu(cpu_time);
+ sys_to_tsc = scale_reciprocal(t->tsc_scale);
+
+ stime_delta = stime - t->stime_local_stamp;
+ if ( stime_delta < 0 )
+ stime_delta = 0;
+
+ tsc = t->local_tsc_stamp + scale_delta(stime_delta, &sys_to_tsc);
+
+ return tsc;
+}
+
+void cstate_restore_tsc(void)
+{
if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
return;
- t = &this_cpu(cpu_time);
- sys_to_tsc = scale_reciprocal(t->tsc_scale);
-
- stime_delta = read_platform_stime() - t->stime_master_stamp;
- if ( stime_delta < 0 )
- stime_delta = 0;
-
- new_tsc = t->local_tsc_stamp + scale_delta(stime_delta, &sys_to_tsc);
-
- write_tsc(new_tsc);
+ write_tsc(stime2tsc(read_platform_stime()));
}
/***************************************************************************
diff -r 00b92112b055 xen/include/asm-x86/cpufeature.h
--- a/xen/include/asm-x86/cpufeature.h Wed Oct 20 17:26:51 2010 +0100
+++ b/xen/include/asm-x86/cpufeature.h Fri Oct 29 19:21:36 2010 +0800
@@ -99,6 +99,7 @@
#define X86_FEATURE_SSE4_2 (4*32+20) /* Streaming SIMD Extensions 4.2 */
#define X86_FEATURE_X2APIC (4*32+21) /* Extended xAPIC */
#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE (4*32+24) /* "tdt" TSC Deadline Timer */
#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
#define X86_FEATURE_OSXSAVE (4*32+27) /* OSXSAVE */
#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running under some hypervisor */
diff -r 00b92112b055 xen/include/asm-x86/msr-index.h
--- a/xen/include/asm-x86/msr-index.h Wed Oct 20 17:26:51 2010 +0100
+++ b/xen/include/asm-x86/msr-index.h Fri Oct 29 19:21:36 2010 +0800
@@ -327,6 +327,8 @@
#define MSR_IA32_MISC_ENABLE_MONITOR_ENABLE (1<<18)
#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1<<22)
#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1<<23)
+
+#define MSR_IA32_TSC_DEADLINE 0x000006E0
/* Intel Model 6 */
#define MSR_P6_EVNTSEL0 0x00000186
diff -r 00b92112b055 xen/include/xen/time.h
--- a/xen/include/xen/time.h Wed Oct 20 17:26:51 2010 +0100
+++ b/xen/include/xen/time.h Fri Oct 29 19:21:36 2010 +0800
@@ -31,6 +31,7 @@ typedef s64 s_time_t;
typedef s64 s_time_t;
s_time_t get_s_time(void);
+u64 stime2tsc(s_time_t stime);
unsigned long get_localtime(struct domain *d);
struct tm {
tdt-host-support.patch
Description: tdt-host-support.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|