aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/apic.c
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-10-29 10:40:14 +0100
committerKeir Fraser <keir@xen.org>2010-10-29 10:40:14 +0100
commitfd1291a826e17108d7c7f20c887847daba451ef4 (patch)
tree963f0da4548bc87d110ff0a4982f1b14f913be29 /xen/arch/x86/apic.c
parent9dbd1007376011d99e6af1dd703c2cc437e7fda0 (diff)
downloadxen-fd1291a826e17108d7c7f20c887847daba451ef4.tar.gz
xen-fd1291a826e17108d7c7f20c887847daba451ef4.tar.bz2
xen-fd1291a826e17108d7c7f20c887847daba451ef4.zip
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] =3D 1 as documented in the Intel Architecture 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@intel.com> Signed-off-by: Wei Gang <gang.wei@intel.com> Signed-off-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/apic.c')
-rw-r--r--xen/arch/x86/apic.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c
index ff8198d7a0..7c1913a18e 100644
--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -38,6 +38,15 @@
#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 __read_mostly;
+static int tdt_enable __initdata = 1;
+boolean_param("tdt", tdt_enable);
+
static struct {
int active;
/* r/w apic fields */
@@ -1198,6 +1207,13 @@ static void __setup_APIC_LVTT(unsigned int clocks)
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_enable && 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,6 +1382,12 @@ int reprogram_timer(s_time_t timeout)
if ( !cpu_has_apic )
return 1;
+ if ( tdt_enabled )
+ {
+ wrmsrl(MSR_IA32_TSC_DEADLINE, timeout ? stime2tsc(timeout) : 0);
+ return 1;
+ }
+
if ( timeout && ((expire = timeout - NOW()) > 0) )
apic_tmict = min_t(u64, (bus_scale * expire) >> 18, UINT_MAX);