genirq: Provide a snapshot mechanism for interrupt statistics
ANBZ: #9025
commit 99cf63c566
tip.
The soft lockup detector lacks a mechanism to identify interrupt storms as
root cause of a lockup. To enable this the detector needs a mechanism to
snapshot the interrupt count statistics on a CPU when the detector observes
a potential lockup scenario and compare that against the interrupt count
when it warns about the lockup later on. The number of interrupts in that
period give a hint whether the lockup might have been caused by an interrupt
storm.
Instead of having extra storage in the lockup detector and accessing the
internals of the interrupt descriptor directly, add a snapshot member to
the per CPU irq_desc::kstat_irq structure and provide interfaces to take a
snapshot of all interrupts on the current CPU and to retrieve the delta of
a specific interrupt later on.
Originally-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Bitao Hu <yaoma@linux.alibaba.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240411074134.30922-3-yaoma@linux.alibaba.com
[OP: modify to be compatible with ANCK-5.10]
Signed-off-by: Bitao Hu <yaoma@linux.alibaba.com>
Reviewed-by: Liu Song <liusong@linux.alibaba.com>
Reviewed-by: Xunlei Pang <xlpang@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/3201
This commit is contained in:
parent
d391de2431
commit
a01e3ffdbd
|
@ -21,9 +21,13 @@ struct pt_regs;
|
|||
/**
|
||||
* struct irqstat - interrupt statistics
|
||||
* @cnt: real-time interrupt count
|
||||
* @ref: snapshot of interrupt count
|
||||
*/
|
||||
struct irqstat {
|
||||
unsigned int cnt;
|
||||
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
|
||||
unsigned int ref;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,6 +72,14 @@ static inline unsigned int kstat_softirqs_cpu(unsigned int irq, int cpu)
|
|||
return kstat_cpu(cpu).softirqs[irq];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
|
||||
extern void kstat_snapshot_irqs(void);
|
||||
extern unsigned int kstat_get_irq_since_snapshot(unsigned int irq);
|
||||
#else
|
||||
static inline void kstat_snapshot_irqs(void) { }
|
||||
static inline unsigned int kstat_get_irq_since_snapshot(unsigned int irq) { return 0; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Number of interrupts per specific IRQ source, since bootup
|
||||
*/
|
||||
|
|
|
@ -113,6 +113,10 @@ config GENERIC_IRQ_MATRIX_ALLOCATOR
|
|||
config GENERIC_IRQ_RESERVATION_MODE
|
||||
bool
|
||||
|
||||
# Snapshot for interrupt statistics
|
||||
config GENERIC_IRQ_STAT_SNAPSHOT
|
||||
bool
|
||||
|
||||
# Support forced irq threading
|
||||
config IRQ_FORCED_THREADING
|
||||
bool
|
||||
|
|
|
@ -1002,6 +1002,31 @@ unsigned int kstat_irqs(unsigned int irq)
|
|||
return sum;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
|
||||
|
||||
void kstat_snapshot_irqs(void)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
unsigned int irq;
|
||||
|
||||
for_each_irq_desc(irq, desc) {
|
||||
if (!desc->kstat_irqs)
|
||||
continue;
|
||||
this_cpu_write(desc->kstat_irqs->ref, this_cpu_read(desc->kstat_irqs->cnt));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int kstat_get_irq_since_snapshot(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
if (!desc || !desc->kstat_irqs)
|
||||
return 0;
|
||||
return this_cpu_read(desc->kstat_irqs->cnt) - this_cpu_read(desc->kstat_irqs->ref);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* kstat_irqs_usr - Get the statistics for an interrupt
|
||||
* @irq: The interrupt number
|
||||
|
|
Loading…
Reference in New Issue