* [PATCH] x86-64: Fix the nterrupt race is in idle callback
@ 2006-11-29 17:15 Venkatesh Pallipadi
2006-11-29 17:31 ` [PATCH] x86-64: Fix the nterrupt race is in idle callback (2nd try) Venkatesh Pallipadi
0 siblings, 1 reply; 3+ messages in thread
From: Venkatesh Pallipadi @ 2006-11-29 17:15 UTC (permalink / raw)
To: Andi Kleen; +Cc: Suresh B Siddha, linux-kernel
Idle callbacks has some races when enter_idle() sets isidle and subsequent
interrupts that can happen on that CPU, before CPU goes to idle. Due to this,
an IDLE_END can get called before IDLE_START. To avoid these races, disable
interrupts before enter_idle and make sure that all idle routines do not
enable interrupts before entering idle.
Note that poll_idle() still has a this race as it has to enable interrupts
before going to idle. But, all other idle routines have the race fixed.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Index: linux-2.6.19-rc-mm/arch/x86_64/kernel/process.c
===================================================================
--- linux-2.6.19-rc-mm.orig/arch/x86_64/kernel/process.c
+++ linux-2.6.19-rc-mm/arch/x86_64/kernel/process.c
@@ -127,6 +127,7 @@ static void default_idle(void)
*/
static void poll_idle (void)
{
+ local_irq_enable();
cpu_relax();
}
@@ -206,6 +207,12 @@ void cpu_idle (void)
idle = default_idle;
if (cpu_is_offline(smp_processor_id()))
play_dead();
+ /*
+ * Idle routines should keep interrupts disabled
+ * from here on, until they go to idle.
+ * Otherwise, idle callbacks can misfire.
+ */
+ local_irq_disable();
enter_idle();
idle();
/* In many cases the interrupt that ended idle
@@ -243,8 +250,12 @@ void mwait_idle_with_hints(unsigned long
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
- local_irq_enable();
- mwait_idle_with_hints(0,0);
+ if (!need_resched()) {
+ __monitor((void *)¤t_thread_info()->flags, 0, 0);
+ smp_mb();
+ if (!need_resched())
+ __sti_mwait(0, 0);
+ }
}
void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
Index: linux-2.6.19-rc-mm/include/asm-x86_64/processor.h
===================================================================
--- linux-2.6.19-rc-mm.orig/include/asm-x86_64/processor.h
+++ linux-2.6.19-rc-mm/include/asm-x86_64/processor.h
@@ -475,6 +475,14 @@ static inline void __mwait(unsigned long
: :"a" (eax), "c" (ecx));
}
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+ /* "mwait %eax,%ecx;" */
+ asm volatile(
+ "sti; .byte 0x0f,0x01,0xc9;"
+ : :"a" (eax), "c" (ecx));
+}
+
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
#define stack_current() \
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] x86-64: Fix the nterrupt race is in idle callback (2nd try)
2006-11-29 17:15 [PATCH] x86-64: Fix the nterrupt race is in idle callback Venkatesh Pallipadi
@ 2006-11-29 17:31 ` Venkatesh Pallipadi
2006-11-29 18:56 ` [PATCH] x86-64: Fix the nterrupt race is in idle callback (3rd try) Venkatesh Pallipadi
0 siblings, 1 reply; 3+ messages in thread
From: Venkatesh Pallipadi @ 2006-11-29 17:31 UTC (permalink / raw)
To: Andi Kleen; +Cc: Suresh B Siddha, linux-kernel
Here is the second try. Thanks to Suresh Siddha who pointed out a issue with
enabling interrupts in the first patch.
Idle callbacks has some races when enter_idle() sets isidle and subsequent
interrupts that can happen on that CPU, before CPU goes to idle. Due to this,
an IDLE_END can get called before IDLE_START. To avoid these races, disable
interrupts before enter_idle and make sure that all idle routines do not
enable interrupts before entering idle.
Note that poll_idle() still has a this race as it has to enable interrupts
before going to idle. But, all other idle routines have the race fixed.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Index: linux-2.6.19-rc-mm/arch/x86_64/kernel/process.c
===================================================================
--- linux-2.6.19-rc-mm.orig/arch/x86_64/kernel/process.c
+++ linux-2.6.19-rc-mm/arch/x86_64/kernel/process.c
@@ -127,6 +127,7 @@ static void default_idle(void)
*/
static void poll_idle (void)
{
+ local_irq_enable();
cpu_relax();
}
@@ -206,6 +207,12 @@ void cpu_idle (void)
idle = default_idle;
if (cpu_is_offline(smp_processor_id()))
play_dead();
+ /*
+ * Idle routines should keep interrupts disabled
+ * from here on, until they go to idle.
+ * Otherwise, idle callbacks can misfire.
+ */
+ local_irq_disable();
enter_idle();
idle();
/* In many cases the interrupt that ended idle
@@ -237,14 +244,22 @@ void mwait_idle_with_hints(unsigned long
smp_mb();
if (!need_resched())
__mwait(eax, ecx);
+ else
+ local_irq_enable();
+ } else {
+ local_irq_enable();
}
}
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
- local_irq_enable();
- mwait_idle_with_hints(0,0);
+ if (!need_resched()) {
+ __monitor((void *)¤t_thread_info()->flags, 0, 0);
+ smp_mb();
+ if (!need_resched())
+ __sti_mwait(0, 0);
+ }
}
void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
Index: linux-2.6.19-rc-mm/include/asm-x86_64/processor.h
===================================================================
--- linux-2.6.19-rc-mm.orig/include/asm-x86_64/processor.h
+++ linux-2.6.19-rc-mm/include/asm-x86_64/processor.h
@@ -475,6 +475,14 @@ static inline void __mwait(unsigned long
: :"a" (eax), "c" (ecx));
}
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+ /* "mwait %eax,%ecx;" */
+ asm volatile(
+ "sti; .byte 0x0f,0x01,0xc9;"
+ : :"a" (eax), "c" (ecx));
+}
+
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
#define stack_current() \
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] x86-64: Fix the nterrupt race is in idle callback (3rd try)
2006-11-29 17:31 ` [PATCH] x86-64: Fix the nterrupt race is in idle callback (2nd try) Venkatesh Pallipadi
@ 2006-11-29 18:56 ` Venkatesh Pallipadi
0 siblings, 0 replies; 3+ messages in thread
From: Venkatesh Pallipadi @ 2006-11-29 18:56 UTC (permalink / raw)
To: Andi Kleen; +Cc: Suresh B Siddha, linux-kernel
Idle callbacks has some races when enter_idle() sets isidle and subsequent
interrupts that can happen on that CPU, before CPU goes to idle. Due to this,
an IDLE_END can get called before IDLE_START. To avoid these races, disable
interrupts before enter_idle and make sure that all idle routines do not
enable interrupts before entering idle.
Note that poll_idle() still has a this race as it has to enable interrupts
before going to idle. But, all other idle routines have the race fixed.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
---
Here is the second try. Thanks to Suresh Siddha who pointed out a issue with
enabling interrupts in the first patch.
Well 2nd try did try to fix. But, did not really fix the issue in original
patch. Guess, today is not my day to send out patches.
Here is the 3rd try. Again thanks to Suresh for being the eagle eye...
Index: linux-2.6.19-rc-mm/arch/x86_64/kernel/process.c
===================================================================
--- linux-2.6.19-rc-mm.orig/arch/x86_64/kernel/process.c
+++ linux-2.6.19-rc-mm/arch/x86_64/kernel/process.c
@@ -127,6 +127,7 @@ static void default_idle(void)
*/
static void poll_idle (void)
{
+ local_irq_enable();
cpu_relax();
}
@@ -206,6 +207,12 @@ void cpu_idle (void)
idle = default_idle;
if (cpu_is_offline(smp_processor_id()))
play_dead();
+ /*
+ * Idle routines should keep interrupts disabled
+ * from here on, until they go to idle.
+ * Otherwise, idle callbacks can misfire.
+ */
+ local_irq_disable();
enter_idle();
idle();
/* In many cases the interrupt that ended idle
@@ -243,8 +250,16 @@ void mwait_idle_with_hints(unsigned long
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
- local_irq_enable();
- mwait_idle_with_hints(0,0);
+ if (!need_resched()) {
+ __monitor((void *)¤t_thread_info()->flags, 0, 0);
+ smp_mb();
+ if (!need_resched())
+ __sti_mwait(0, 0);
+ else
+ local_irq_enable();
+ } else {
+ local_irq_enable();
+ }
}
void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
Index: linux-2.6.19-rc-mm/include/asm-x86_64/processor.h
===================================================================
--- linux-2.6.19-rc-mm.orig/include/asm-x86_64/processor.h
+++ linux-2.6.19-rc-mm/include/asm-x86_64/processor.h
@@ -475,6 +475,14 @@ static inline void __mwait(unsigned long
: :"a" (eax), "c" (ecx));
}
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+ /* "mwait %eax,%ecx;" */
+ asm volatile(
+ "sti; .byte 0x0f,0x01,0xc9;"
+ : :"a" (eax), "c" (ecx));
+}
+
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
#define stack_current() \
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-11-29 19:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-29 17:15 [PATCH] x86-64: Fix the nterrupt race is in idle callback Venkatesh Pallipadi
2006-11-29 17:31 ` [PATCH] x86-64: Fix the nterrupt race is in idle callback (2nd try) Venkatesh Pallipadi
2006-11-29 18:56 ` [PATCH] x86-64: Fix the nterrupt race is in idle callback (3rd try) Venkatesh Pallipadi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox