diff options
author | Keir Fraser <keir@xen.org> | 2010-10-29 10:40:14 +0100 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-10-29 10:40:14 +0100 |
commit | fd1291a826e17108d7c7f20c887847daba451ef4 (patch) | |
tree | 963f0da4548bc87d110ff0a4982f1b14f913be29 /xen/arch/x86/apic.c | |
parent | 9dbd1007376011d99e6af1dd703c2cc437e7fda0 (diff) | |
download | xen-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.c | 28 |
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); |