powerpc: Provide a way to defer perf counter work until interrupts are enabled

Because 64-bit powerpc uses lazy (soft) interrupt disabling, it is
possible for a performance monitor exception to come in when the
kernel thinks interrupts are disabled (i.e. when they are
soft-disabled but hard-enabled).  In such a situation the performance
monitor exception handler might have some processing to do (such as
process wakeups) which can't be done in what is effectively an NMI
handler.

This provides a way to defer that work until interrupts get enabled,
either in raw_local_irq_restore() or by returning from an interrupt
handler to code that had interrupts enabled.  We have a per-processor
flag that indicates that there is work pending to do when interrupts
subsequently get re-enabled.  This flag is checked in the interrupt
return path and in raw_local_irq_restore(), and if it is set,
perf_counter_do_pending() is called to do the pending work.

Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Paul Mackerras
2009-01-09 16:52:19 +11:00
parent d662ed2673
commit 93a6d3ce69
5 changed files with 52 additions and 0 deletions

View File

@@ -131,5 +131,36 @@ static inline int irqs_disabled_flags(unsigned long flags)
*/
struct hw_interrupt_type;
#ifdef CONFIG_PERF_COUNTERS
static inline unsigned long get_perf_counter_pending(void)
{
unsigned long x;
asm volatile("lbz %0,%1(13)"
: "=r" (x)
: "i" (offsetof(struct paca_struct, perf_counter_pending)));
return x;
}
static inline void set_perf_counter_pending(int x)
{
asm volatile("stb %0,%1(13)" : :
"r" (x),
"i" (offsetof(struct paca_struct, perf_counter_pending)));
}
extern void perf_counter_do_pending(void);
#else
static inline unsigned long get_perf_counter_pending(void)
{
return 0;
}
static inline void set_perf_counter_pending(int x) {}
static inline void perf_counter_do_pending(void) {}
#endif /* CONFIG_PERF_COUNTERS */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HW_IRQ_H */