public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch] x86, apic: use tsc deadline for oneshot when available
@ 2012-10-22 21:37 Suresh Siddha
  2012-10-31  1:05 ` Venki Pallipadi
  2012-11-02 10:32 ` [tip:x86/timers] x86: apic: Use " tip-bot for Suresh Siddha
  0 siblings, 2 replies; 3+ messages in thread
From: Suresh Siddha @ 2012-10-22 21:37 UTC (permalink / raw)
  To: tglx, hpa, mingo; +Cc: linux-kernel, venki, len.brown

Thomas, You wanted to run some tests with this, right? Please give it a
try and see if this is ok to be pushed to the -tip.

thanks,
suresh
--8<--
From: Suresh Siddha <suresh.b.siddha@intel.com>
Subject: x86, apic: use tsc deadline for oneshot when available

If the TSC deadline mode is supported, LAPIC timer one-shot mode can be
implemented using IA32_TSC_DEADLINE MSR. An interrupt will be generated
when the TSC value equals or exceeds the value in the IA32_TSC_DEADLINE
MSR.

This enables us to skip the APIC calibration during boot. Also,
in xapic mode, this enables us to skip the uncached apic access
to re-arm the APIC timer.

As this timer ticks at the high frequency TSC rate, we use the
TSC_DIVISOR (32) to work with the 32-bit restrictions in the clockevent
API's to avoid 64-bit divides etc (frequency is u32 and "unsigned long"
in the set_next_event(), max_delta limits the next event to 32-bit for
32-bit kernel).

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
---
 Documentation/kernel-parameters.txt |    4 ++
 arch/x86/include/asm/msr-index.h    |    2 +
 arch/x86/kernel/apic/apic.c         |   66 ++++++++++++++++++++++++++---------
 3 files changed, 55 insertions(+), 17 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9776f06..4aa9ca0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1304,6 +1304,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	lapic		[X86-32,APIC] Enable the local APIC even if BIOS
 			disabled it.
 
+	lapic=		[x86,APIC] "notscdeadline" Do not use TSC deadline
+			value for LAPIC timer one-shot implementation. Default
+			back to the programmable timer unit in the LAPIC.
+
 	lapic_timer_c2_ok	[X86,APIC] trust the local apic timer
 			in C2 power state.
 
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 7f0edce..e400cdb 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -337,6 +337,8 @@
 #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE	(1ULL << 38)
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE	(1ULL << 39)
 
+#define MSR_IA32_TSC_DEADLINE		0x000006E0
+
 /* P4/Xeon+ specific */
 #define MSR_IA32_MCG_EAX		0x00000180
 #define MSR_IA32_MCG_EBX		0x00000181
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b17416e..b0c49b1 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -90,21 +90,6 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
  */
 DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID);
 
-/*
- * Knob to control our willingness to enable the local APIC.
- *
- * +1=force-enable
- */
-static int force_enable_local_apic __initdata;
-/*
- * APIC command line parameters
- */
-static int __init parse_lapic(char *arg)
-{
-	force_enable_local_apic = 1;
-	return 0;
-}
-early_param("lapic", parse_lapic);
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 
@@ -133,6 +118,25 @@ static inline void imcr_apic_to_pic(void)
 }
 #endif
 
+/*
+ * Knob to control our willingness to enable the local APIC.
+ *
+ * +1=force-enable
+ */
+static int force_enable_local_apic __initdata;
+/*
+ * APIC command line parameters
+ */
+static int __init parse_lapic(char *arg)
+{
+	if (config_enabled(CONFIG_X86_32) && !arg)
+		force_enable_local_apic = 1;
+	else if (!strncmp(arg, "notscdeadline", 13))
+		setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
+	return 0;
+}
+early_param("lapic", parse_lapic);
+
 #ifdef CONFIG_X86_64
 static int apic_calibrate_pmtmr __initdata;
 static __init int setup_apicpmtimer(char *s)
@@ -315,6 +319,7 @@ int lapic_get_maxlvt(void)
 
 /* Clock divisor */
 #define APIC_DIVISOR 16
+#define TSC_DIVISOR  32
 
 /*
  * This function sets up the local APIC timer, with a timeout of
@@ -333,6 +338,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 	lvtt_value = LOCAL_TIMER_VECTOR;
 	if (!oneshot)
 		lvtt_value |= APIC_LVT_TIMER_PERIODIC;
+	else if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
+		lvtt_value |= APIC_LVT_TIMER_TSCDEADLINE;
+
 	if (!lapic_is_integrated())
 		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
 
@@ -341,6 +349,11 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 
 	apic_write(APIC_LVTT, lvtt_value);
 
+	if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) {
+		printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
+		return;
+	}
+
 	/*
 	 * Divide PICLK by 16
 	 */
@@ -453,6 +466,15 @@ static int lapic_next_event(unsigned long delta,
 	return 0;
 }
 
+static int lapic_next_deadline(unsigned long delta,
+			       struct clock_event_device *evt)
+{
+	u64 tsc;
+	rdtscll(tsc);
+	wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
+	return 0;
+}
+
 /*
  * Setup the lapic timer in periodic or oneshot mode
  */
@@ -533,7 +555,15 @@ static void __cpuinit setup_APIC_timer(void)
 	memcpy(levt, &lapic_clockevent, sizeof(*levt));
 	levt->cpumask = cpumask_of(smp_processor_id());
 
-	clockevents_register_device(levt);
+	if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
+		levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC |
+				    CLOCK_EVT_FEAT_DUMMY);
+		levt->set_next_event = lapic_next_deadline;
+		clockevents_config_and_register(levt,
+						(tsc_khz / TSC_DIVISOR) * 1000,
+						0xF, ~0UL);
+	} else
+		clockevents_register_device(levt);
 }
 
 /*
@@ -661,7 +691,9 @@ static int __init calibrate_APIC_clock(void)
 	 * in the clockevent structure and return.
 	 */
 
-	if (lapic_timer_frequency) {
+	if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
+		return 0;
+	} else if (lapic_timer_frequency) {
 		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
 				lapic_timer_frequency);
 		lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [patch] x86, apic: use tsc deadline for oneshot when available
  2012-10-22 21:37 [patch] x86, apic: use tsc deadline for oneshot when available Suresh Siddha
@ 2012-10-31  1:05 ` Venki Pallipadi
  2012-11-02 10:32 ` [tip:x86/timers] x86: apic: Use " tip-bot for Suresh Siddha
  1 sibling, 0 replies; 3+ messages in thread
From: Venki Pallipadi @ 2012-10-31  1:05 UTC (permalink / raw)
  To: Suresh Siddha
  Cc: Thomas Gleixner, H. Peter Anvin, Ingo Molnar,
	Linux Kernel Mailing List, Brown, Len

Patch looks good.

Acked-by: Venkatesh Pallipadi <venki@google.com>

On Mon, Oct 22, 2012 at 2:37 PM, Suresh Siddha
<suresh.b.siddha@intel.com> wrote:
>
> Thomas, You wanted to run some tests with this, right? Please give it a
> try and see if this is ok to be pushed to the -tip.
>
> thanks,
> suresh
> --8<--
> From: Suresh Siddha <suresh.b.siddha@intel.com>
> Subject: x86, apic: use tsc deadline for oneshot when available
>
> If the TSC deadline mode is supported, LAPIC timer one-shot mode can be
> implemented using IA32_TSC_DEADLINE MSR. An interrupt will be generated
> when the TSC value equals or exceeds the value in the IA32_TSC_DEADLINE
> MSR.
>
> This enables us to skip the APIC calibration during boot. Also,
> in xapic mode, this enables us to skip the uncached apic access
> to re-arm the APIC timer.
>
> As this timer ticks at the high frequency TSC rate, we use the
> TSC_DIVISOR (32) to work with the 32-bit restrictions in the clockevent
> API's to avoid 64-bit divides etc (frequency is u32 and "unsigned long"
> in the set_next_event(), max_delta limits the next event to 32-bit for
> 32-bit kernel).
>
> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
> ---
>  Documentation/kernel-parameters.txt |    4 ++
>  arch/x86/include/asm/msr-index.h    |    2 +
>  arch/x86/kernel/apic/apic.c         |   66 ++++++++++++++++++++++++++---------
>  3 files changed, 55 insertions(+), 17 deletions(-)
>
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 9776f06..4aa9ca0 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -1304,6 +1304,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>         lapic           [X86-32,APIC] Enable the local APIC even if BIOS
>                         disabled it.
>
> +       lapic=          [x86,APIC] "notscdeadline" Do not use TSC deadline
> +                       value for LAPIC timer one-shot implementation. Default
> +                       back to the programmable timer unit in the LAPIC.
> +
>         lapic_timer_c2_ok       [X86,APIC] trust the local apic timer
>                         in C2 power state.
>
> diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
> index 7f0edce..e400cdb 100644
> --- a/arch/x86/include/asm/msr-index.h
> +++ b/arch/x86/include/asm/msr-index.h
> @@ -337,6 +337,8 @@
>  #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE     (1ULL << 38)
>  #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE   (1ULL << 39)
>
> +#define MSR_IA32_TSC_DEADLINE          0x000006E0
> +
>  /* P4/Xeon+ specific */
>  #define MSR_IA32_MCG_EAX               0x00000180
>  #define MSR_IA32_MCG_EBX               0x00000181
> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
> index b17416e..b0c49b1 100644
> --- a/arch/x86/kernel/apic/apic.c
> +++ b/arch/x86/kernel/apic/apic.c
> @@ -90,21 +90,6 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
>   */
>  DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID);
>
> -/*
> - * Knob to control our willingness to enable the local APIC.
> - *
> - * +1=force-enable
> - */
> -static int force_enable_local_apic __initdata;
> -/*
> - * APIC command line parameters
> - */
> -static int __init parse_lapic(char *arg)
> -{
> -       force_enable_local_apic = 1;
> -       return 0;
> -}
> -early_param("lapic", parse_lapic);
>  /* Local APIC was disabled by the BIOS and enabled by the kernel */
>  static int enabled_via_apicbase;
>
> @@ -133,6 +118,25 @@ static inline void imcr_apic_to_pic(void)
>  }
>  #endif
>
> +/*
> + * Knob to control our willingness to enable the local APIC.
> + *
> + * +1=force-enable
> + */
> +static int force_enable_local_apic __initdata;
> +/*
> + * APIC command line parameters
> + */
> +static int __init parse_lapic(char *arg)
> +{
> +       if (config_enabled(CONFIG_X86_32) && !arg)
> +               force_enable_local_apic = 1;
> +       else if (!strncmp(arg, "notscdeadline", 13))
> +               setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
> +       return 0;
> +}
> +early_param("lapic", parse_lapic);
> +
>  #ifdef CONFIG_X86_64
>  static int apic_calibrate_pmtmr __initdata;
>  static __init int setup_apicpmtimer(char *s)
> @@ -315,6 +319,7 @@ int lapic_get_maxlvt(void)
>
>  /* Clock divisor */
>  #define APIC_DIVISOR 16
> +#define TSC_DIVISOR  32
>
>  /*
>   * This function sets up the local APIC timer, with a timeout of
> @@ -333,6 +338,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
>         lvtt_value = LOCAL_TIMER_VECTOR;
>         if (!oneshot)
>                 lvtt_value |= APIC_LVT_TIMER_PERIODIC;
> +       else if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
> +               lvtt_value |= APIC_LVT_TIMER_TSCDEADLINE;
> +
>         if (!lapic_is_integrated())
>                 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
>
> @@ -341,6 +349,11 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
>
>         apic_write(APIC_LVTT, lvtt_value);
>
> +       if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) {
> +               printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
> +               return;
> +       }
> +
>         /*
>          * Divide PICLK by 16
>          */
> @@ -453,6 +466,15 @@ static int lapic_next_event(unsigned long delta,
>         return 0;
>  }
>
> +static int lapic_next_deadline(unsigned long delta,
> +                              struct clock_event_device *evt)
> +{
> +       u64 tsc;
> +       rdtscll(tsc);
> +       wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
> +       return 0;
> +}
> +
>  /*
>   * Setup the lapic timer in periodic or oneshot mode
>   */
> @@ -533,7 +555,15 @@ static void __cpuinit setup_APIC_timer(void)
>         memcpy(levt, &lapic_clockevent, sizeof(*levt));
>         levt->cpumask = cpumask_of(smp_processor_id());
>
> -       clockevents_register_device(levt);
> +       if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
> +               levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC |
> +                                   CLOCK_EVT_FEAT_DUMMY);
> +               levt->set_next_event = lapic_next_deadline;
> +               clockevents_config_and_register(levt,
> +                                               (tsc_khz / TSC_DIVISOR) * 1000,
> +                                               0xF, ~0UL);
> +       } else
> +               clockevents_register_device(levt);
>  }
>
>  /*
> @@ -661,7 +691,9 @@ static int __init calibrate_APIC_clock(void)
>          * in the clockevent structure and return.
>          */
>
> -       if (lapic_timer_frequency) {
> +       if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
> +               return 0;
> +       } else if (lapic_timer_frequency) {
>                 apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
>                                 lapic_timer_frequency);
>                 lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:x86/timers] x86: apic: Use tsc deadline for oneshot when available
  2012-10-22 21:37 [patch] x86, apic: use tsc deadline for oneshot when available Suresh Siddha
  2012-10-31  1:05 ` Venki Pallipadi
@ 2012-11-02 10:32 ` tip-bot for Suresh Siddha
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for Suresh Siddha @ 2012-11-02 10:32 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, suresh.b.siddha, tglx

Commit-ID:  279f1461432ccdec0b98c0bcbe0a8e2c0f6fdda5
Gitweb:     http://git.kernel.org/tip/279f1461432ccdec0b98c0bcbe0a8e2c0f6fdda5
Author:     Suresh Siddha <suresh.b.siddha@intel.com>
AuthorDate: Mon, 22 Oct 2012 14:37:58 -0700
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 2 Nov 2012 11:23:37 +0100

x86: apic: Use tsc deadline for oneshot when available

If the TSC deadline mode is supported, LAPIC timer one-shot mode can be
implemented using IA32_TSC_DEADLINE MSR. An interrupt will be generated
when the TSC value equals or exceeds the value in the IA32_TSC_DEADLINE
MSR.

This enables us to skip the APIC calibration during boot. Also, in
xapic mode, this enables us to skip the uncached apic access to re-arm
the APIC timer.

As this timer ticks at the high frequency TSC rate, we use the
TSC_DIVISOR (32) to work with the 32-bit restrictions in the
clockevent API's to avoid 64-bit divides etc (frequency is u32 and
"unsigned long" in the set_next_event(), max_delta limits the next
event to 32-bit for 32-bit kernel).

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: venki@google.com
Cc: len.brown@intel.com
Link: http://lkml.kernel.org/r/1350941878.6017.31.camel@sbsiddha-desk.sc.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/kernel-parameters.txt |    4 ++
 arch/x86/include/asm/msr-index.h    |    2 +
 arch/x86/kernel/apic/apic.c         |   73 +++++++++++++++++++++++++---------
 3 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9776f06..4aa9ca0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1304,6 +1304,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	lapic		[X86-32,APIC] Enable the local APIC even if BIOS
 			disabled it.
 
+	lapic=		[x86,APIC] "notscdeadline" Do not use TSC deadline
+			value for LAPIC timer one-shot implementation. Default
+			back to the programmable timer unit in the LAPIC.
+
 	lapic_timer_c2_ok	[X86,APIC] trust the local apic timer
 			in C2 power state.
 
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 7f0edce..e400cdb 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -337,6 +337,8 @@
 #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE	(1ULL << 38)
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE	(1ULL << 39)
 
+#define MSR_IA32_TSC_DEADLINE		0x000006E0
+
 /* P4/Xeon+ specific */
 #define MSR_IA32_MCG_EAX		0x00000180
 #define MSR_IA32_MCG_EBX		0x00000181
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b17416e..b994cc8 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -90,21 +90,6 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
  */
 DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID);
 
-/*
- * Knob to control our willingness to enable the local APIC.
- *
- * +1=force-enable
- */
-static int force_enable_local_apic __initdata;
-/*
- * APIC command line parameters
- */
-static int __init parse_lapic(char *arg)
-{
-	force_enable_local_apic = 1;
-	return 0;
-}
-early_param("lapic", parse_lapic);
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 
@@ -133,6 +118,25 @@ static inline void imcr_apic_to_pic(void)
 }
 #endif
 
+/*
+ * Knob to control our willingness to enable the local APIC.
+ *
+ * +1=force-enable
+ */
+static int force_enable_local_apic __initdata;
+/*
+ * APIC command line parameters
+ */
+static int __init parse_lapic(char *arg)
+{
+	if (config_enabled(CONFIG_X86_32) && !arg)
+		force_enable_local_apic = 1;
+	else if (!strncmp(arg, "notscdeadline", 13))
+		setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
+	return 0;
+}
+early_param("lapic", parse_lapic);
+
 #ifdef CONFIG_X86_64
 static int apic_calibrate_pmtmr __initdata;
 static __init int setup_apicpmtimer(char *s)
@@ -315,6 +319,7 @@ int lapic_get_maxlvt(void)
 
 /* Clock divisor */
 #define APIC_DIVISOR 16
+#define TSC_DIVISOR  32
 
 /*
  * This function sets up the local APIC timer, with a timeout of
@@ -333,6 +338,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 	lvtt_value = LOCAL_TIMER_VECTOR;
 	if (!oneshot)
 		lvtt_value |= APIC_LVT_TIMER_PERIODIC;
+	else if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
+		lvtt_value |= APIC_LVT_TIMER_TSCDEADLINE;
+
 	if (!lapic_is_integrated())
 		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
 
@@ -341,6 +349,11 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 
 	apic_write(APIC_LVTT, lvtt_value);
 
+	if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) {
+		printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
+		return;
+	}
+
 	/*
 	 * Divide PICLK by 16
 	 */
@@ -453,6 +466,16 @@ static int lapic_next_event(unsigned long delta,
 	return 0;
 }
 
+static int lapic_next_deadline(unsigned long delta,
+			       struct clock_event_device *evt)
+{
+	u64 tsc;
+
+	rdtscll(tsc);
+	wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
+	return 0;
+}
+
 /*
  * Setup the lapic timer in periodic or oneshot mode
  */
@@ -533,7 +556,15 @@ static void __cpuinit setup_APIC_timer(void)
 	memcpy(levt, &lapic_clockevent, sizeof(*levt));
 	levt->cpumask = cpumask_of(smp_processor_id());
 
-	clockevents_register_device(levt);
+	if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
+		levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC |
+				    CLOCK_EVT_FEAT_DUMMY);
+		levt->set_next_event = lapic_next_deadline;
+		clockevents_config_and_register(levt,
+						(tsc_khz / TSC_DIVISOR) * 1000,
+						0xF, ~0UL);
+	} else
+		clockevents_register_device(levt);
 }
 
 /*
@@ -661,7 +692,9 @@ static int __init calibrate_APIC_clock(void)
 	 * in the clockevent structure and return.
 	 */
 
-	if (lapic_timer_frequency) {
+	if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
+		return 0;
+	} else if (lapic_timer_frequency) {
 		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
 				lapic_timer_frequency);
 		lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
@@ -674,6 +707,9 @@ static int __init calibrate_APIC_clock(void)
 		return 0;
 	}
 
+	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
+		    "calibrating APIC timer ...\n");
+
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
@@ -811,9 +847,6 @@ void __init setup_boot_APIC_clock(void)
 		return;
 	}
 
-	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
-		    "calibrating APIC timer ...\n");
-
 	if (calibrate_APIC_clock()) {
 		/* No broadcast on UP ! */
 		if (num_possible_cpus() > 1)

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-11-02 10:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-22 21:37 [patch] x86, apic: use tsc deadline for oneshot when available Suresh Siddha
2012-10-31  1:05 ` Venki Pallipadi
2012-11-02 10:32 ` [tip:x86/timers] x86: apic: Use " tip-bot for Suresh Siddha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox