powerpc: Fix WARN_ON in decrementer_check_overflow
PATCH 1/1 powerpc: Fix WARN_ON in decrementer_check_overflow
We use __get_cpu_var() which triggers a false positive warning in smp_processor_id() thinking interrupts are enabled (at this point, they are soft-enabled but hard-disabled).
---
I was initially planning to fix that with a more in-depth rework of how we do lazy irq disabling on powerpc, but that patch is becoming too complex for this release so I'll apply this as a stop-gap and leave the full rework for -next
arch/powerpc/kernel/irq.c +5 -1
@@ -118,10 +118,14 @@ static inline notrace void set_soft_enabled(unsigned long enable) static inline notrace void decrementer_check_overflow(void) {u64 now =get_tb_or_rtc (); -u64 *next_tb = &__get_cpu_var (decrementers_next_tb); +u64 *next_tb; + +preempt_disable (); + next_tb = &__get_cpu_var (decrementers_next_tb);if (now >= *next_tb)set_dec (1 ); +preempt_enable (); } notrace void arch_local_irq_restore(unsigned long en)
Quoted 11 lines · Benjamin Herrenschmidt
We use
__get_cpu_var()which triggers a false positive warning insmp_processor_id()thinking interrupts are enabled (at this point, they are soft-enabled but hard-disabled).Signed-off-by Benjamin Herrenschmidt <[email protected]>---
I was initially planning to fix that with a more in-depth rework of how we do lazy irq disabling on powerpc, but that patch is becoming too complex for this release so I'll apply this as a stop-gap and leave the full rework for -next
Okay, thanks for the update, that's equivalent to the get_cpu_var plus put_cpu_var patch I had generally been running with successfully.
(I was not at all confident that it was a sufficient fix, and have to say "generally" above because one time I got something that looked like recursive calls overflowing the stack, and IIRC something "irq" did appear in each frame of the trace. But probably no connection, never seen again, and I don't recall even which -rc or -next it was.)
Hugh
Quoted 21 lines
arch/powerpc/kernel/irq.c +5
-1@@ -118,10 +118,14 @@ static inline notrace void set_soft_enabled(unsigned long enable) static inline notrace void decrementer_check_overflow(void) {u64 now =get_tb_or_rtc (); -u64 *next_tb = &__get_cpu_var (decrementers_next_tb); +u64 *next_tb; + +preempt_disable (); + next_tb = &__get_cpu_var (decrementers_next_tb);if (now >= *next_tb)set_dec (1 ); +preempt_enable (); } notrace void arch_local_irq_restore(unsigned long en)
Quoted 9 lines · Hugh Dickins
Okay, thanks for the update, that's equivalent to the
get_cpu_varplusput_cpu_varpatch I had generally been running with successfully.(I was not at all confident that it was a sufficient fix, and have to say "generally" above because one time I got something that looked like recursive calls overflowing the stack, and IIRC something "irq" did appear in each frame of the trace. But probably no connection, never seen again, and I don't recall even which -rc or -next it was.)
If you ever see that again, please shoot me the log !
Cheers,
Ben.