High resolution timer updates and x86_64 support - V2
Subsystems (14)
cover High resolution timer updates and x86_64 support - V2
The following patch series contains:
- dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
- updates and improvements to high resolution timer / dynticks
- high resolution timer / dynticks support for x86_64
The x86_64 support is based on an initial patch from Chris Wright. Thanks Chris !
The patch set has been tested in the -hrt and -rt trees for quite a while and the initial problems have been sorted out. Thanks to the folks from the PowerTop project for testing and feedback.
The -hrt tree at http://www.tglx.de/projects/hrtimers/2.6.22-rc4/ contains also an hpet force patch series from Venki Pallipadi, but I leave this up to Venki to send it mainline wards.
Changes since V1:
- simplified the idle breakage fixup
- fixed a resume bug (making the famous VAIO work again)
- added a clocksource settimeofday hook for PPC (Tony Breeds)
Thanks,
tglx
PATCH 1/25 NOHZ: Fix nox x86 dyntick idle handling
The cpuidle patches moved the tick nohz handling from irq_exit into the inner idle loop. The change is correct as it covers non interrupt based wakeups (e.g DMA) on x86 as well, but the move breaks ARM, SH and SPARC64.
Keep the original implementation and deselet the irq exit code for those architectures which have non irq idle wakeups.
This way the non affected architectures are not burdened with the extra changes in the idle implementation.
--- arch/i386/Kconfig | 4 ++++ kernel/softirq.c | 5 +++++ 2 files changed, 9 insertions(+)
arch/i386/Kconfig +4 -0
@@ -31,6 +31,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST default y depends on X86_LOCAL_APIC +config NONIRQ_WAKEUP + bool + default y + config LOCKDEP_SUPPORT bool default y
kernel/softirq.c +5 -0
@@ -304,6 +304,11 @@ void irq_exit(void)if (!in_interrupt () &&local_softirq_pending ())invoke_softirq (); +#if defined(CONFIG_NO_HZ ) && !defined(CONFIG_NONIRQ_WAKEUP ) +/* Make sure that timer wheel updates are propagated */ +if (!in_interrupt () &&idle_cpu (smp_processor_id ()) && !need_resched ()) + tick_nohz_stop_sched_tick();a +#endif preempt_enable_no_resched (); }
Re: [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling
kernel/softirq.c void irq_exit(void) · line 313
Quoted 7 lines · Thomas Gleixner
kernel/softirq.c +5
-0+#if defined(CONFIG_NO_HZ ) && !defined(CONFIG_NONIRQ_WAKEUP ) +/* Make sure that timer wheel updates are propagated */ +if (!in_interrupt () &&idle_cpu (smp_processor_id ()) && !need_resched ()) + tick_nohz_stop_sched_tick();a +#endif preempt_enable_no_resched (); }
The bit above breaks the build for a CONFIG_NO_HZ build without CONFIG_NONIRQ_WAKEUP -- please remove the extra "a" after tick_nohz_stop_sched_tick(); before applying this.
Regards,
bero
Re: [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling
Quoted 13 lines · Bernhard Rosenkraenzer
Review
Quoted 7 lines · Thomas Gleixner
(quoted diff) +5
-0+#if defined(CONFIG_NO_HZ) && !defined(CONFIG_NONIRQ_WAKEUP) + /* Make sure that timer wheel updates are propagated */ + if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched()) + tick_nohz_stop_sched_tick();a +#endif preempt_enable_no_resched(); }The bit above breaks the build for a
CONFIG_NO_HZbuild withoutCONFIG_NONIRQ_WAKEUP-- please remove the extra "a" aftertick_nohz_stop_sched_tick(); before applying this.
Oops. Must have happened when I edited the mailbox. Replacement patch below:
tglx
--------------------->
Subject: NOHZ: Fix nox x86 dyntick idle handling
The cpuidle patches moved the tick nohz handling from irq_exit into the inner idle loop. The change is correct as it covers non interrupt based wakeups (e.g DMA) on x86 as well, but the move breaks ARM, SH and SPARC64.
Keep the original implementation and deselet the irq exit code for those architectures which have no irq idle wakeups.
This way the non affected architectures are not burdened with the extra changes in the idle implementation.
--- arch/i386/Kconfig | 4 ++++ kernel/softirq.c | 5 +++++ 2 files changed, 9 insertions(+)
arch/i386/Kconfig +4 -0
@@ -31,6 +31,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST default y depends on X86_LOCAL_APIC +config NONIRQ_WAKEUP + bool + default y + config LOCKDEP_SUPPORT bool default y
kernel/softirq.c +5 -0
@@ -304,6 +304,11 @@ void irq_exit(void)if (!in_interrupt () &&local_softirq_pending ())invoke_softirq (); +#if defined(CONFIG_NO_HZ ) && !defined(CONFIG_NONIRQ_WAKEUP ) +/* Make sure that timer wheel updates are propagated */ +if (!in_interrupt () &&idle_cpu (smp_processor_id ()) && !need_resched ()) +tick_nohz_stop_sched_tick (); +#endif preempt_enable_no_resched (); }
PATCH 2/25 ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown
In reply to Thomas GleixnerFrom: Udo A. Steinberg <[email protected]>
The chipset doc for IHC4 tells us:
1.In general, software should not attempt any non-posted accesses during arbiter disable except to the ICH4's power management registers. This implies that interrupt handlers for any unmasked hardware interrupts and SMI/NMI should check ARB_DIS status before reading from ICH devices.
So it's not a good idea to access ICH devices after arbiter shut down.
--- drivers/acpi/processor_idle.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/acpi/processor_idle.c +6 -1
@@ -978,6 +978,12 @@ static int acpi_idle_enter_c3(struct cpureturn 0 ; } +/* +* Must be done before busmaster disable as we might need to +* access HPET ! +*/ +acpi_state_timer_broadcast (pr, cx,1 ); +/* disable bus master */ if (pr->flags.bm_check) {spin_lock (&c3_lock);
@@ -997,7 +1003,6 @@ static int acpi_idle_enter_c3(struct cpu/* Get start time (ticks) */ t1 =inl (acpi_gbl_FADT.xpm_timer_block.address); -acpi_state_timer_broadcast (pr, cx,1 );acpi_idle_do_entry (cx); t2 =inl (acpi_gbl_FADT.xpm_timer_block.address);
PATCH 3/25 Clockevents remove prototypes of removed functions
In reply to Thomas Gleixner--- include/linux/clockchips.h | 4 ---- 1 file changed, 4 deletions(-)
include/linux/clockchips.h +0 -4
@@ -119,10 +119,6 @@ extern void clockevents_register_device(extern void clockevents_exchange_device (struct clock_event_device *old,struct clock_event_device *new); -extern -struct clock_event_device *clockevents_request_device (unsigned int features, -cpumask_t cpumask); -extern void clockevents_release_device (struct clock_event_device *dev);extern void clockevents_set_mode (struct clock_event_device *dev,enum clock_event_mode mode);extern int clockevents_register_notifier (struct notifier_block *nb);
PATCH 4/25 Timekeeping: Fixup shadow variable argument
In reply to Thomas Gleixnerclocksource_adjust() has a clock argument, which shadows the file global clock variable. Fix this up.
--- kernel/time/timekeeping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/time/timekeeping.c +2 -2
@@ -401,7 +401,7 @@ static __always_inline int clocksource_b* this is optimized for the most common adjustments of -1,0,1, * for other values we can do a bit more work. */ -static void clocksource_adjust (struct clocksource *clock,s64 offset) +static void clocksource_adjust (s64 offset) {s64 error, interval = clock->cycle_interval;int adj;
@@ -476,7 +476,7 @@ void update_wall_time(void) }/* correct the clock when NTP error is too big */ -clocksource_adjust (clock, offset); +clocksource_adjust (offset);/* store full nanoseconds into xtime */ xtime.tv_nsec = (s64 )clock->xtime_nsec >> clock->shift;
PATCH 5/25 timer.c cleanup recently introduced whitespace damage
In reply to Thomas Gleixner--- kernel/timer.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
kernel/timer.c +12 -12
@@ -103,14 +103,14 @@ static inline tvec_base_t *tbase_get_basstatic inline void timer_set_deferrable (struct timer_list *timer) { timer->base = ((tvec_base_t *)((unsigned long )(timer->base) | -TBASE_DEFERRABLE_FLAG )); +TBASE_DEFERRABLE_FLAG )); }static inline void timer_set_base (struct timer_list *timer,tvec_base_t *new_base) { timer->base = (tvec_base_t *)((unsigned long )(new_base) | -tbase_get_deferrable (timer->base)); +tbase_get_deferrable (timer->base)); }/**
@@ -445,10 +445,10 @@ EXPORT_SYMBOL(__mod_timer);void add_timer_on (struct timer_list *timer,int cpu) {tvec_base_t *base =per_cpu (tvec_bases, cpu); -unsigned long flags; +unsigned long flags;timer_stats_timer_set_start_info (timer); -BUG_ON (timer_pending (timer) || !timer->function); +BUG_ON (timer_pending (timer) || !timer->function);spin_lock_irqsave (&base->lock, flags);timer_set_base (timer, base);internal_add_timer (base, timer);
@@ -627,7 +627,7 @@ static inline void __run_timers(tvec_baswhile (time_after_eq (jiffies, base->timer_jiffies)) {struct list_head work_list;struct list_head *head = &work_list; -int index = base->timer_jiffies &TVR_MASK ; +int index = base->timer_jiffies &TVR_MASK ;/* * Cascade timers:
@@ -644,8 +644,8 @@ static inline void __run_timers(tvec_basunsigned long data; timer = list_first_entry(head, struct timer_list,entry); - fn = timer->function; - data = timer->data; + fn = timer->function; + data = timer->data;timer_stats_account_timer (timer);
@@ -689,8 +689,8 @@ static unsigned long __next_timer_interr index = slot = timer_jiffies &TVR_MASK ; do { list_for_each_entry(nte, base->tv1.vec + slot, entry) { - if (tbase_get_deferrable(nte->base)) - continue; + if (tbase_get_deferrable(nte->base)) + continue; found = 1; expires = nte->expires;
@@ -834,7 +834,7 @@ void update_process_times(int user_tick)if (rcu_pending (cpu))rcu_check_callbacks (cpu, user_tick);scheduler_tick (); -run_posix_cpu_timers (p); +run_posix_cpu_timers (p); }/*
@@ -909,7 +909,7 @@ static inline void update_times(unsignedupdate_wall_time ();calc_load (ticks); } - +/* * The 64-bit jiffies value is not atomic - you MUST NOT read it * without sampling the sequence number in xtime_lock.
@@ -1105,7 +1105,7 @@ asmlinkage long sys_gettid(void)/** * do_sysinfo - fill in sysinfo struct * @info: pointer to buffer to fill -*/ +*/ int do_sysinfo (struct sysinfo *info) {unsigned long mem_total, sav_total;
PATCH 6/25 clockevents: Fix resume logic
In reply to Thomas GleixnerWe need to make sure, that the clockevent devices are resumed, before the tick is resumed. The current resume logic does not guarantee this.
Add CLOCK_EVT_MODE_RESUME and call the set mode functions of the clock event devices before resuming the tick / oneshot functionality.
Fixup the existing users.
This removes the sysfs entry for the HPET, which is now controlled by the clockevents resume code.
--- arch/arm/mach-davinci/time.c | 2 + arch/arm/mach-imx/time.c | 1 arch/arm/mach-ixp4xx/common.c | 2 + arch/arm/mach-omap1/time.c | 1 arch/arm/plat-omap/timer32k.c | 2 + arch/i386/kernel/apic.c | 3 + arch/i386/kernel/hpet.c | 71 ++------------------------------------ arch/i386/kernel/i8253.c | 26 ++++++------- arch/i386/kernel/vmiclock.c | 1 arch/i386/xen/time.c | 1 arch/sh/kernel/timers/timer-tmu.c | 1 arch/sparc64/kernel/time.c | 1 include/linux/clockchips.h | 1 kernel/time/tick-broadcast.c | 6 ++- kernel/time/tick-common.c | 16 +++++--- 15 files changed, 47 insertions(+), 88 deletions(-)
arch/i386/kernel/apic.c +3 -0
@@ -263,6 +263,9 @@ static void lapic_timer_setup(enum clock v |= (APIC_LVT_MASKED |LOCAL_TIMER_VECTOR );apic_write_around (APIC_LVTT , v);break ; +case CLOCK_EVT_MODE_RESUME : +/* Nothing to do here */ +break ; }local_irq_restore (flags);
arch/i386/kernel/hpet.c +5 -66
92 lines not on this page · raw message
arch/i386/kernel/i8253.c +12 -14
@@ -3,11 +3,11 @@* */ #include <linux/clockchips.h> -#include <linux/spinlock.h> +#include <linux/init.h> +#include <linux/interrupt.h> #include <linux/jiffies.h> -#include <linux/sysdev.h> #include <linux/module.h> -#include <linux/init.h> +#include <linux/spinlock.h> #include <asm/smp.h> #include <asm/delay.h>
@@ -42,26 +42,24 @@ static void init_pit_timer(enum clock_evcase CLOCK_EVT_MODE_PERIODIC :/* binary, mode 2, LSB/MSB, ch 0 */ outb_p (0x34 ,PIT_MODE ); -udelay (10 );outb_p (LATCH &0xff ,PIT_CH0 );/* LSB */ -udelay (10 );outb (LATCH >>8 ,PIT_CH0 );/* MSB */ break ; -/* -* Avoid unnecessary state transitions, as it confuses -* Geode / Cyrix based boxen. -*/ case CLOCK_EVT_MODE_SHUTDOWN : -if (evt->mode ==CLOCK_EVT_MODE_UNUSED ) -break ;case CLOCK_EVT_MODE_UNUSED : -if (evt->mode ==CLOCK_EVT_MODE_SHUTDOWN ) -break ; +outb_p (0x30 ,PIT_MODE ); +outb_p (0 ,PIT_CH0 );/* LSB */ +outb_p (0 ,PIT_CH0 );/* MSB */ +break ; +case CLOCK_EVT_MODE_ONESHOT :/* One shot setup */ outb_p (0x38 ,PIT_MODE ); -udelay (10 ); +break ; + +case CLOCK_EVT_MODE_RESUME : +/* Nothing to do here */ break ; }spin_unlock_irqrestore (&i8253_lock, flags);
include/linux/clockchips.h +1 -0
@@ -23,6 +23,7 @@ enum clock_event_mode {CLOCK_EVT_MODE_SHUTDOWN ,CLOCK_EVT_MODE_PERIODIC ,CLOCK_EVT_MODE_ONESHOT , + CLOCK_EVT_MODE_RESUME, };/* Clock event notification values */
kernel/time/tick-broadcast.c +4 -2
@@ -49,7 +49,7 @@ cpumask_t *tick_get_broadcast_mask(void)*/ static void tick_broadcast_start_periodic (struct clock_event_device *bc) { -if (bc && bc->mode ==CLOCK_EVT_MODE_SHUTDOWN ) +if (bc)tick_setup_periodic (bc,1 ); }
@@ -299,7 +299,7 @@ void tick_suspend_broadcast(void)spin_lock_irqsave (&tick_broadcast_lock, flags); bc = tick_broadcast_device.evtdev; -if (bc && tick_broadcast_device.mode ==TICKDEV_MODE_PERIODIC ) +if (bc)clockevents_set_mode (bc,CLOCK_EVT_MODE_SHUTDOWN );spin_unlock_irqrestore (&tick_broadcast_lock, flags);
@@ -316,6 +316,8 @@ int tick_resume_broadcast(void) bc = tick_broadcast_device.evtdev;if (bc) { +clockevents_set_mode (bc,CLOCK_EVT_MODE_RESUME ); +switch (tick_broadcast_device.mode) {case TICKDEV_MODE_PERIODIC :if (!cpus_empty (tick_broadcast_mask))
kernel/time/tick-common.c +10 -6
@@ -318,12 +318,17 @@ static void tick_resume(void) {struct tick_device *td = &__get_cpu_var (tick_cpu_device);unsigned long flags; +int broadcast =tick_resume_broadcast ();spin_lock_irqsave (&tick_device_lock, flags); -if (td->mode ==TICKDEV_MODE_PERIODIC ) -tick_setup_periodic (td->evtdev,0 ); -else -tick_resume_oneshot (); +clockevents_set_mode (td->evtdev,CLOCK_EVT_MODE_RESUME ); + +if (!broadcast) { +if (td->mode ==TICKDEV_MODE_PERIODIC ) +tick_setup_periodic (td->evtdev,0 ); +else +tick_resume_oneshot (); + }spin_unlock_irqrestore (&tick_device_lock, flags); }
@@ -360,8 +365,7 @@ static int tick_notify(struct notifier_bbreak ;case CLOCK_EVT_NOTIFY_RESUME : -if (!tick_resume_broadcast ()) -tick_resume (); +tick_resume ();break ;default :
arch/arm/mach-davinci/time.c +2 -0
@@ -285,6 +285,8 @@ static void davinci_set_mode(enum clock_case CLOCK_EVT_MODE_SHUTDOWN : t->opts =TIMER_OPTS_DISABLED ;break ; +case CLOCK_EVT_MODE_RESUME : +break ; } }
arch/arm/mach-imx/time.c +1 -0
@@ -159,6 +159,7 @@ static void imx_set_mode(enum clock_evenbreak ;case CLOCK_EVT_MODE_SHUTDOWN :case CLOCK_EVT_MODE_UNUSED : +case CLOCK_EVT_MODE_RESUME :/* Left event sources disabled, no more interrupts appears */ break ; }
arch/arm/mach-ixp4xx/common.c +2 -0
@@ -459,6 +459,8 @@ static void ixp4xx_set_mode(enum clock_edefault : osrt = opts =0 ;break ; +case CLOCK_EVT_MODE_RESUME : +break ; } *IXP4XX_OSRT1 = osrt | opts;
arch/arm/mach-omap1/time.c +1 -0
@@ -156,6 +156,7 @@ static void omap_mpu_set_mode(enum clockbreak ;case CLOCK_EVT_MODE_UNUSED :case CLOCK_EVT_MODE_SHUTDOWN : +case CLOCK_EVT_MODE_RESUME :break ; } }
arch/arm/plat-omap/timer32k.c +2 -0
@@ -156,6 +156,8 @@ static void omap_32k_timer_set_mode(enumcase CLOCK_EVT_MODE_SHUTDOWN :omap_32k_timer_stop ();break ; +case CLOCK_EVT_MODE_RESUME : +break ; } }
arch/i386/kernel/vmiclock.c +1 -0
@@ -142,6 +142,7 @@ static void vmi_timer_set_mode(enum clocswitch (mode) {case CLOCK_EVT_MODE_ONESHOT : +case CLOCK_EVT_MODE_RESUME :break ;case CLOCK_EVT_MODE_PERIODIC : cycles_per_hz = vmi_timer_ops.get_cycle_frequency ();
arch/i386/xen/time.c +1 -0
@@ -407,6 +407,7 @@ static void xen_timerop_set_mode(enum clbreak ;case CLOCK_EVT_MODE_ONESHOT : +case CLOCK_EVT_MODE_RESUME :break ;case CLOCK_EVT_MODE_UNUSED :
arch/sh/kernel/timers/timer-tmu.c +1 -0
@@ -80,6 +80,7 @@ static void tmu_set_mode(enum clock_evenbreak ;case CLOCK_EVT_MODE_UNUSED :case CLOCK_EVT_MODE_SHUTDOWN : +case CLOCK_EVT_MODE_RESUME :break ; } }
arch/sparc64/kernel/time.c +1 -0
@@ -938,6 +938,7 @@ static void sparc64_timer_setup(enum clo {switch (mode) {case CLOCK_EVT_MODE_ONESHOT : +case CLOCK_EVT_MODE_RESUME :break ;case CLOCK_EVT_MODE_SHUTDOWN :
Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic)
* From: Thomas Gleixner
[]
Quoted 5 lines
Fixup the existing users.
This removes the sysfs entry for the HPET, which is now controlled by the clockevents resume code.
Quoted 8 lines
Signed-off-by Thomas Gleixner <[email protected]>--- arch/arm/mach-davinci/time.c | 2 + arch/arm/mach-imx/time.c | 1 arch/arm/mach-ixp4xx/common.c | 2 + arch/arm/mach-omap1/time.c | 1 arch/arm/plat-omap/timer32k.c | 2 +
Testers and users are most likely to run one particular arch on one particular test bench. If individual patches are arch separated, i think bisecting will be a little bit easier.
Thus, i would like to propose separate arch patching (x86_64/i386 mainly).
Is it possible to do that? (And even set such check in ``checkpatch''?)
You would say, why? Because current kbuild/kconfig support of builds for whole tree.
That's because to make download, build, test and debug particular arch more easily, i'm trying to re-think and re-do some kbuild parts. With minimum set of files, downloaded with git one can spend less time/bandwidth for starting testing.
Quoted 5 lines
arch/i386/kernel/apic.c | 3 + arch/i386/kernel/hpet.c | 71 ++------------------------------------ arch/i386/kernel/i8253.c | 26 ++++++------- arch/i386/kernel/vmiclock.c | 1 arch/i386/xen/time.c | 1
Opinions?
Quoted 2 lines
arch/sh/kernel/timers/timer-tmu.c | 1 arch/sparc64/kernel/time.c | 1
____
Re: Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic)
Oleg,
Quoted 5 lines · Oleg Verych
Quoted 1 line
arch/arm/plat-omap/timer32k.c | 2 +Testers and users are most likely to run one particular arch on one particular test bench. If individual patches are arch separated, i think bisecting will be a little bit easier.
No it is not. See below.
Quoted 1 line
Thus, i would like to propose separate arch patching (x86_64/i386 mainly).
This change adds an enum entry in a generic header file. _ALL_ users of clock events have a switch(this_changed_enum) in the set_mode() function. _ALL_ of them will spit warnings and some of them will even break, when the fix up is not done in one go.
Quoted 1 line
Is it possible to do that? (And even set such check in ``checkpatch''?)
It's possible, but results in an commit which will affect bisecting. I'm not going to send a patch which knowingly breaks bisecting either at compile or at run time.
Quoted 7 lines
You would say, why? Because current kbuild/kconfig support of builds for whole tree.
That's because to make download, build, test and debug particular arch more easily, i'm trying to re-think and re-do some kbuild parts. With minimum set of files, downloaded with git one can spend less time/bandwidth for starting testing.
Oh, well. That's going to be an interesting feature for git and the result will be published kernel trees with a total delta of 40MB against mainline, because someone tweaked the stuff in a way that it contains only the relevant files for a particular sub architecture. Embedded folks do this already and it makes it extremely hard to do efficient trouble shooting on such crippled trees. No thanks.
If we would still have 9600 Baud modem connections I would understand that, but git is really effective since packing was added, so this argument is more or less an academic exercise.
tglx
PATCH 7/25 Tick management: spread timer interrupt
In reply to Thomas GleixnerFrom: john stultz <[email protected]>
After discussing w/ Thomas over IRC, it seems the issue is the sched tick fires on every cpu at the same time, causing extra lock contention.
This smaller change, adds an extra offset per cpu so the ticks don't line up. This patch also drops the idle latency from 40us down to under 20us.
--- kernel/time/tick-sched.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
kernel/time/tick-sched.c +6 -1
@@ -573,6 +573,7 @@ void tick_setup_sched_timer(void) {struct tick_sched *ts = &__get_cpu_var (tick_cpu_sched);ktime_t now =ktime_get (); +u64 offset;/* * Emulate tick processing via per-CPU hrtimers:
@@ -581,8 +582,12 @@ void tick_setup_sched_timer(void) ts->sched_timer.function = tick_sched_timer; ts->sched_timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ; -/* Get the next period */ +/* Get the next period (per cpu)*/ ts->sched_timer.expires =tick_init_jiffy_update (); + offset =ktime_to_ns (tick_period) >>1 ; +do_div (offset,NR_CPUS ); + offset *=smp_processor_id (); + ts->sched_timer.expires =ktime_add_ns (ts->sched_timer.expires, offset);for (;;) {hrtimer_forward (&ts->sched_timer, now, tick_period);
PATCH 8/25 i386: PIT stop only, when in periodic or oneshot mode
In reply to Thomas GleixnerThe patch is necessary on one of my boxen, where programming the stop sequence twice leads to PIT malfunction.
Sigh !
--- arch/i386/kernel/i8253.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/i386/kernel/i8253.c +6 -3
@@ -48,9 +48,12 @@ static void init_pit_timer(enum clock_evcase CLOCK_EVT_MODE_SHUTDOWN :case CLOCK_EVT_MODE_UNUSED : -outb_p (0x30 ,PIT_MODE ); -outb_p (0 ,PIT_CH0 );/* LSB */ -outb_p (0 ,PIT_CH0 );/* MSB */ +if (evt->mode ==CLOCK_EVT_MODE_PERIODIC || + evt->mode ==CLOCK_EVT_MODE_ONESHOT ) { +outb_p (0x30 ,PIT_MODE ); +outb_p (0 ,PIT_CH0 ); +outb_p (0 ,PIT_CH0 ); + }break ;case CLOCK_EVT_MODE_ONESHOT :
PATCH 9/25 clockevents: Fix device replacement
In reply to Thomas GleixnerWhen a device is replaced by a better rated device, then the broadcast mode needs to be evaluated again. When the new device has no requirement for broadcasting, then the broadcast bits for the CPU must be cleared.
--- kernel/time/tick-broadcast.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
kernel/time/tick-broadcast.c +28 -1
@@ -31,6 +31,12 @@ struct tick_device tick_broadcast_devicestatic cpumask_t tick_broadcast_mask;static DEFINE_SPINLOCK (tick_broadcast_lock); +#ifdef CONFIG_TICK_ONESHOT +static void tick_broadcast_clear_oneshot (int cpu); +#else +static inline void tick_broadcast_clear_oneshot (int cpu) { } +#endif +/* * Debugging: see timer_list.c */
@@ -99,8 +105,19 @@ int tick_device_uses_broadcast(struct clcpu_set (cpu, tick_broadcast_mask);tick_broadcast_start_periodic (tick_broadcast_device.evtdev); ret =1 ; - } + }else { +/* +* When the new device is not affected by the stop +* feature and the cpu is marked in the broadcast mask +* then clear the broadcast bit. +*/ +if (!(dev->features &CLOCK_EVT_FEAT_C3STOP )) { +int cpu =smp_processor_id (); +cpu_clear (cpu, tick_broadcast_mask); +tick_broadcast_clear_oneshot (cpu); + } + }spin_unlock_irqrestore (&tick_broadcast_lock, flags);return ret; }
@@ -487,6 +504,16 @@ out:spin_unlock_irqrestore (&tick_broadcast_lock, flags); } +/* +* Reset the one shot broadcast for a cpu +* +* Called with tick_broadcast_lock held +*/ +static void tick_broadcast_clear_oneshot (int cpu) +{ +cpu_clear (cpu, tick_broadcast_oneshot_mask); +} +/** * tick_broadcast_setup_highres - setup the broadcast device for highres */
PATCH 10/25 highres: Improve debug output
In reply to Thomas GleixnerFrom: Ingo Molnar <[email protected]>
Add some more debug information to the hrtimer and clock events code.
--- arch/i386/kernel/apic.c | 3 +++ kernel/hrtimer.c | 5 ++++- kernel/time/tick-oneshot.c | 15 ++++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-)
arch/i386/kernel/apic.c +3 -0
@@ -524,6 +524,9 @@ void __init setup_boot_APIC_clock(void)*/ if (nmi_watchdog !=NMI_IO_APIC ) lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY ; +else +printk (KERN_WARNING "APIC timer registered as dummy," +" due to nmi_watchdog=1!\n" ); }/* Setup the lapic or request the broadcast */
kernel/hrtimer.c +4 -1
@@ -558,7 +558,8 @@ static inline int hrtimer_enqueue_reprog*/ static int hrtimer_switch_to_hres (void ) { -struct hrtimer_cpu_base *base = &__get_cpu_var (hrtimer_bases); +int cpu =smp_processor_id (); +struct hrtimer_cpu_base *base = &per_cpu (hrtimer_bases, cpu);unsigned long flags;if (base->hres_active)
@@ -568,6 +569,8 @@ static int hrtimer_switch_to_hres(void)if (tick_init_highres ()) {local_irq_restore (flags); +printk (KERN_WARNING "Could not switch to high resolution " +"mode on CPU %d\n" , cpu);return 0 ; } base->hres_active =1 ;
kernel/time/tick-oneshot.c +14 -1
@@ -73,8 +73,21 @@ int tick_switch_to_oneshot(void (*handlestruct clock_event_device *dev = td->evtdev;if (!dev || !(dev->features &CLOCK_EVT_FEAT_ONESHOT ) || - !tick_device_is_functional (dev)) + !tick_device_is_functional (dev)) { + +printk (KERN_INFO "Clockevents: " +"could not switch to one-shot mode:" ); +if (!dev) { +printk (" no tick device\n" ); + }else { +if (!tick_device_is_functional (dev)) +printk (" %s is not functional.\n" , dev->name); +else if (!(dev->features &CLOCK_EVT_FEAT_ONESHOT )) +printk (" %s does not support one-shot mode.\n" , + dev->name); + }return -EINVAL ; + } td->mode =TICKDEV_MODE_ONESHOT ; dev->event_handler = handler;
PATCH 11/25 hrtimer: speedup hrtimer_enqueue
In reply to Thomas GleixnerFrom: Ingo Molnar <[email protected]>
Speedup hrtimer_enqueue by evaluating the rbtree insertion result.
--- kernel/hrtimer.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
kernel/hrtimer.c +6 -4
@@ -686,6 +686,7 @@ static void enqueue_hrtimer(struct hrtimstruct rb_node **link = &base->active.rb_node;struct rb_node *parent =NULL ;struct hrtimer *entry; +int leftmost =1 ;/* * Find the right place in the rbtree:
@@ -697,18 +698,19 @@ static void enqueue_hrtimer(struct hrtim* We dont care about collisions. Nodes with * the same expiry time stay together. */ -if (timer->expires.tv64 < entry->expires.tv64) +if (timer->expires.tv64 < entry->expires.tv64) { link = &(*link)->rb_left; -else + }else { link = &(*link)->rb_right; + leftmost =0 ; + } }/* * Insert the timer to the rbtree and check whether it * replaces the first pending timer */ -if (!base->first || timer->expires.tv64 < - rb_entry(base->first, struct hrtimer, node)->expires.tv64) { +if (leftmost) {/* * Reprogram the clock event device. When the timer is already * expired hrtimer_enqueue_reprogram has either called the
PATCH 12/25 pcspkr: use the global PIT lock
In reply to Thomas GleixnerReplace the pcspkr private PIT lock by the global PIT lock to serialize the PIT access all over the place.
--- arch/x86_64/kernel/time.c | 2 ++ drivers/input/misc/pcspkr.c | 11 ++++++++--- include/asm-x86_64/i8253.h | 6 ++++++ 3 files changed, 16 insertions(+), 3 deletions(-)
arch/x86_64/kernel/time.c +2 -0
@@ -33,6 +33,7 @@#include <acpi/acpi_bus.h> #endif #include <asm/8253pit.h> +#include <asm/i8253.h> #include <asm/pgtable.h> #include <asm/vsyscall.h> #include <asm/timex.h>
@@ -51,6 +52,7 @@ static char *timename = NULL;DEFINE_SPINLOCK (rtc_lock);EXPORT_SYMBOL (rtc_lock);DEFINE_SPINLOCK (i8253_lock); +EXPORT_SYMBOL (i8253_lock);volatile unsigned long __jiffies __section_jiffies =INITIAL_JIFFIES ;
drivers/input/misc/pcspkr.c +8 -3
@@ -24,7 +24,12 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@uMODULE_DESCRIPTION ("PC Speaker beeper driver" );MODULE_LICENSE ("GPL" ); -static DEFINE_SPINLOCK (i8253_beep_lock); +#ifdef CONFIG_X86 +/* Use the global PIT lock ! */ +#include <asm/i8253.h> +#else +static DEFINE_SPINLOCK (i8253_lock); +#endif static int pcspkr_event (struct input_dev *dev,unsigned int type,unsigned int code,int value) {
@@ -43,7 +48,7 @@ static int pcspkr_event(struct input_devif (value >20 && value <32767 ) count =PIT_TICK_RATE / value; -spin_lock_irqsave (&i8253_beep_lock, flags); +spin_lock_irqsave (&i8253_lock, flags);if (count) {/* enable counter 2 */
@@ -58,7 +63,7 @@ static int pcspkr_event(struct input_devoutb (inb_p (0x61 ) &0xFC ,0x61 ); } -spin_unlock_irqrestore (&i8253_beep_lock, flags); +spin_unlock_irqrestore (&i8253_lock, flags);return 0 ; }
include/asm-x86_64/i8253.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef __ASM_I8253_H__ +#define __ASM_I8253_H__ + +extern spinlock_t i8253_lock; + +#endif /* __ASM_I8253_H__ */
PATCH 13/25 i386: hpet assumes boot cpu is 0
In reply to Thomas GleixnerFrom: Chris Wright <[email protected]>
I fixed this in x86_64. Looks like the kind of thing that will break voyager on i386.
--- arch/i386/kernel/hpet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/i386/kernel/hpet.c +1 -1
@@ -325,7 +325,7 @@ int __init hpet_enable(void)* Start hpet with the boot cpu mask and make it * global after the IO_APIC has been initialized. */ - hpet_clockevent.cpumask =cpumask_of_cpu (0 ); + hpet_clockevent.cpumask =cpumask_of_cpu (smp_processor_id ());clockevents_register_device (&hpet_clockevent); global_clock_event = &hpet_clockevent;return 1 ;
PATCH 14/25 NTP: Move the cmos update code into ntp.c
In reply to Thomas Gleixneri386 and sparc64 have the identical code to update the cmos clock. Move it into kernel/time/ntp.c as there are other architectures coming along with the same requirements.
--- arch/i386/Kconfig | 4 +++ arch/i386/kernel/time.c | 50 +------------------------------------- arch/sparc64/Kconfig | 4 +++ arch/sparc64/kernel/time.c | 53 +--------------------------------------- include/asm-i386/timer.h | 1 include/linux/time.h | 2 + kernel/time/ntp.c | 59 ++++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 70 insertions(+), 103 deletions(-)
arch/i386/Kconfig +4 -0
@@ -18,6 +18,10 @@ config GENERIC_TIME bool default y +config GENERIC_CMOS_UPDATE + bool + default y + config CLOCKSOURCE_WATCHDOG bool default y
arch/i386/kernel/time.c +2 -48
57 lines not on this page · raw message
arch/sparc64/kernel/time.c +2 -51
60 lines not on this page · raw message
include/linux/time.h +2 -0
@@ -93,6 +93,8 @@ extern struct timespec wall_to_monotonic extern seqlock_t xtime_lock __attribute__((weak));extern unsigned long read_persistent_clock (void ); +extern int update_persistent_clock (struct timespec now); +extern int no_sync_cmos_clock__read_mostly ;void timekeeping_init (void );static inline unsigned long get_seconds (void )
kernel/time/ntp.c +56 -3
80 lines not on this page · raw message
arch/sparc64/Kconfig +4 -0
@@ -23,6 +23,10 @@ config GENERIC_TIME bool default y +config GENERIC_CMOS_UPDATE + bool + default y + config GENERIC_CLOCKEVENTS bool default y
include/asm-i386/timer.h +0 -1
@@ -12,7 +12,6 @@ unsigned long native_calculate_cpu_khz(vextern int timer_ack;extern int no_timer_check; -extern int no_sync_cmos_clock;extern int recalibrate_cpu_khz (void );#ifndef CONFIG_PARAVIRT
Re: [patch-mm 14/25] NTP: Move the cmos update code into ntp.c
Hi Thomas,
Quoted 20 lines · Thomas Gleixner
i386 and sparc64 have the identical code to update the cmos clock. Move it into
kernel/time/ntp.cas there are other architectures coming along with the same requirements.Signed-off-by Thomas Gleixner <[email protected]>Cc Chris Wright <[email protected]>Cc Ingo Molnar <[email protected]>Cc john stultz <[email protected]>Cc David Miller <[email protected]>--- arch/i386/Kconfig | 4 +++ arch/i386/kernel/time.c | 50 +------------------------------------- arch/sparc64/Kconfig | 4 +++ arch/sparc64/kernel/time.c | 53 +--------------------------------------- include/asm-i386/timer.h | 1 include/linux/time.h | 2 + kernel/time/ntp.c | 59 ++++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 70 insertions(+), 103 deletions(-)
[snip]
include/linux/time.h extern struct timespec wall_to_monotonic · line 96
Quoted 10 lines
/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
Index:linux-2.6.22-rc4-mm/include/linux/time.h
===================================================================include/linux/time.h +1
-0@@ -93,6 +93,8 @@ extern struct timespec wall_to_monotonic extern seqlock_t xtime_lock __attribute__((weak));extern unsigned long read_persistent_clock (void ); +extern int update_persistent_clock (struct timespec now);
I'm wondering if update_persistent_clock shouldn't be part of "drivers/rtc/*" framework. Do you have any idea on how this is going to be implemented on platforms that use this framework ?
Quoted 26 lines
include/linux/time.h +1
-0+extern int no_sync_cmos_clock__read_mostly ;void timekeeping_init (void );static inline unsigned long get_seconds (void )Index:
linux-2.6.22-rc4-mm/kernel/time/ntp.c
===================================================================kernel/time/ntp.c +5
-1@@ -10,6 +10,7 @@#include <linux/mm.h> #include <linux/time.h> +#include <linux/timer.h> #include <linux/timex.h> #include <linux/jiffies.h> #include <linux/hrtimer.h> @@ -187,12 +188,64 @@ u64 current_tick_length(void)return tick_length; } +#ifdef CONFIG_GENERIC_CMOS_UPDATE -void __attribute__ ((weak))notify_arch_cmos_timer (void ) +/* Disable the cmos update - used by virtualization and embedded */ +int no_sync_cmos_clock__read_mostly ; +
[snip]
kernel/time/ntp.c u64 current_tick_length(void) · line 243
Quoted 6 lines
kernel/time/ntp.c +5
-0+static void notify_cmos_timer (void ) +{ +if (no_sync_cmos_clock) +mod_timer (&sync_cmos_timer, jiffies +1 ); +}
Isn't the test condition wrong ? Shouldn't it be:
if (!no_sync_cmos_clock) mod_timer(&sync_cmos_timer, jiffies + 1);
Thanks,
Franck
PATCH 15/25 clocksource: add settimeofday hook for PPC
In reply to Thomas GleixnerFrom: Tony Breeds <[email protected] >
I'm working on a clocksource implementation for all powerpc platforms. some of these platforms needs to do a little work as part of the settimeofday() syscall and I can't see a way to do that without adding this hook to clocksource.
From: Tony Breeds <[email protected]>
Add per clocksource hook to settimeofday().
Some clocksources need to do extra work as part of the settimeofday call, this hook make it easy to do so.
---
include/linux/clocksource.h | 3 +++ kernel/time/timekeeping.c | 3 +++ 2 files changed, 6 insertions(+)
include/linux/clocksource.h +3 -0
@@ -50,6 +50,7 @@ struct clocksource;* @flags: flags describing special properties * @vread: vsyscall based read * @resume: resume function for the clocksource, if necessary +* @settimeofday: [Optional] Do arch specific work during do_settimeofday * @cycle_interval: Used internally by timekeeping core, please ignore. * @xtime_interval: Used internally by timekeeping core, please ignore. */
@@ -68,6 +69,8 @@ struct clocksource {cycle_t (*vread)(void);void (*resume)(void ); +void (*settimeofday)(struct clocksource *cs,struct timespec *ts); +/* timekeeping specific data, ignore */ cycle_t cycle_interval;u64 xtime_interval;
kernel/time/timekeeping.c +3 -0
@@ -159,6 +159,9 @@ int do_settimeofday(struct timespec *tv) clock->error =0 ;ntp_clear (); +if (clock->settimeofday) + clock->settimeofday (clock, tv); +update_vsyscall (&xtime, clock);write_sequnlock_irqrestore (&xtime_lock, flags);
Re: [patch-mm 15/25] clocksource: add settimeofday hook for PPC
Quoted 9 lines · Thomas Gleixner
plain text document attachment
(clocksource-add-settimeofday-hook.patch)
From: Tony Breeds <[email protected] >I'm working on a clocksource implementation for all powerpc platforms. some of these platforms needs to do a little work as part of the
settimeofday()syscall and I can't see a way to do that without adding this hook to clocksource.
I'd like to see how this is used? If the code that uses this API change isn't ready yet, then this patch should really wait..
Daniel
RFC 1/1 clocksouce implementation for powerpc
Quoted 12 lines · Daniel Walker
Quoted 9 lines · Thomas Gleixner
plain text document attachment
(clocksource-add-settimeofday-hook.patch)
From: Tony Breeds <[email protected] >I'm working on a clocksource implementation for all powerpc platforms. some of these platforms needs to do a little work as part of the
settimeofday()syscall and I can't see a way to do that without adding this hook to clocksource.
Quoted 2 lines
I'd like to see how this is used? If the code that uses this API change isn't ready yet, then this patch should really wait..
This is my current patch to rework arch/powerpc/kernel/time.c to create a clocksource. It's not ready for inclusion.
powerpc needs to keep the vdso in sync whenener settimeodfay() is called. Adding the hook the to the clocksource structure was my way of allowing this to happen. There are other approaches, but this seemed to best allow for runtime. Initially I considered using update_vsyscall() but this is called from do_timer(), and I don't need this code run then :(
This has been booted on pSeries and iSeries (I'm using glibc 2.5, which uses the vdso gettimeoday())
All comments appreiated.
arch/powerpc/Kconfig +6 -0
@@ -31,6 +31,12 @@ config MMU bool default y +config GENERIC_TIME + def_bool y + +config GENERIC_TIME_VSYSCALL + def_bool y + config GENERIC_HARDIRQS bool default y
arch/powerpc/kernel/time.c +101 -132
269 lines not on this page · raw message
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
Re: [RFC] clocksouce implementation for powerpc
Quoted 19 lines · Tony Breeds
Quoted 12 lines · Daniel Walker
Quoted 9 lines · Thomas Gleixner
plain text document attachment
(clocksource-add-settimeofday-hook.patch)
From: Tony Breeds <[email protected] >I'm working on a clocksource implementation for all powerpc platforms. some of these platforms needs to do a little work as part of the
settimeofday()syscall and I can't see a way to do that without adding this hook to clocksource.Quoted 2 lines
I'd like to see how this is used? If the code that uses this API change isn't ready yet, then this patch should really wait..
This is my current patch to rework
arch/powerpc/kernel/time.cto create a clocksource. It's not ready for inclusion.
Quoted 6 lines
powerpc needs to keep the vdso in sync whenener
settimeodfay()is called. Adding the hook the to the clocksource structure was my way of allowing this to happen. There are other approaches, but this seemed to best allow for runtime. Initially I considered usingupdate_vsyscall()but this is called fromdo_timer(), and I don't need this code run then :(
As I said in our private thread, I do think you should be using update_vsyscall() .. update_vsyscall() is just called when the time is set, usually that happens in the timer interrupt and sometimes that happens in settimeofday() ..
Quoted 4 lines
This has been booted on pSeries and iSeries (I'm using glibc 2.5, which uses the vdso
gettimeoday())All comments appreiated.
At least some of your code is duplications over what is already being worked on inside the powerpc community.. For instance, I know there is already a timebase clocksource,
http://people.redhat.com/~mingo/realtime-preempt/patch-2.6.21.5-rt17
Quoted 241 lines
Index: working/arch/powerpc/Kconfig
===================================================================arch/powerpc/Kconfig +6
-0@@ -31,6 +31,12 @@ config MMU bool default y +config GENERIC_TIME + def_bool y + +config GENERIC_TIME_VSYSCALL + def_bool y + config GENERIC_HARDIRQS bool default yIndex:
working/arch/powerpc/kernel/time.c
===================================================================arch/powerpc/kernel/time.c +56
-132@@ -74,6 +74,30 @@#endif #include <asm/smp.h> +/* powerpc clocksource/clockevent code */ + +/* TODO: +* o Code style +* * Variable names ... be consistent. +* +* TODO: Clocksource +* o Need a _USE_RTC() clocksource impelementation +* o xtime: Either time.c manages it, or clocksource does, not both +*/ + +#include <linux/clocksource.h> + +static struct clocksource clocksource_timebase = { + .name ="timebase" , + .rating =200 , + .flags =CLOCK_SOURCE_IS_CONTINUOUS , + .mask =CLOCKSOURCE_MASK (64 ), + .shift =22 , + .mult =0 ,/* To be filled in */ + .read =NULL ,/* To be filled in */ + .settimeofday =NULL ,/* To be filled in */ +}; +/* keep track of when we need to update the rtc */ time_t last_rtc_update;#ifdef CONFIG_PPC_ISERIES @@ -376,65 +400,6 @@ static __inline__ void timer_check_rtc(v } } -/* -* This version of gettimeofday has microsecond resolution. -*/ -static inline void __do_gettimeofday (struct timeval *tv) -{ -unsigned long sec, usec; -u64 tb_ticks, xsec; -struct gettimeofday_vars *temp_varp; -u64 temp_tb_to_xs, temp_stamp_xsec; - -/* -* These calculations are faster (gets rid of divides) -* if done in units of 1/2^20 rather than microseconds. -* The conversion to microseconds at the end is done -* without a divide (and in fact, without a multiply) -*/ - temp_varp = do_gtod.varp; - -/* Sampling the time base must be done after loading -* do_gtod.varp in order to avoid racing with update_gtod. -*/ -data_barrier (temp_varp); - tb_ticks =get_tb () - temp_varp->tb_orig_stamp; - temp_tb_to_xs = temp_varp->tb_to_xs; - temp_stamp_xsec = temp_varp->stamp_xsec; - xsec = temp_stamp_xsec +mulhdu (tb_ticks, temp_tb_to_xs); - sec = xsec /XSEC_PER_SEC ; - usec = (unsigned long )xsec & (XSEC_PER_SEC -1 ); - usec =SCALE_XSEC (usec,1000000 ); - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -void do_gettimeofday (struct timeval *tv) -{ -if (__USE_RTC ()) { -/* do this the old way */ -unsigned long flags, seq; -unsigned int sec, nsec, usec; - -do { - seq =read_seqbegin_irqsave (&xtime_lock, flags); - sec = xtime.tv_sec; - nsec = xtime.tv_nsec +tb_ticks_since (tb_last_jiffy); - }while (read_seqretry_irqrestore (&xtime_lock, seq, flags)); - usec = nsec /1000 ; -while (usec >=1000000 ) { - usec -=1000000 ; - ++sec; - } - tv->tv_sec = sec; - tv->tv_usec = usec; -return ; - } -__do_gettimeofday (tv); -} - -EXPORT_SYMBOL (do_gettimeofday);/* * There are two copies of tb_to_xs and stamp_xsec so that no @@ -666,8 +631,8 @@ void timer_interrupt(struct pt_regs * reif (per_cpu (last_jiffy, cpu) >= tb_next_jiffy) { tb_last_jiffy = tb_next_jiffy;do_timer (1 ); -timer_recalc_offset (tb_last_jiffy); -timer_check_rtc (); +/* timer_recalc_offset() && timer_check_rtc() +* are now called from update_vsyscall() */ }write_sequnlock (&xtime_lock); }@@ -739,77 +704,6 @@ unsigned long long sched_clock(void)return mulhdu (get_tb () - boot_tb, tb_to_ns_scale) << tb_to_ns_shift; } -int do_settimeofday (struct timespec *tv) -{ -time_t wtm_sec, new_sec = tv->tv_sec; -long wtm_nsec, new_nsec = tv->tv_nsec; -unsigned long flags; -u64 new_xsec; -unsigned long tb_delta; - -if ((unsigned long )tv->tv_nsec >=NSEC_PER_SEC ) -return -EINVAL ; - -write_seqlock_irqsave (&xtime_lock, flags); - -/* -* Updating the RTC is not the job of this code. If the time is -* stepped under NTP, the RTC will be updated after STA_UNSYNC -* is cleared. Tools like clock/hwclock either copy the RTC -* to the system time, in which case there is no point in writing -* to the RTC again, or write to the RTC but then they don't call -* settimeofday to perform this operation. -*/ -#ifdef CONFIG_PPC_ISERIES -if (firmware_has_feature (FW_FEATURE_ISERIES ) && first_settimeofday) { -iSeries_tb_recal (); - first_settimeofday =0 ; - } -#endif - -/* Make userspace gettimeofday spin until we're done. */ - ++vdso_data->tb_update_count; -smp_mb (); - -/* -* Subtract off the number of nanoseconds since the -* beginning of the last tick. -*/ - tb_delta =tb_ticks_since (tb_last_jiffy); - tb_delta =mulhdu (tb_delta, do_gtod.varp->tb_to_xs);/* in xsec */ - new_nsec -=SCALE_XSEC (tb_delta,1000000000 ); - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec); - -set_normalized_timespec (&xtime, new_sec, new_nsec); -set_normalized_timespec (&wall_to_monotonic, wtm_sec, wtm_nsec); - -/* In case of a large backwards jump in time with NTP, we want the -* clock to be updated as soon as the PLL is again in lock. -*/ - last_rtc_update = new_sec -658 ; - -ntp_clear (); - - new_xsec = xtime.tv_nsec; -if (new_xsec !=0 ) { - new_xsec *=XSEC_PER_SEC ; -do_div (new_xsec,NSEC_PER_SEC ); - } - new_xsec += (u64 )xtime.tv_sec *XSEC_PER_SEC ; -update_gtod (tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); - - vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; - vdso_data->tz_dsttime = sys_tz.tz_dsttime; - -write_sequnlock_irqrestore (&xtime_lock, flags); -clock_was_set (); -return 0 ; -} - -EXPORT_SYMBOL (do_settimeofday); -static int __init get_freq (char *name,int cells,unsigned long *val) {struct device_node *cpu;@@ -878,6 +772,78 @@ unsigned long get_boot_time(void) tm.tm_hour, tm.tm_min, tm.tm_sec); } +/* clocksource code */ +static cycle_t timebase_read (void ) +{ +return (cycle_t )get_tb (); +} + +static void clocksource_settimeofday (struct clocksource *cs, +struct timespec *ts) +{ +u64 new_xsec; + +#ifdef CONFIG_PPC_ISERIES +if (firmware_has_feature (FW_FEATURE_ISERIES ) && first_settimeofday) { +iSeries_tb_recal (); + first_settimeofday =0 ; + } +#endif + +/* Make userspace gettimeofday spin until we're done. */ + ++vdso_data->tb_update_count; +smp_mb (); + +/* In case of a large backwards jump in time with NTP, we want the +* clock to be updated as soon as the PLL is again in lock. +*/ + last_rtc_update = xtime.tv_sec -658 ; + + new_xsec = xtime.tv_nsec; +if (new_xsec !=0 ) { + new_xsec *=XSEC_PER_SEC ;
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 814
Quoted 10 lines
arch/powerpc/kernel/time.c +10
-0+do_div (new_xsec,NSEC_PER_SEC ); + } + + new_xsec += (u64 )xtime.tv_sec *XSEC_PER_SEC ; + + vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; + vdso_data->tz_dsttime = sys_tz.tz_dsttime; + +update_gtod (tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); +}
It does look too large to run from interrupt context, but it also looks like it could get cleaned out more ..
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 820
Quoted 5 lines
arch/powerpc/kernel/time.c +5
-0+void update_vsyscall (struct timespec *wall_time,struct clocksource *clock) +{ +timer_recalc_offset (tb_last_jiffy); +timer_check_rtc (); +}
Hmm .. This doesn't look like it's taking into account that the time has changed .. Your time has effectively incremented by one jiffie .. The vdso_data doesn't appear to be updated ..
Quoted 43 lines
arch/powerpc/kernel/time.c +28
-0+void __init clocksource_init (void ) +{ +int mult; + +if (__USE_RTC ()) +return ; + + mult =clocksource_hz2mult (tb_ticks_per_sec, + clocksource_timebase.shift); + clocksource_timebase.mult = mult; + + clocksource_timebase.read = timebase_read; + clocksource_timebase.settimeofday = clocksource_settimeofday; + +if (clocksource_register (&clocksource_timebase)) { +printk (KERN_ERR "clocksource: %s is already registered\n" , + clocksource_timebase.name); +return ; + } + +printk (KERN_INFO "clocksource: %s mult[%x] shift[%d] registered\n" , + clocksource_timebase.name, + clocksource_timebase.mult, clocksource_timebase.shift); +} +/* This function is only called on the boot processor */ void __init time_init (void ) {@@ -999,6 +965,9 @@ void __init time_init(void) -xtime.tv_sec, -xtime.tv_nsec);write_sequnlock_irqrestore (&xtime_lock, flags); +/* Register the clocksource */ +clocksource_init (); +/* Not exact, but the timer interrupt takes care of this */ set_dec (tb_ticks_per_jiffy); }Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
Re: [RFC] clocksouce implementation for powerpc
Quoted 23 lines · Daniel Walker
Quoted 23 lines
arch/powerpc/kernel/time.c +23
-0+static void clocksource_settimeofday (struct clocksource *cs, +struct timespec *ts) +{ +u64 new_xsec; + +#ifdef CONFIG_PPC_ISERIES +if (firmware_has_feature (FW_FEATURE_ISERIES ) && first_settimeofday) { +iSeries_tb_recal (); + first_settimeofday =0 ; + } +#endif + +/* Make userspace gettimeofday spin until we're done. */ + ++vdso_data->tb_update_count; +smp_mb (); + +/* In case of a large backwards jump in time with NTP, we want the +* clock to be updated as soon as the PLL is again in lock. +*/ + last_rtc_update = xtime.tv_sec -658 ; + + new_xsec = xtime.tv_nsec; +if (new_xsec !=0 ) {
Quoted 8 lines
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 811
Quoted 8 lines
arch/powerpc/kernel/time.c +8
-0+ new_xsec *=XSEC_PER_SEC ; +do_div (new_xsec,NSEC_PER_SEC ); + } + + new_xsec += (u64 )xtime.tv_sec *XSEC_PER_SEC ; + + vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; + vdso_data->tz_dsttime = sys_tz.tz_dsttime;
I'm not sure why these are copied *only* here. Shouldn't they be copied
only once, at init. time?
Quoted 5 lines
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 814
Quoted 3 lines
arch/powerpc/kernel/time.c +3
-0+ +update_gtod (tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); +}It does look too large to run from interrupt context,
You mean if this would have been "included" into update_vsyscall()?
Quoted 2 lines
but it also looks
like it could get cleaned out more ..
Yeah, at least new_xsec calculation is duplicated in timer_recalc_offset()..
Quoted 8 lines
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 820
Quoted 5 lines
arch/powerpc/kernel/time.c +5
-0+void update_vsyscall (struct timespec *wall_time,struct clocksource *clock) +{ +timer_recalc_offset (tb_last_jiffy); +timer_check_rtc (); +}Hmm .. This doesn't look like it's taking into account that the time has changed ..
Why? By the time it gets called (form the timer softirq context)tb_last_jiffy should've been incremented. Well, this won't happen wither in or right after the timer interrupt... since timer has no IRQ on PowerPC -- it signals "exception". Well, HRT works somehow anyway. :-)
Quoted 2 lines
Your time has effectively incremented by one jiffie .. The
vdso_datadoesn't appear to be updated ..
Moreover, it will get called for settimeofday() as well which would seem
to double the overhead since your clocksource hook will get called beforehand.
WBR, Sergei
Re: [RFC] clocksouce implementation for powerpc
Quoted 10 lines · Sergei Shtylyov
Quoted 8 lines
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 820
Quoted 5 lines
arch/powerpc/kernel/time.c +5
-0+void update_vsyscall (struct timespec *wall_time,struct clocksource *clock) +{ +timer_recalc_offset (tb_last_jiffy); +timer_check_rtc (); +}Hmm .. This doesn't look like it's taking into account that the time has changed ..
Why? By the time it gets called (form the timer softirq context)
It is called from interrupt context at least in mainline. Only the -rt patch moves this to the softirq.
tglx
Re: [RFC] clocksouce implementation for powerpc
Hello.
Quoted 6 lines · Thomas Gleixner
Quoted 6 lines
Quoted 5 lines
Quoted 5 lines
arch/powerpc/kernel/time.c +5
-0+void update_vsyscall (struct timespec *wall_time,struct clocksource *clock) +{ +timer_recalc_offset (tb_last_jiffy); +timer_check_rtc (); +}
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Hmm .. This doesn't look like it's taking into account that the time has changed ..
Why? By the time it gets called (form the timer softirq context)
It is called from interrupt context at least in mainline. Only the -rt patch moves this to the softirq.
Anyway, by the time it gets called, tb_last_jiffy gets updated.
Quoted 1 line
tglx
WBR, Sergei
Re: [RFC] clocksouce implementation for powerpc
In reply to Daniel WalkerOn Wed, Jun 20, 2007 at 07:57:19AM -0700, Daniel Walker wrote:
Hi Daniel.
Quoted 4 lines
As I said in our private thread, I do think you should be using
update_vsyscall()..update_vsyscall()is just called when the time is set, usually that happens in the timer interrupt and sometimes that happens insettimeofday()..
Well I've taken another look at the code and I think I can probably restructure my code to use update_vsyscall(). I thought I needed a hook that was called /only/ from settimeofday() (which as you say doesn't match update_vsyscall()'s usage).
I'll try again and see what problems I hit.
Quoted 5 lines
At least some of your code is duplications over what is already being worked on inside the powerpc community.. For instance, I know there is already a timebase clocksource,
http://people.redhat.com/~mingo/realtime-preempt/patch-2.6.21.5-rt17
Thanks. The one in -rt doesn't seem to support the VDSO. however I see that there is duplication of effort there.
Quoted 3 lines
Hmm .. This doesn't look like it's taking into account that the time has changed .. Your time has effectively incremented by one jiffie .. The
vdso_datadoesn't appear to be updated ..
Unless I miss your meaning, the vdso is updated in timer_recalc_offset()/update_gtod() when needed.
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
Re: [RFC] clocksouce implementation for powerpc
In reply to Tony BreedsHello.
Quoted 9 lines · Tony Breeds
Quoted 8 lines
Quoted 8 lines
plain text document attachment
(clocksource-add-settimeofday-hook.patch)
From: Tony Breeds <[email protected] >I'm working on a clocksource implementation for all powerpc platforms. some of these platforms needs to do a little work as part of the
settimeofday()syscall and I can't see a way to do that without adding this hook to clocksource.
Quoted 5 lines
Quoted 2 lines
I'd like to see how this is used? If the code that uses this API change isn't ready yet, then this patch should really wait..
This is my current patch to rework
arch/powerpc/kernel/time.cto create a clocksource. It's not ready for inclusion.
I guess it's been based on the prior work by John Stultz (and me too :-)?
Quoted 9 lines
powerpc needs to keep the vdso in sync whenener
settimeodfay()is called. Adding the hook the to the clocksource structure was my way of allowing this to happen. There are other approaches, but this seemed to best allow for runtime. Initially I considered usingupdate_vsyscall()but this is called fromdo_timer(), and I don't need this code run then :(This has been booted on pSeries and iSeries (I'm using glibc 2.5, which uses the vdso
gettimeoday())
[...]
Quoted 7 lines
Index:
working/arch/powerpc/kernel/time.c
===================================================================arch/powerpc/kernel/time.c +0
-0@@ -74,6 +74,30 @@#endif #include <asm/smp.h>
arch/powerpc/kernel/time.c line 85
Quoted 10 lines
arch/powerpc/kernel/time.c +9
-0+/* powerpc clocksource/clockevent code */ + +/* TODO: +* o Code style +* * Variable names ... be consistent. +* +* TODO: Clocksource +* o Need a _USE_RTC() clocksource impelementation +* o xtime: Either time.c manages it, or clocksource does, not both
If you mean the init. part, this has been already done by me -- I've
implemented read_persistent_clock() and got rid of xtime setting. What's left is to implemet update_persistent_clock() and get rid of timer_check_rtc()...
arch/powerpc/kernel/time.c line 92
Quoted 7 lines
arch/powerpc/kernel/time.c +7
-0+*/ + +#include <linux/clocksource.h> + +static struct clocksource clocksource_timebase = { + .name ="timebase" , + .rating =200 ,
Perhaps we even need to raise the rating to 300 or 400 -- according to
what <linux/clocksource.h> says?
arch/powerpc/kernel/time.c line 95
Quoted 3 lines
arch/powerpc/kernel/time.c +3
-0+ .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .mask = CLOCKSOURCE_MASK(64), + .shift = 22,
PPC64 has issues with the fixed shift value, see:
arch/powerpc/kernel/time.c line 98
Quoted 3 lines
arch/powerpc/kernel/time.c +3
-0+ .mult = 0, /* To be filled in */ + .read = NULL, /* To be filled in */ + .settimeofday = NULL, /* To be filled in */
I don't quite understand why not just init them right away? The values
are fixed anyways.
Quoted 5 lines
arch/powerpc/kernel/time.c +2
-0+}; +/* keep track of when we need to update the rtc */ time_t last_rtc_update;#ifdef CONFIG_PPC_ISERIES
[...]
arch/powerpc/kernel/time.c void timer_interrupt(struct pt_regs * re · line 635
Quoted 8 lines
arch/powerpc/kernel/time.c +2
-2@@ -666,8 +631,8 @@ void timer_interrupt(struct pt_regs * reif (per_cpu (last_jiffy, cpu) >= tb_next_jiffy) { tb_last_jiffy = tb_next_jiffy;do_timer (1 ); -timer_recalc_offset (tb_last_jiffy); -timer_check_rtc (); +/* timer_recalc_offset() && timer_check_rtc() +* are now called from update_vsyscall() */
I.e. in the softirq context...
[...]
WBR, Sergei
Re: [RFC] clocksouce implementation for powerpc
On Wed, Jun 20, 2007 at 08:53:47PM +0400, Sergei Shtylyov wrote:
Hi Sergei,
Thanks for taking the time to look over my patch.
Quoted 1 line
I guess it's been based on the prior work by John Stultz (and me too :-)?
At some level I guess so. John did send me a patch a while ago.
Quoted 4 lines
If you mean the init. part, this has been already done by me -- I've
implementedread_persistent_clock()and got rid of xtime setting. What's left is to implemetupdate_persistent_clock()and get rid oftimer_check_rtc()...
Actually I think that comment is redundant. and should be removed sorry.
Quoted 2 lines
Perhaps we even need to raise the rating to 300 or 400 -- according to
what <linux/clocksource.h> says?
Sure.
Quoted 7 lines
arch/powerpc/kernel/time.c line 95
Quoted 3 lines
arch/powerpc/kernel/time.c +3
-0+ .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .mask = CLOCKSOURCE_MASK(64), + .shift = 22,PPC64 has issues with the fixed shift value, see:
Thanks!
Quoted 6 lines
arch/powerpc/kernel/time.c line 98
Quoted 3 lines
arch/powerpc/kernel/time.c +3
-0+ .mult = 0, /* To be filled in */ + .read = NULL, /* To be filled in */ + .settimeofday = NULL, /* To be filled in */I don't quite understand why not just init them right away? The values
are fixed anyways.
Well at least mult needs to be calculated at runtime, and I prefer to have the structure near the top of the file at which stage the read/settimeofday functions aren't defined.
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
Re: [RFC] clocksouce implementation for powerpc
Quoted 11 lines · Tony Breeds
Thanks for taking the time to look over my patch.
Quoted 1 line
I guess it's been based on the prior work by John Stultz (and me too :-)?
At some level I guess so. John did send me a patch a while ago.
Quoted 2 lines
If you mean the init. part, this has been already done by me -- I've
implementedread_persistent_clock()and got rid of xtime setting. What's left is to implemetupdate_persistent_clock()and get rid oftimer_check_rtc()...Actually I think that comment is redundant. and should be removed sorry.
I guess you haven't looked thru the -rt patch? There's much more than
John's initial patch there now, including the clockevents driver.
Quoted 8 lines
Quoted 6 lines
arch/powerpc/kernel/time.c line 98
Quoted 3 lines
arch/powerpc/kernel/time.c +3
-0+ .mult = 0, /* To be filled in */ + .read = NULL, /* To be filled in */ + .settimeofday = NULL, /* To be filled in */I don't quite understand why not just init them right away? The values
are fixed anyways.Well at least mult needs to be calculated at runtime, and I prefer to
I was talking about the method intializers specifically.
Quoted 2 lines
have the structure near the top of the file at which stage the read/settimeofday functions aren't defined.
I don't think it's justified anyway.
Quoted 1 line
Yours Tony
WBR, Sergei
Re: [RFC] clocksouce implementation for powerpc
In reply to Tony BreedsQuoted 13 lines · Tony Breeds
Quoted 12 lines · Daniel Walker
Quoted 9 lines · Thomas Gleixner
plain text document attachment
(clocksource-add-settimeofday-hook.patch)
From: Tony Breeds <[email protected] >I'm working on a clocksource implementation for all powerpc platforms. some of these platforms needs to do a little work as part of the
settimeofday()syscall and I can't see a way to do that without adding this hook to clocksource.
Quoted 5 lines
Quoted 2 lines
I'd like to see how this is used? If the code that uses this API change isn't ready yet, then this patch should really wait..
This is my current patch to rework
arch/powerpc/kernel/time.cto create a clocksource. It's not ready for inclusion.
Hey Tony,
Thanks for sending this out! I really appreciate this work, as its been
on my todo forever, and I've just not been able to focus on it. Currently it seems a bit minimal of a conversion (ideally there should be very little time code left), but It looks like a great start!
More comments below.
Quoted 6 lines
powerpc needs to keep the vdso in sync whenener
settimeodfay()is called. Adding the hook the to the clocksource structure was my way of allowing this to happen. There are other approaches, but this seemed to best allow for runtime. Initially I considered usingupdate_vsyscall()but this is called fromdo_timer(), and I don't need this code run then :(
I might be missing a subtlety in the ppc code, but I'm still not sure if I see the need for the clocksource settimeofday hook.
update_vsyscall() is intended to provide a hook that allows the generic time code to provide all the needed timekeeping state to the arch specific vsyscall implementation. It is called any time the base timekeeping variables are changed.
You're already calling timer_recalc_offset from there which looks almost as expensive as the settime hook, so I'm not sure I understand the division.
But to your credit, the patch Sergei and I have been slowly working on (I believe I've sent that to you already, but if not let me know) never got the VDSO code working, so good show!
Quoted 30 lines
arch/powerpc/kernel/time.c +30
-0+static void clocksource_settimeofday (struct clocksource *cs, +struct timespec *ts) +{ +u64 new_xsec; + +#ifdef CONFIG_PPC_ISERIES +if (firmware_has_feature (FW_FEATURE_ISERIES ) && first_settimeofday) { +iSeries_tb_recal (); + first_settimeofday =0 ; + } +#endif + +/* Make userspace gettimeofday spin until we're done. */ + ++vdso_data->tb_update_count; +smp_mb (); + +/* In case of a large backwards jump in time with NTP, we want the +* clock to be updated as soon as the PLL is again in lock. +*/ + last_rtc_update = xtime.tv_sec -658 ; + + new_xsec = xtime.tv_nsec; +if (new_xsec !=0 ) { + new_xsec *=XSEC_PER_SEC ; +do_div (new_xsec,NSEC_PER_SEC ); + } + + new_xsec += (u64 )xtime.tv_sec *XSEC_PER_SEC ; + + vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
arch/powerpc/kernel/time.c unsigned long get_boot_time(void) · line 820
Quoted 10 lines
arch/powerpc/kernel/time.c +10
-0+ vdso_data->tz_dsttime = sys_tz.tz_dsttime; + +update_gtod (tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); +} + +void update_vsyscall (struct timespec *wall_time,struct clocksource *clock) +{ +timer_recalc_offset (tb_last_jiffy); +timer_check_rtc (); +}
I think it would be enlightening to flatten this out a bit. Putting both the timer_recalc_offset and clocksource_settime code in the same function. It might illustrate where some optimizations could be done and where it might make more sense to split things up.
Also I'd leave timer_check_rtc() in the timer_interrupt for now (later moving it to tglx's generic rtc update).
thanks
-john
Re: [RFC] clocksouce implementation for powerpc
On Wed, Jun 20, 2007 at 02:06:01PM -0700, john stultz wrote:
Hi John.
Quoted 5 lines
Hey Tony,
Thanks for sending this out! I really appreciate this work, as its been
on my todo forever, and I've just not been able to focus on it. Currently it seems a bit minimal of a conversion (ideally there should be very little time code left), but It looks like a great start!
Thanks.
Quoted 7 lines
I might be missing a subtlety in the ppc code, but I'm still not sure if I see the need for the clocksource settimeofday hook.
update_vsyscall()is intended to provide a hook that allows the generic time code to provide all the needed timekeeping state to the arch specific vsyscall implementation. It is called any time the base timekeeping variables are changed.
Well as I just said the Daniel, I was under the impression I needed a hook that was only called from settimeofday(). The comments I've recieved from everyone has given me good cause to re-evaluate.
I think I can make it work without the hook, that started this discussion. Thomas, I think it's probably best to axe it now. If I /really/ need it then I'll start the discussion again :) Thanks.
Quoted 7 lines
I think it would be enlightening to flatten this out a bit. Putting both the
timer_recalc_offsetandclocksource_settimecode in the same function. It might illustrate where some optimizations could be done and where it might make more sense to split things up.Also I'd leave
timer_check_rtc()in thetimer_interruptfor now (later moving it to tglx's generic rtc update).
Yes you're rigth I don't need to move the timer_check_rtc() call.
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
PATCH 16/25 x86_64: untangle asm/hpet.h from asm/timex.h
In reply to Thomas GleixnerFrom: Chris Wright <[email protected]>
When making changes to x86_64 timers, I noticed that touching hpet.h triggered an unreasonably large rebuild. Untangling it from timex.h quiets the extra rebuild quite a bit.
--- drivers/char/rtc.c | 2 +- include/asm-x86_64/apic.h | 2 ++ include/asm-x86_64/hpet.h | 1 - include/asm-x86_64/timex.h | 1 - 4 files changed, 3 insertions(+), 3 deletions(-)
drivers/char/rtc.c +1 -1
@@ -82,7 +82,7 @@#include <asm/uaccess.h> #include <asm/system.h> -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__)#include <asm/hpet.h> #endif
include/asm-x86_64/timex.h +0 -1
@@ -9,7 +9,6 @@#include <asm/8253pit.h> #include <asm/msr.h> #include <asm/vsyscall.h> -#include <asm/hpet.h> #include <asm/system.h> #include <asm/processor.h> #include <asm/tsc.h>
include/asm-x86_64/apic.h +2 -0
@@ -86,6 +86,8 @@ extern void setup_apic_routing(void);extern void setup_APIC_extened_lvt (unsigned char lvt_off,unsigned char vector,unsigned char msg_type,unsigned char mask); +extern int apic_is_clustered_box (void ); +#define K8_APIC_EXT_LVT_BASE 0x500#define K8_APIC_EXT_INT_MSG_FIX 0x0#define K8_APIC_EXT_INT_MSG_SMI 0x2
include/asm-x86_64/hpet.h +0 -1
@@ -55,7 +55,6 @@extern int is_hpet_enabled (void );extern int hpet_rtc_timer_init (void ); -extern int apic_is_clustered_box (void );extern int hpet_arch_init (void );extern int hpet_timer_stop_set_go (unsigned long tick);extern int hpet_reenable (void );
PATCH 17/25 x86_64: Use generic cmos update
In reply to Thomas GleixnerUse the generic cmos update function in kernel/time/ntp.c
--- arch/x86_64/Kconfig | 4 ++++ arch/x86_64/kernel/time.c | 25 +++++++++---------------- 2 files changed, 13 insertions(+), 16 deletions(-)
arch/x86_64/kernel/time.c +9 -16
@@ -82,8 +82,9 @@ EXPORT_SYMBOL(profile_pc);* sheet for details. */ -static void set_rtc_mmss (unsigned long nowtime) +static int set_rtc_mmss (unsigned long nowtime) { +int retval =0 ;int real_seconds, real_minutes, cmos_minutes;unsigned char control, freq_select;
@@ -123,6 +124,7 @@ static void set_rtc_mmss(unsigned long nif (abs (real_minutes - cmos_minutes) >=30 ) {printk (KERN_WARNING "time.c: can't update CMOS clock " "from %d to %d\n" , cmos_minutes, real_minutes); + retval =-1 ; }else {BIN_TO_BCD (real_seconds);BIN_TO_BCD (real_minutes);
@@ -142,12 +144,17 @@ static void set_rtc_mmss(unsigned long nCMOS_WRITE (freq_select,RTC_FREQ_SELECT );spin_unlock (&rtc_lock); + +return retval; } +int update_persistent_clock (struct timespec now) +{ +return set_rtc_mmss (now.tv_sec); +}void main_timer_handler (void ) { -static unsigned long rtc_update =0 ;/* * Here we are in the timer irq handler. We have irqs locally disabled (so we * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
@@ -175,20 +182,6 @@ void main_timer_handler(void)if (!using_apic_timer)smp_local_timer_interrupt (); -/* -* If we have an externally synchronized Linux clock, then update CMOS clock -* accordingly every ~11 minutes. set_rtc_mmss() will be called in the jiffy -* closest to exactly 500 ms before the next second. If the update fails, we -* don't care, as it'll be updated on the next turn, and the problem (time way -* off) isn't likely to go away much sooner anyway. -*/ - -if (ntp_synced () && xtime.tv_sec > rtc_update && -abs (xtime.tv_nsec -500000000 ) <= tick_nsec /2 ) { -set_rtc_mmss (xtime.tv_sec); - rtc_update = xtime.tv_sec +660 ; - } -write_sequnlock (&xtime_lock); }
arch/x86_64/Kconfig +4 -0
@@ -32,6 +32,10 @@ config GENERIC_TIME_VSYSCALL bool default y +config GENERIC_CMOS_UPDATE + bool + default y + config ZONE_DMA32 bool default y
PATCH 18/25 i386: move setup_pit_timer to the correct header file
In reply to Thomas Gleixnersetup_pit_timer is declared in asm-i386/timer.h. Move it to the pit header file, so it can be used by x86_64 as well.
--- include/asm-i386/i8253.h | 2 ++ include/asm-i386/timer.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-)
include/asm-i386/i8253.h +2 -0
@@ -18,4 +18,6 @@ static inline void pit_interrupt_hook(vo global_clock_event->event_handler(global_clock_event); } +extern void setup_pit_timer (void ); +#endif /* __ASM_I8253_H__ */
include/asm-i386/timer.h +0 -1
@@ -6,7 +6,6 @@#define TICK_SIZE (tick_nsec / 1000) -void setup_pit_timer (void );unsigned long long native_sched_clock (void );unsigned long native_calculate_cpu_khz (void );
PATCH 19/25 x86-64: remove dead code and other janitor work in tsc.c
In reply to Thomas GleixnerRemove unused code and variables and do some codingstyle / whitespace cleanups while at it.
--- arch/x86_64/kernel/tsc.c | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-)
arch/x86_64/kernel/tsc.c +11 -30
@@ -35,25 +35,9 @@ static inline int check_tsc_unstable(voi* first tick after the change will be slightly wrong. */ -#include <linux/workqueue.h> - -static unsigned int cpufreq_delayed_issched =0 ; -static unsigned int cpufreq_init =0 ; -static struct work_struct cpufreq_delayed_get_work; - -static void handle_cpufreq_delayed_get (struct work_struct *v) -{ -unsigned int cpu; -for_each_online_cpu (cpu) { -cpufreq_get (cpu); - } - cpufreq_delayed_issched =0 ; -} - -static unsigned int ref_freq =0 ; -static unsigned long loops_per_jiffy_ref =0 ; - -static unsigned long tsc_khz_ref =0 ; +static unsigned int ref_freq; +static unsigned long loops_per_jiffy_ref; +static unsigned long tsc_khz_ref;static int time_cpufreq_notifier (struct notifier_block *nb,unsigned long val,void *data)
@@ -97,10 +81,8 @@ static struct notifier_block time_cpufrestatic int __init cpufreq_tsc (void ) { -INIT_WORK (&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); -if (!cpufreq_register_notifier (&time_cpufreq_notifier_block, -CPUFREQ_TRANSITION_NOTIFIER )) - cpufreq_init =1 ; +cpufreq_register_notifier (&time_cpufreq_notifier_block, +CPUFREQ_TRANSITION_NOTIFIER );return 0 ; }
@@ -108,8 +90,6 @@ core_initcall(cpufreq_tsc);#endif -static int tsc_unstable =0 ; -/* * Make an educated guess if the TSC is trustworthy and synchronized * over all CPUs.
@@ -122,17 +102,18 @@ __cpuinit int unsynchronized_tsc(void)#endif /* Most intel systems have synchronized TSCs except for multi node systems */ -if (boot_cpu_data.x86_vendor ==X86_VENDOR_INTEL ) { +if (boot_cpu_data.x86_vendor ==X86_VENDOR_INTEL ) {#ifdef CONFIG_ACPI /* But TSC doesn't tick in C3 so don't use it there */ -if (acpi_gbl_FADT.header.length >0 && acpi_gbl_FADT.C3latency <1000 ) +if (acpi_gbl_FADT.header.length >0 && + acpi_gbl_FADT.C3latency <1000 )return 1 ;#endif -return 0 ; +return 0 ; } -/* Assume multi socket systems are not synchronized */ -return num_present_cpus () >1 ; +/* Assume multi socket systems are not synchronized */ +return num_present_cpus () >1 ; }int __init notsc_setup (char *s)
PATCH 20/25 x86_64: Convert to cleckevents
In reply to Thomas GleixnerConvert x86_64 to the clockevents code. Share code with i386 for hpet and PIT.
Build and whitespace fixups from:
Venki Pallipadi <[email protected]>
and
Chris Wright <[email protected]>
Based on an initial patch from Chris Wright <[email protected]>
--- arch/i386/kernel/hpet.c | 50 ++ arch/i386/kernel/i8253.c | 5 arch/x86_64/Kconfig | 12 arch/x86_64/kernel/Makefile | 4 arch/x86_64/kernel/apic.c | 567 +++++++++++++++++-------------- arch/x86_64/kernel/hpet.c | 493 -------------------------- arch/x86_64/kernel/i8259.c | 47 -- arch/x86_64/kernel/mce_amd.c | 6 arch/x86_64/kernel/smpboot.c | 4 arch/x86_64/kernel/time.c | 253 +------------ arch/x86_64/kernel/tsc.c | 90 ++++ drivers/acpi/processor_idle.c | 12 include/asm-i386/hpet.h | 125 ++---- include/asm-i386/i8253.h | 5 include/asm-i386/mach-default/io_ports.h | 5 include/asm-i386/tsc.h | 4 include/asm-x86_64/apic.h | 10 include/asm-x86_64/hpet.h | 77 ---- include/asm-x86_64/i8253.h | 8 include/asm-x86_64/proto.h | 3 20 files changed, 569 insertions(+), 1211 deletions(-)
arch/x86_64/kernel/apic.c +320 -247
@@ -25,6 +25,8 @@#include <linux/sysdev.h> #include <linux/module.h> #include <linux/ioport.h> +#include <linux/clockchips.h> +#include <linux/acpi_pmtmr.h> #include <asm/atomic.h> #include <asm/smp.h>
@@ -38,10 +40,10 @@#include <asm/timex.h> #include <asm/hpet.h> #include <asm/apic.h> +#include <asm/i8253.h> int apic_mapped;int apic_verbosity; -int apic_runs_main_timer;int apic_calibrate_pmtmr__initdata ;int disable_apic_timer__initdata ;
@@ -50,20 +52,36 @@ int disable_apic_timer __initdata;int local_apic_timer_c2_ok;EXPORT_SYMBOL_GPL (local_apic_timer_c2_ok); +/* Local APIC timer verification ok */ +static int local_apic_timer_verify_ok; +static struct resource *ioapic_resources;static struct resource lapic_resource = { .name ="Local APIC" , .flags =IORESOURCE_MEM |IORESOURCE_BUSY , }; -/* -* cpu_mask that denotes the CPUs that needs timer interrupt coming in as -* IPIs in place of local APIC timers -*/ -static cpumask_t timer_interrupt_broadcast_ipi_mask; +static unsigned int calibration_result; -/* Using APIC to generate smp_local_timer_interrupt? */ -int using_apic_timer__read_mostly =0 ; +static int lapic_next_event (unsigned long delta, +struct clock_event_device *evt); +static void lapic_timer_setup (enum clock_event_mode mode, +struct clock_event_device *evt); + +static void lapic_timer_broadcast (cpumask_t mask); + +static struct clock_event_device lapic_clockevent = { + .name ="lapic" , + .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT + |CLOCK_EVT_FEAT_C3STOP |CLOCK_EVT_FEAT_DUMMY , + .shift =32 , + .set_mode = lapic_timer_setup, + .set_next_event = lapic_next_event, + .broadcast = lapic_timer_broadcast, + .rating =100 , + .irq =-1 , +}; +static DEFINE_PER_CPU(struct clock_event_device, lapic_events);static void apic_pm_activate (void );
@@ -92,8 +110,9 @@ unsigned int safe_apic_wait_icr_idle(voivoid enable_NMI_through_LVT0 (void * dummy) {unsigned int v; - - v =APIC_DM_NMI ;/* unmask and set to NMI */ + +/* unmask and set to NMI */ + v =APIC_DM_NMI ;apic_write (APIC_LVT0 , v); }
@@ -120,7 +139,7 @@ void ack_bad_irq(unsigned int irq)* holds up an irq slot - in excessive cases (when multiple * unexpected vectors occur) that might lock up the APIC * completely. -* But don't ack when the APIC is disabled. -AK +* But don't ack when the APIC is disabled. -AK */ if (!disable_apic)ack_APIC_irq ();
@@ -616,7 +635,7 @@ early_param("apic", apic_set_verbosity);* Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. * On AMD64 we trust the BIOS - if it says no APIC it is likely -* not correctly set up (usually the APIC timer won't work etc.) +* not correctly set up (usually the APIC timer won't work etc.) */ static int __init detect_init_APIC (void )
@@ -759,14 +778,14 @@ void __init init_apic_mappings(void)#define APIC_DIVISOR 16 -static void __setup_APIC_LVTT (unsigned int clocks) +static void __setup_APIC_LVTT (unsigned int clocks,int oneshot,int irqen) {unsigned int lvtt_value, tmp_value; -int cpu =smp_processor_id (); - - lvtt_value =APIC_LVT_TIMER_PERIODIC |LOCAL_TIMER_VECTOR ; -if (cpu_isset (cpu, timer_interrupt_broadcast_ipi_mask)) + lvtt_value =LOCAL_TIMER_VECTOR ; +if (!oneshot) + lvtt_value |=APIC_LVT_TIMER_PERIODIC ; +if (!irqen) lvtt_value |=APIC_LVT_MASKED ;apic_write (APIC_LVTT , lvtt_value);
@@ -779,227 +798,313 @@ static void __setup_APIC_LVTT(unsigned i & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | APIC_TDR_DIV_16); -apic_write (APIC_TMICT , clocks/APIC_DIVISOR ); +if (!oneshot) +apic_write (APIC_TMICT , clocks/APIC_DIVISOR ); } -static void setup_APIC_timer (unsigned int clocks) +static int lapic_next_event (unsigned long delta, +struct clock_event_device *evt) +{ +apic_write (APIC_TMICT , delta); +return 0 ; +} + +static void lapic_timer_setup (enum clock_event_mode mode, +struct clock_event_device *evt) {unsigned long flags; +unsigned int v; + +/* Lapic used for broadcast ? */ +if (!local_apic_timer_verify_ok) +return ;local_irq_save (flags); -/* wait for irq slice */ -if (hpet_address && hpet_use_timer) { -int trigger =hpet_readl (HPET_T0_CMP ); -while (hpet_readl (HPET_COUNTER ) >= trigger) -/* do nothing */ ; -while (hpet_readl (HPET_COUNTER ) < trigger) -/* do nothing */ ; - }else { -int c1, c2; -outb_p (0x00 ,0x43 ); - c2 =inb_p (0x40 ); - c2 |=inb_p (0x40 ) <<8 ; -do { - c1 = c2; -outb_p (0x00 ,0x43 ); - c2 =inb_p (0x40 ); - c2 |=inb_p (0x40 ) <<8 ; - }while (c2 - c1 <300 ); - } -__setup_APIC_LVTT (clocks); -/* Turn off PIT interrupt if we use APIC timer as main timer. -Only works with the PM timer right now -TBD fix it for HPET too. */ -if ((pmtmr_ioport !=0 ) && -smp_processor_id () == boot_cpu_id && - apic_runs_main_timer ==1 && - !cpu_isset (boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) { -stop_timer_interrupt (); - apic_runs_main_timer++; +switch (mode) { +case CLOCK_EVT_MODE_PERIODIC : +case CLOCK_EVT_MODE_ONESHOT : +__setup_APIC_LVTT (calibration_result, + mode !=CLOCK_EVT_MODE_PERIODIC ,1 ); +break ; +case CLOCK_EVT_MODE_UNUSED : +case CLOCK_EVT_MODE_SHUTDOWN : + v =apic_read (APIC_LVTT ); + v |= (APIC_LVT_MASKED |LOCAL_TIMER_VECTOR ); +apic_write (APIC_LVTT , v); +break ; +case CLOCK_EVT_MODE_RESUME : +/* Nothing to do here */ +break ; } +local_irq_restore (flags); }/* -* In this function we calibrate APIC bus clocks to the external -* timer. Unfortunately we cannot use jiffies and the timer irq -* to calibrate, since some later bootup code depends on getting -* the first irq? Ugh. -* -* We want to do the calibration only once since we -* want to have local timer irqs syncron. CPUs connected -* by the same APIC bus have the very same bus frequency. -* And we want to have irqs off anyways, no accidental -* APIC irq that way. +* Local APIC timer broadcast function */ - -#define TICK_COUNT 100000000 - -static int __init calibrate_APIC_clock (void ) +static void lapic_timer_broadcast (cpumask_t mask) { -unsigned apic, apic_start; -unsigned long tsc, tsc_start; -int result; -/* -* Put whatever arbitrary (but long enough) timeout -* value into the APIC clock, we just want to get the -* counter running for calibration. -*/ -__setup_APIC_LVTT (4000000000 ); - - apic_start =apic_read (APIC_TMCCT ); -#ifdef CONFIG_X86_PM_TIMER -if (apic_calibrate_pmtmr && pmtmr_ioport) { -pmtimer_wait (5000 );/* 5ms wait */ - apic =apic_read (APIC_TMCCT ); - result = (apic_start - apic) *1000L /5 ; - } else +#ifdef CONFIG_SMP +send_IPI_mask (mask,LOCAL_TIMER_VECTOR );#endif - { -rdtscll (tsc_start); +} -do { - apic =apic_read (APIC_TMCCT ); -rdtscll (tsc); - }while ((tsc - tsc_start) <TICK_COUNT && - (apic_start - apic) <TICK_COUNT ); +static void __devinit setup_APIC_timer (void ) +{ +struct clock_event_device *levt = &__get_cpu_var (lapic_events); - result = (apic_start - apic) *1000L * tsc_khz / - (tsc - tsc_start); - } -printk ("result %d\n" , result); +memcpy (levt, &lapic_clockevent,sizeof (*levt)); + levt->cpumask =cpumask_of_cpu (smp_processor_id ()); + +clockevents_register_device (levt); +} + +/* +* In this functions we calibrate APIC bus clocks to the external timer. +* +* We want to do the calibration only once since we want to have local timer +* irqs syncron. CPUs connected by the same APIC bus have the very same bus +* frequency. +* +* This was previously done by reading the PIT/HPET and waiting for a wrap +* around to find out, that a tick has elapsed. I have a box, where the PIT +* readout is broken, so it never gets out of the wait loop again. This was +* also reported by others. +* +* Monitoring the jiffies value is inaccurate and the clockevents +* infrastructure allows us to do a simple substitution of the interrupt +* handler. +* +* The calibration routine also uses the pm_timer when possible, as the PIT +* happens to run way too slow (factor 2.3 on my VAIO CoreDuo, which goes +* back to normal later in the boot process). +*/ +#define LAPIC_CAL_LOOPS (HZ/10) -printk (KERN_INFO "Detected %d.%03d MHz APIC timer.\n" , - result /1000 /1000 , result /1000 %1000 ); +static __initdata volatile int lapic_cal_loops =-1 ; +static __initdata long lapic_cal_t1, lapic_cal_t2; +static __initdata unsigned long long lapic_cal_tsc1, lapic_cal_tsc2; +static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2; +static __initdata unsigned long lapic_cal_j1, lapic_cal_j2; -return result *APIC_DIVISOR /HZ ; +/* +* Temporary interrupt handler. +*/ +static void __init lapic_cal_handler (struct clock_event_device *dev) +{ +unsigned long long tsc =0 ; +long tapic =apic_read (APIC_TMCCT ); +unsigned long pm =acpi_pm_read_early (); + +if (cpu_has_tsc) +rdtscll (tsc); + +switch (lapic_cal_loops++) { +case 0 : + lapic_cal_t1 = tapic; + lapic_cal_tsc1 = tsc; + lapic_cal_pm1 = pm; + lapic_cal_j1 = jiffies; +break ; + +case LAPIC_CAL_LOOPS : + lapic_cal_t2 = tapic; + lapic_cal_tsc2 = tsc; +if (pm < lapic_cal_pm1) + pm +=ACPI_PM_OVRRUN ; + lapic_cal_pm2 = pm; + lapic_cal_j2 = jiffies; +break ; + } } -static unsigned int calibration_result; -void __init setup_boot_APIC_clock (void ) { -if (disable_apic_timer) { -printk (KERN_INFO "Disabling APIC timer\n" ); -return ; - } +struct clock_event_device *levt = &__get_cpu_var (lapic_events); +const long pm_100ms =PMTMR_TICKS_PER_SEC /10 ; +const long pm_thresh = pm_100ms/100 ; +void (*real_handler)(struct clock_event_device *dev); +unsigned long deltaj; +long delta, deltapm; +int pm_referenced =0 ; + +/* +* The local apic timer can be disabled via the kernel +* commandline or from the test above. Register the lapic +* timer as a dummy clock event source on SMP systems, so the +* broadcast mechanism is used. On UP systems simply ignore it. +*/ +if (disable_apic_timer) { +printk (KERN_INFO "Disabling APIC timer\n" ); +/* No broadcast on UP ! */ +if (num_possible_cpus () >1 ) +setup_APIC_timer (); +return ; + }printk (KERN_INFO "Using local APIC timer interrupts.\n" ); - using_apic_timer =1 ; -local_irq_disable (); +/* Replace the global interrupt handler */ + real_handler = global_clock_event->event_handler; + global_clock_event->event_handler = lapic_cal_handler; - calibration_result =calibrate_APIC_clock ();/* -* Now set up the timer for real. +* Setup the APIC counter to 1e9. There is no way the lapic +* can underflow in the 100ms detection time frame */ -setup_APIC_timer (calibration_result); +__setup_APIC_LVTT (1000000000 ,0 ,0 ); +/* Let the interrupts run */ local_irq_enable (); -} -void __cpuinit setup_secondary_APIC_clock (void ) -{ -local_irq_disable ();/* FIXME: Do we need this? --RR */ -setup_APIC_timer (calibration_result); -local_irq_enable (); -} +while (lapic_cal_loops <=LAPIC_CAL_LOOPS ) +cpu_relax (); -void disable_APIC_timer (void ) -{ -if (using_apic_timer) { -unsigned long v; +local_irq_disable (); - v =apic_read (APIC_LVTT ); -/* -* When an illegal vector value (0-15) is written to an LVT -* entry and delivery mode is Fixed, the APIC may signal an -* illegal vector error, with out regard to whether the mask -* bit is set or whether an interrupt is actually seen on input. -* -* Boot sequence might call this function when the LVTT has -* '0' vector value. So make sure vector field is set to -* valid value. -*/ - v |= (APIC_LVT_MASKED |LOCAL_TIMER_VECTOR ); -apic_write (APIC_LVTT , v); +/* Restore the real event handler */ + global_clock_event->event_handler = real_handler; + +/* Build delta t1-t2 as apic timer counts down */ + delta = lapic_cal_t1 - lapic_cal_t2; +apic_printk (APIC_VERBOSE ,"... lapic delta = %ld\n" , delta); + +/* Check, if the PM timer is available */ + deltapm = lapic_cal_pm2 - lapic_cal_pm1; +apic_printk (APIC_VERBOSE ,"... PM timer delta = %ld\n" , deltapm); + +if (deltapm) { +unsigned long mult; +u64 res; + + mult =clocksource_hz2mult (PMTMR_TICKS_PER_SEC ,22 ); + +if (deltapm > (pm_100ms - pm_thresh) && + deltapm < (pm_100ms + pm_thresh)) { +apic_printk (APIC_VERBOSE ,"... PM timer result ok\n" ); + }else { + res = (((u64 ) deltapm) * mult) >>22 ; +do_div (res,1000000 ); +printk (KERN_WARNING "APIC calibration not consistent " +"with PM Timer: %ldms instead of 100ms\n" , + (long )res); +/* Correct the lapic counter value */ + res = (((u64 ) delta ) * pm_100ms); +do_div (res, deltapm); +printk (KERN_INFO "APIC delta adjusted to PM-Timer: " +"%lu (%ld)\n" , (unsigned long ) res, delta); + delta = (long ) res; + } + pm_referenced =1 ; } -} -void enable_APIC_timer (void ) -{ -int cpu =smp_processor_id (); +/* Calculate the scaled math multiplication factor */ + lapic_clockevent.mult =div_sc (delta,TICK_NSEC *LAPIC_CAL_LOOPS ,32 ); + lapic_clockevent.max_delta_ns = +clockevent_delta2ns (0x7FFFFF , &lapic_clockevent); + lapic_clockevent.min_delta_ns = +clockevent_delta2ns (0xF , &lapic_clockevent); -if (using_apic_timer && - !cpu_isset (cpu, timer_interrupt_broadcast_ipi_mask)) { -unsigned long v; + calibration_result = (delta *APIC_DIVISOR ) /LAPIC_CAL_LOOPS ; - v =apic_read (APIC_LVTT ); -apic_write (APIC_LVTT , v & ~APIC_LVT_MASKED ); +apic_printk (APIC_VERBOSE ,"..... delta %ld\n" , delta); +apic_printk (APIC_VERBOSE ,"..... mult: %ld\n" , lapic_clockevent.mult); +apic_printk (APIC_VERBOSE ,"..... calibration result: %u\n" , + calibration_result); + +if (cpu_has_tsc) { + delta = (long )(lapic_cal_tsc2 - lapic_cal_tsc1); +apic_printk (APIC_VERBOSE ,"..... CPU clock speed is " +"%ld.%04ld MHz.\n" , + (delta /LAPIC_CAL_LOOPS ) / (1000000 /HZ ), + (delta /LAPIC_CAL_LOOPS ) % (1000000 /HZ )); } -} -void switch_APIC_timer_to_ipi (void *cpumask) -{ -cpumask_t mask = *(cpumask_t *)cpumask; -int cpu =smp_processor_id (); +apic_printk (APIC_VERBOSE ,"..... host bus clock speed is " +"%u.%04u MHz.\n" , + calibration_result / (1000000 /HZ ), + calibration_result % (1000000 /HZ )); -if (cpu_isset (cpu, mask) && - !cpu_isset (cpu, timer_interrupt_broadcast_ipi_mask)) { -disable_APIC_timer (); -cpu_set (cpu, timer_interrupt_broadcast_ipi_mask); - } -} -EXPORT_SYMBOL (switch_APIC_timer_to_ipi); + local_apic_timer_verify_ok =1 ; -void smp_send_timer_broadcast_ipi (void ) -{ -int cpu =smp_processor_id (); -cpumask_t mask; +/* We trust the pm timer based calibration */ +if (!pm_referenced) { +apic_printk (APIC_VERBOSE ,"... verify APIC timer\n" ); -cpus_and (mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask); +/* +* Setup the apic timer manually +*/ + levt->event_handler = lapic_cal_handler; +lapic_timer_setup (CLOCK_EVT_MODE_PERIODIC , levt); + lapic_cal_loops =-1 ; -if (cpu_isset (cpu, mask)) { -cpu_clear (cpu, mask); -add_pda (apic_timer_irqs,1 ); -smp_local_timer_interrupt (); - } +/* Let the interrupts run */ +local_irq_enable (); + +while (lapic_cal_loops <=LAPIC_CAL_LOOPS ) +cpu_relax (); + +local_irq_disable (); + +/* Stop the lapic timer */ +lapic_timer_setup (CLOCK_EVT_MODE_SHUTDOWN , levt); + +local_irq_enable (); -if (!cpus_empty (mask)) { -send_IPI_mask (mask,LOCAL_TIMER_VECTOR ); +/* Jiffies delta */ + deltaj = lapic_cal_j2 - lapic_cal_j1; +apic_printk (APIC_VERBOSE ,"... jiffies delta = %lu\n" , deltaj); + +/* Check, if the jiffies result is consistent */ +if (deltaj >=LAPIC_CAL_LOOPS -2 && deltaj <=LAPIC_CAL_LOOPS +2 ) +apic_printk (APIC_VERBOSE ,"... jiffies result ok\n" ); +else + local_apic_timer_verify_ok =0 ; + }else +local_irq_enable (); + +if (!local_apic_timer_verify_ok) { +printk (KERN_WARNING +"APIC timer disabled due to verification failure.\n" ); +/* No broadcast on UP ! */ +if (num_possible_cpus () ==1 ) +return ; + }else { +/* +* If nmi_watchdog is set to IO_APIC, we need the +* PIT/HPET going. Otherwise register lapic as a dummy +* device. +*/ +if (nmi_watchdog !=NMI_IO_APIC ) + lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY ; } + +/* Setup the lapic or request the broadcast */ +setup_APIC_timer (); } -void switch_ipi_to_APIC_timer (void *cpumask) +void __cpuinit setup_secondary_APIC_clock (void ) { -cpumask_t mask = *(cpumask_t *)cpumask; -int cpu =smp_processor_id (); - -if (cpu_isset (cpu, mask) && -cpu_isset (cpu, timer_interrupt_broadcast_ipi_mask)) { -cpu_clear (cpu, timer_interrupt_broadcast_ipi_mask); -enable_APIC_timer (); - } +setup_APIC_timer (); } -EXPORT_SYMBOL (switch_ipi_to_APIC_timer);int setup_profiling_timer (unsigned int multiplier) {return -EINVAL ; } -void setup_APIC_extened_lvt (unsigned char lvt_off,unsigned char vector, -unsigned char msg_type,unsigned char mask) +void setup_APIC_extended_lvt (unsigned char lvt_off,unsigned char vector, +unsigned char msg_type,unsigned char mask) {unsigned long reg = (lvt_off <<4 ) +K8_APIC_EXT_LVT_BASE ;unsigned int v = (mask <<16 ) | (msg_type <<8 ) | vector; +apic_write (reg, v); } -#undef APIC_DIVISOR -/* * Local timer interrupt handler. It does both profiling and * process statistics/rescheduling.
@@ -1010,24 +1115,36 @@ void setup_APIC_extened_lvt(unsigned cha* value into /proc/profile. */ -void smp_local_timer_interrupt (void ) +void local_apic_timer_interrupt (void ) { -profile_tick (CPU_PROFILING ); -#ifdef CONFIG_SMP -update_process_times (user_mode (get_irq_regs ())); -#endif -if (apic_runs_main_timer >1 &&smp_processor_id () == boot_cpu_id) -main_timer_handler (); +int cpu =smp_processor_id (); +struct clock_event_device *evt = &per_cpu (lapic_events, cpu); +/* -* We take the 'long' return path, and there every subsystem -* grabs the appropriate locks (kernel lock/ irq lock). -* -* We might want to decouple profiling from the 'long path', -* and do the profiling totally in assembly. +* Normally we should not be here till LAPIC has been initialized but +* in some cases like kdump, its possible that there is a pending LAPIC +* timer interrupt from previous kernel's context and is delivered in +* new kernel the moment interrupts are enabled. * -* Currently this isn't too much of an issue (performance wise), -* we can take more than 100K local irqs per second on a 100 MHz P5. +* Interrupts are enabled early and LAPIC is setup much later, hence +* its possible that when we get here evt->event_handler is NULL. +* Check for event_handler being NULL and discard the interrupt as +* spurious. +*/ +if (!evt->event_handler) { +printk (KERN_WARNING +"Spurious LAPIC timer interrupt on cpu %d\n" , cpu); +/* Switch it off */ +lapic_timer_setup (CLOCK_EVT_MODE_SHUTDOWN , evt); +return ; + } + +/* +* the NMI deadlock-detector uses this. */ +add_pda (apic_timer_irqs,1 ); + + evt->event_handler (evt); }/*
@@ -1043,11 +1160,6 @@ void smp_apic_timer_interrupt(struct pt_struct pt_regs *old_regs =set_irq_regs (regs);/* -* the NMI deadlock-detector uses this. -*/ -add_pda (apic_timer_irqs,1 ); - -/* * NOTE! We'd better ACK the irq immediately, * because timer handling can be slow. */
@@ -1059,7 +1171,7 @@ void smp_apic_timer_interrupt(struct pt_*/ exit_idle ();irq_enter (); -smp_local_timer_interrupt (); +local_apic_timer_interrupt ();irq_exit ();set_irq_regs (old_regs); }
@@ -1127,21 +1239,6 @@ asmlinkage void smp_spurious_interrupt(v v =apic_read (APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f ) >>1 ));if (v & (1 << (SPURIOUS_APIC_VECTOR &0x1f )))ack_APIC_irq (); - -#if 0 -static unsigned long last_warning; -static unsigned long skipped; - -/* see sw-dev-man vol 3, chapter 7.4.13.5 */ -if (time_before (last_warning+30 *HZ ,jiffies)) { -printk (KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n" , -smp_processor_id (), skipped); - last_warning = jiffies; - skipped =0 ; - }else { - skipped++; - } -#endif irq_exit (); }
@@ -1173,11 +1270,11 @@ asmlinkage void smp_error_interrupt(void7: Illegal register address */ printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n" , -smp_processor_id (), v , v1); +smp_processor_id (), v , v1);irq_exit (); } -int disable_apic; +int disable_apic;/* * This initializes the IO-APIC and APIC hardware if this is
@@ -1185,11 +1282,11 @@ int disable_apic;*/ int __init APIC_init_uniprocessor (void ) { -if (disable_apic) { +if (disable_apic) {printk (KERN_INFO "Apic disabled\n" ); -return -1 ; +return -1 ; } -if (!cpu_has_apic) { +if (!cpu_has_apic) { disable_apic =1 ;printk (KERN_INFO "Apic disabled by BIOS\n" );return -1 ;
@@ -1211,8 +1308,8 @@ int __init APIC_init_uniprocessor (void)return 0 ; } -static __init int setup_disableapic (char *str) -{ +static __init int setup_disableapic (char *str) +{ disable_apic =1 ;clear_bit (X86_FEATURE_APIC , boot_cpu_data.x86_capability);return 0 ;
@@ -1220,10 +1317,10 @@ static __init int setup_disableapic(charearly_param ("disableapic" , setup_disableapic);/* same as disableapic, for compatibility */ -static __init int setup_nolapic (char *str) -{ +static __init int setup_nolapic (char *str) +{return setup_disableapic (str); -} +}early_param ("nolapic" , setup_nolapic);static int __init parse_lapic_timer_c2_ok (char *arg)
@@ -1233,36 +1330,12 @@ static int __init parse_lapic_timer_c2_o }early_param ("lapic_timer_c2_ok" , parse_lapic_timer_c2_ok); -static __init int setup_noapictimer (char *str) -{ +static __init int setup_noapictimer (char *str) +{if (str[0 ] !=' ' && str[0 ] !=0 )return 0 ; disable_apic_timer =1 ;return 1 ; -} - -static __init int setup_apicmaintimer (char *str) -{ - apic_runs_main_timer =1 ; - nohpet =1 ; -return 1 ; } -__setup ("apicmaintimer" , setup_apicmaintimer); - -static __init int setup_noapicmaintimer (char *str) -{ - apic_runs_main_timer =-1 ; -return 1 ; -} -__setup ("noapicmaintimer" , setup_noapicmaintimer); - -static __init int setup_apicpmtimer (char *s) -{ - apic_calibrate_pmtmr =1 ; -notsc_setup (NULL ); -return setup_apicmaintimer (NULL ); -} -__setup ("apicpmtimer" , setup_apicpmtimer); - -__setup ("noapictimer" , setup_noapictimer); +__setup ("noapictimer" , setup_noapictimer);
arch/x86_64/kernel/time.c +29 -224
334 lines not on this page · raw message
arch/x86_64/kernel/hpet.c deleted +0 -493
493 lines not on this page · raw message
arch/x86_64/Kconfig +12 -0
@@ -28,6 +28,18 @@ config GENERIC_TIME bool default y +config GENERIC_CLOCKEVENTS + bool + default y + +config GENERIC_CLOCKEVENTS_BROADCAST + bool + default y + +config NONIRQ_WAKEUP + bool + default y + config GENERIC_TIME_VSYSCALL bool default y
include/asm-x86_64/hpet.h +1 -76
78 lines not on this page · raw message
include/asm-i386/hpet.h +50 -75
162 lines not on this page · raw message
arch/i386/kernel/hpet.c +45 -5
97 lines not on this page · raw message
arch/x86_64/kernel/mce_amd.c +3 -3
@@ -157,9 +157,9 @@ void __cpuinit mce_amd_feature_init(stru high |=K8_APIC_EXT_LVT_ENTRY_THRESHOLD <<20 ;wrmsr (address, low, high); -setup_APIC_extened_lvt (K8_APIC_EXT_LVT_ENTRY_THRESHOLD , -THRESHOLD_APIC_VECTOR , -K8_APIC_EXT_INT_MSG_FIX ,0 ); +setup_APIC_extended_lvt (K8_APIC_EXT_LVT_ENTRY_THRESHOLD , +THRESHOLD_APIC_VECTOR , +K8_APIC_EXT_INT_MSG_FIX ,0 ); threshold_defaults.address = address;threshold_restart_bank (&threshold_defaults,0 ,0 );
arch/x86_64/kernel/smpboot.c +0 -4
@@ -223,8 +223,6 @@ void __cpuinit smp_callin(void)local_irq_disable ();Dprintk ("Stack at about %p\n" ,&cpuid); -disable_APIC_timer (); -/* * Save our processor parameters */
@@ -348,8 +346,6 @@ void __cpuinit start_secondary(void)enable_8259A_irq (0 ); } -enable_APIC_timer (); -/* * The sibling maps must be set before turing the online map on for * this cpu
drivers/acpi/processor_idle.c +0 -12
@@ -203,21 +203,12 @@ static void acpi_timer_check_state(int sstatic void acpi_propagate_timer_broadcast (struct acpi_processor *pr) { -#ifdef CONFIG_GENERIC_CLOCKEVENTS unsigned long reason; reason = pr->power.timer_broadcast_on_state <INT_MAX ?CLOCK_EVT_NOTIFY_BROADCAST_ON :CLOCK_EVT_NOTIFY_BROADCAST_OFF ;clockevents_notify (reason, &pr->id); -#else -cpumask_t mask =cpumask_of_cpu (pr->id); - -if (pr->power.timer_broadcast_on_state <INT_MAX ) -on_each_cpu (switch_APIC_timer_to_ipi, &mask,1 ,1 ); -else -on_each_cpu (switch_ipi_to_APIC_timer, &mask,1 ,1 ); -#endif }/* Power(C) State timer broadcast control */
@@ -225,8 +216,6 @@ static void acpi_state_timer_broadcast(sstruct acpi_processor_cx *cx, int broadcast) { -#ifdef CONFIG_GENERIC_CLOCKEVENTS - int state = cx - pr->power.states;if (state >= pr->power.timer_broadcast_on_state) {
@@ -236,7 +225,6 @@ static void acpi_state_timer_broadcast(sCLOCK_EVT_NOTIFY_BROADCAST_EXIT ; clockevents_notify(reason, &pr->id); } -#endif }#else
include/asm-x86_64/i8253.h +2 -6
@@ -1,6 +1,2 @@ -#ifndef __ASM_I8253_H__ -#define __ASM_I8253_H__ - -extern spinlock_t i8253_lock; - -#endif /* __ASM_I8253_H__ */ +#include <asm-i386/i8253.h> +#include <asm/8253pit.h>
include/asm-x86_64/proto.h +0 -3
@@ -51,9 +51,6 @@ extern void reserve_bootmem_generic(unsiextern void load_gs_index (unsigned gs); -extern void stop_timer_interrupt (void ); -extern void main_timer_handler (void ); -extern unsigned long end_pfn_map;extern void show_trace (struct task_struct *,struct pt_regs *,unsigned long * rsp);
include/asm-x86_64/apic.h +2 -8
@@ -79,12 +79,10 @@ extern void smp_local_timer_interrupt (vextern void setup_boot_APIC_clock (void );extern void setup_secondary_APIC_clock (void );extern int APIC_init_uniprocessor (void ); -extern void disable_APIC_timer (void ); -extern void enable_APIC_timer (void );extern void setup_apic_routing (void ); -extern void setup_APIC_extened_lvt (unsigned char lvt_off,unsigned char vector, -unsigned char msg_type,unsigned char mask); +extern void setup_APIC_extended_lvt (unsigned char lvt_off,unsigned char vector, +unsigned char msg_type,unsigned char mask);extern int apic_is_clustered_box (void );
@@ -95,10 +93,6 @@ extern int apic_is_clustered_box(void);#define K8_APIC_EXT_INT_MSG_EXT 0x7#define K8_APIC_EXT_LVT_ENTRY_THRESHOLD 0 -void smp_send_timer_broadcast_ipi (void ); -void switch_APIC_timer_to_ipi (void *cpumask); -void switch_ipi_to_APIC_timer (void *cpumask); -#define ARCH_APICTIMER_STOPS_ON_C3 1extern unsigned boot_cpu_id;
arch/i386/kernel/i8253.c +3 -2
@@ -15,8 +15,6 @@#include <asm/io.h> #include <asm/timer.h> -#include "io_ports.h" -DEFINE_SPINLOCK (i8253_lock);EXPORT_SYMBOL (i8253_lock);
@@ -122,6 +120,7 @@ void __init setup_pit_timer(void) global_clock_event = &pit_clockevent; } +#ifndef CONFIG_X86_64 /* * Since the PIT overflows every tick, its not very useful * to just read by itself. So use jiffies to emulate a free
@@ -206,3 +205,5 @@ static int __init init_pit_clocksource(v return clocksource_register(&clocksource_pit); }arch_initcall (init_pit_clocksource); + +#endif
arch/x86_64/kernel/tsc.c +90 -0
103 lines not on this page · raw message
include/asm-i386/tsc.h +4 -0
@@ -71,4 +71,8 @@ extern void init_tsc_clocksource(void);extern void check_tsc_sync_source (int cpu);extern void check_tsc_sync_target (void ); +#ifdef CONFIG_X86_64 +extern void tsc_calibrate (void ); +#endif +#endif
arch/x86_64/kernel/i8259.c +0 -47
59 lines not on this page · raw message
include/asm-i386/mach-default/io_ports.h +0 -5
@@ -7,11 +7,6 @@#ifndef _MACH_IO_PORTS_H#define _MACH_IO_PORTS_H -/* i8253A PIT registers */ -#define PIT_MODE 0x43 -#define PIT_CH0 0x40 -#define PIT_CH2 0x42 -/* i8259A PIC registers */ #define PIC_MASTER_CMD 0x20#define PIC_MASTER_IMR 0x21
include/asm-i386/i8253.h +5 -0
@@ -3,6 +3,11 @@#include <linux/clockchips.h> +/* i8253A PIT registers */ +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 +#define PIT_CH2 0x42 +extern spinlock_t i8253_lock;extern struct clock_event_device *global_clock_event;
arch/x86_64/kernel/Makefile +3 -1
@@ -9,7 +9,7 @@ obj-y := process.o signal.o entry.o trap x8664_ksyms.o i387.o syscall.o vsyscall.o \ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o bugs.o \ - perfctr-watchdog.o sched-clock.o + perfctr-watchdog.o sched-clock.o i8253.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_X86_MCE) += mce.o therm_throt.o
@@ -49,6 +49,8 @@ obj-y += pcspeaker.o CFLAGS_vsyscall.o := $(PROFILING) -g0 +i8253-y += ../../i386/kernel/i8253.o +hpet-y += ../../i386/kernel/hpet.o therm_throt-y += ../../i386/kernel/cpu/mcheck/therm_throt.o bootflag-y += ../../i386/kernel/bootflag.o legacy_serial-y += ../../i386/kernel/legacy_serial.o
PATCH 21/25 x86_64: hpet restore vread
In reply to Thomas GleixnerQuoted 1 line
From [email protected]
It seems the hpet clocksource's vread method was lost in the x86_64 conversion to clockevents. So here it is.
arch/i386/kernel/hpet.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/i386/kernel/hpet.c +10 -0
@@ -255,6 +255,13 @@ static cycle_t read_hpet(void)return (cycle_t )hpet_readl (HPET_COUNTER ); } +#ifdef CONFIG_X86_64 +static cycle_t __vsyscall_fn vread_hpet(void) +{ +return readl ((const void __iomem *)fix_to_virt (VSYSCALL_HPET ) +0xf0 ); +} +#endif +static struct clocksource clocksource_hpet = { .name ="hpet" , .rating =250 ,
@@ -263,6 +270,9 @@ static struct clocksource clocksource_hp .shift = HPET_SHIFT, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .resume = hpet_start_counter, +#ifdef CONFIG_X86_64 + .vread = vread_hpet, +#endif };/*
PATCH 22/25 x86_64: restore restore nohpet cmdline
In reply to Thomas GleixnerFrom: Chris Wright <[email protected]>
Lost when merged with i386. Happy to drop, but I suspect Andi would rather not break existing users (I noticed because it was part of my testing). If dropped, Documentation needs updating.
--- arch/i386/kernel/hpet.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/i386/kernel/hpet.c +7 -0
@@ -89,6 +89,13 @@ static int __init hpet_setup(char* str) }__setup ("hpet=" , hpet_setup); +static int __init disable_hpet (char *str) +{ + boot_hpet_disable =1 ; +return 1 ; +} +__setup ("nohpet" , disable_hpet); +static inline int is_hpet_capable (void ) {return (!boot_hpet_disable && hpet_address);
PATCH 23/25 x86-64 block irq balancing for timer
In reply to Thomas GleixnerFrom: Venki Pallipadi <[email protected]>
Disable irq balancing on IRQ0.
--- arch/x86_64/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86_64/kernel/time.c +1 -1
@@ -255,7 +255,7 @@ static unsigned int __init tsc_calibratestatic struct irqaction irq0 = { .handler = timer_interrupt, - .flags =IRQF_DISABLED |IRQF_IRQPOLL , + .flags =IRQF_DISABLED |IRQF_IRQPOLL |IRQF_NOBALANCING , .mask =CPU_MASK_NONE , .name ="timer" };
PATCH 24/25 x86_64: prep idle loop for dynticks
In reply to Thomas GleixnerFrom: Chris Wright <[email protected]>
Add tick_nohz_{stop,restart}_sched_tick to idle loop in prepartion for turning on dynticks. These are just noops until NO_HZ is enabled in next patch.
--- arch/x86_64/kernel/process.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86_64/kernel/process.c +4 -0
@@ -37,6 +37,7 @@#include <linux/notifier.h> #include <linux/kprobes.h> #include <linux/kdebug.h> +#include <linux/tick.h> #include <asm/uaccess.h> #include <asm/pgtable.h>
@@ -207,6 +208,8 @@ void cpu_idle (void)if (__get_cpu_var (cpu_idle_state))__get_cpu_var (cpu_idle_state) =0 ; +tick_nohz_stop_sched_tick (); +check_pgt_cache ();rmb (); idle = pm_idle;
@@ -228,6 +231,7 @@ void cpu_idle (void)__exit_idle (); } +tick_nohz_restart_sched_tick ();preempt_enable_no_resched ();schedule ();preempt_disable ();
PATCH 25/25 x86_64: enable high resolution timers and dynticks
In reply to Thomas GleixnerFrom: Chris Wright <[email protected]>
Everything is in place, enable the HIGHRES andf NO_HZ config options.
--- arch/x86_64/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
arch/x86_64/Kconfig +2 -0
@@ -150,6 +150,8 @@ source "init/Kconfig" menu "Processor type and features" +source "kernel/time/Kconfig" + choice prompt "Subarchitecture Type" default X86_PC
Quoted 3 lines · On Saturday 16 June 2007 11:36:00 Thomas Gleixner wrote:
The -hrt tree at http://www.tglx.de/projects/hrtimers/2.6.22-rc4/ contains also an hpet force patch series from Venki Pallipadi, but I leave this up to Venki to send it mainline wards.
What's the status on the nForce "hpet force fix" (Subject: "Enable hidden HPET on NVidia motherboards") that also exists? I think if one board can have its HPET forced, so can another.
Last I heard we were waiting on NVIDIA to confirm whether Mikko's logic was supported by specifications? Any update on this?
Signature · 5 lines
Cheers, Alistair. Final year Computer Science undergraduate. 1F2 55 South Clerk Street, Edinburgh, UK.
Quoted 11 lines · Alistair John Strachan
Quoted 3 lines · On Saturday 16 June 2007 11:36:00 Thomas Gleixner wrote:
The -hrt tree at http://www.tglx.de/projects/hrtimers/2.6.22-rc4/ contains also an hpet force patch series from Venki Pallipadi, but I leave this up to Venki to send it mainline wards.
What's the status on the nForce "hpet force fix" (Subject: "Enable hidden HPET on NVidia motherboards") that also exists? I think if one board can have its HPET forced, so can another.
Last I heard we were waiting on NVIDIA to confirm whether Mikko's logic was supported by specifications? Any update on this?
The full hpet force enable series is maintained by Venki and updates should go to him. I can add the patch to my -hrt queue for testing.
tglx
Hi all.
I'm currently running with the combined patch applied all the time, and it seems to be working fine here, including with hibernation.
Regards,
Nigel
Signature · 4 lines
Nigel, Michelle and Alisdair Cunningham 5 Mitchell Street Cobden 3266 Victoria, Australia
Quoted 7 lines · Thomas Gleixner
The following patch series contains:
- dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
- updates and improvements to high resolution timer / dynticks
- high resolution timer / dynticks support for
x86_64
Am running with the 22-rc4-mm2-hrt4 patch on my Latitude D820. Mostly seems to work, but for some reason the Intel 'powertop' util thinks it's 100% busy:
PowerTOP version 1.7 (C) 2007 Intel Corporation
Cn Avg residency (5s) P-states (frequencies)
C0 (cpu running) (100.0%)
C1 0.0ms ( 0.0%) 2.00 Ghz 0.0%
C2 0.0ms ( 0.0%) 1.67 Ghz 0.0%
C3 0.0ms ( 0.0%) 1333 Mhz 0.0%
1000 Mhz 100.0%In reality:
[/sys/devices/system/cpu/cpu0/cpuidle] for i in */*; do echo -n "$i: "; cat $i; done state0/latency: 1
state0/power: 1000
state0/time: 0
state0/usage: 3
state1/latency: 1
state1/power: 500
state1/time: 1756017623
state1/usage: 1837402
state2/latency: 57
state2/power: 100
state2/time: -159524787
state2/usage: 15007443
I think we have a 32/64 bit issue on state2/time which is probably borking things up....
Quoted 36 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Monday, June 18, 2007 1:07 PM
To: Thomas Gleixner
Cc: LKML; Andrew Morton; Ingo Molnar; Andi Kleen; Chris Wright; Arjan van de Ven; Pallipadi, Venkatesh
Subject: Re: [patch-mm 00/25] High resolution timer updates andx86_64support - V2Quoted 7 lines · Thomas Gleixner
The following patch series contains:
- dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
- updates and improvements to high resolution timer / dynticks
- high resolution timer / dynticks support for
x86_64Am running with the 22-rc4-mm2-hrt4 patch on my Latitude D820. Mostly seems
to work, but for some reason the Intel 'powertop' util thinks it's 100% busy:PowerTOP version 1.7 (C) 2007 Intel Corporation
Cn Avg residency (5s) P-states (frequencies)
C0 (cpu running) (100.0%)C1 0.0ms ( 0.0%) 2.00 Ghz 0.0% C2 0.0ms ( 0.0%) 1.67 Ghz 0.0% C3 0.0ms ( 0.0%) 1333 Mhz 0.0% 1000 Mhz 100.0%In reality:
Quoted 15 lines
[
/sys/devices/system/cpu/cpu0/cpuidle] for i in */*; do echo -n "$i: "; cat $i; done
state0/latency: 1
state0/power: 1000
state0/time: 0
state0/usage: 3
state1/latency: 1
state1/power: 500
state1/time: 1756017623
state1/usage: 1837402
state2/latency: 57
state2/power: 100
state2/time: -159524787
state2/usage: 15007443
The problem is powertop only understands /proc/acpi/processor/CPU*/power for
and not /sys..cpuidle for the moment.
I had a patch in recent cpuidle fixes series that makes /proc interface active
again with cpuidle which should correct this. Those patches are not in rc4-mm2-hrt4, but are there in latest rc4-hrt and rc5-hrt series.
Thanks,
Venki
Quoted 4 lines · Venkatesh
Quoted 3 lines
state2/time: -159524787
state2/usage: 15007443
Quoted 8 lines
The problem is powertop only understands
/proc/acpi/processor/CPU*/powerfor
and not /sys..cpuidle for the moment.I had a patch in recent cpuidle fixes series that makes /proc interface active
again with cpuidle which should correct this. Those patches are not in rc4-mm2-hrt4, but are there in latest rc4-hrt and rc5-hrt series.
OK, so I've got a 32/64 bug that isn't the cause of *this* issue because powertop isn't looking at the broken value.
A quick check shows that the keep_proc_acpi_power_around_001.patch from rc5-hrt will apply to rc4-mm2-hrt - I'll give that a try tonight and report back...
Quoted 24 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Monday, June 18, 2007 2:50 PM
To: Pallipadi, Venkatesh
Cc: Thomas Gleixner; LKML; Andrew Morton; Ingo Molnar; Andi Kleen; Chris Wright; Arjan van de Ven
Subject: Re: [patch-mm 00/25] High resolution timer updates andx86_64support - V2Quoted 5 lines · Venkatesh
Quoted 3 lines
state2/time: -159524787
state2/usage: 15007443The problem is powertop only understands
/proc/acpi/processor/CPU*/powerQuoted 4 lines
for
and not /sys..cpuidle for the moment.I had a patch in recent cpuidle fixes series that makes
/proc interface
Quoted 9 lines
Quoted 2 lines
active
again with cpuidle which should correct this. Those patchesare not in
Quoted 1 line
rc4-mm2-hrt4, but are there in latest rc4-hrt and rc5-hrt series.
OK, so I've got a 32/64 bug that isn't the cause of *this* issue because
powertop isn't looking at the broken value.
Yes. The output does indicate a bug in cpuidle /sysfs part. Will look at sysfs output of cpuidle and fix those issues soon.
Thanks,
Venki
Quoted 3 lines · On Mon, 18 Jun 2007 17:49:44 EDT, [email protected] said:
A quick check shows that the keep_proc_acpi_power_around_001.patch from rc5-hrt will apply to rc4-mm2-hrt - I'll give that a try tonight and report back...
Confirming - I backported that patch from rc5-hrt to rc4-mm2-hrt, and now powertop is reporting sane values again:
PowerTOP version 1.7 (C) 2007 Intel Corporation
Cn Avg residency (5s) P-states (frequencies)
C0 (cpu running) (15.8%)
C1 0.0ms ( 0.0%) 2.00 Ghz 0.0%
C2 0.6ms ( 7.9%) 1.67 Ghz 0.0%
C3 0.7ms (76.3%) 1333 Mhz 0.0%
1000 Mhz 100.0%Quoted 14 lines · On Mon, 2007-06-18 at 16:06 -0400, [email protected] wrote:
Quoted 7 lines · Thomas Gleixner
The following patch series contains:
- dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
- updates and improvements to high resolution timer / dynticks
- high resolution timer / dynticks support for
x86_64Am running with the 22-rc4-mm2-hrt4 patch on my Latitude D820. Mostly seems to work, but for some reason the Intel 'powertop' util thinks it's 100% busy:
PowerTOP version 1.7 (C) 2007 Intel Corporation
Quoted 8 lines
Cn Avg residency (5s) P-states (frequencies)
C0 (cpu running) (100.0%)C1 0.0ms ( 0.0%) 2.00 Ghz 0.0% C2 0.0ms ( 0.0%) 1.67 Ghz 0.0% C3 0.0ms ( 0.0%) 1333 Mhz 0.0% 1000 Mhz 100.0%In reality:
looks like something broke the /proc/acpi/processor/*/power file data....
can you check in that file to see if there is actual C-state time accounting going on?
(it is in mainline, so if it's not then it's an -mm or -hrt bug)
Signature · 2 lines
if you want to mail me at work (you don't), use arjan (at) linux.intel.com Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org