Skip to content

Commit 99cf63c

Browse files
hubitao-yaomaKAGA-KOKO
authored andcommitted
genirq: Provide a snapshot mechanism for interrupt statistics
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
1 parent 86d2a2f commit 99cf63c

4 files changed

Lines changed: 41 additions & 0 deletions

File tree

include/linux/irqdesc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ struct pt_regs;
2020
/**
2121
* struct irqstat - interrupt statistics
2222
* @cnt: real-time interrupt count
23+
* @ref: snapshot of interrupt count
2324
*/
2425
struct irqstat {
2526
unsigned int cnt;
27+
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
28+
unsigned int ref;
29+
#endif
2630
};
2731

2832
/**

include/linux/kernel_stat.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ static inline unsigned int kstat_cpu_softirqs_sum(int cpu)
7979
return sum;
8080
}
8181

82+
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
83+
extern void kstat_snapshot_irqs(void);
84+
extern unsigned int kstat_get_irq_since_snapshot(unsigned int irq);
85+
#else
86+
static inline void kstat_snapshot_irqs(void) { }
87+
static inline unsigned int kstat_get_irq_since_snapshot(unsigned int irq) { return 0; }
88+
#endif
89+
8290
/*
8391
* Number of interrupts per specific IRQ source, since bootup
8492
*/

kernel/irq/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ config GENERIC_IRQ_MATRIX_ALLOCATOR
108108
config GENERIC_IRQ_RESERVATION_MODE
109109
bool
110110

111+
# Snapshot for interrupt statistics
112+
config GENERIC_IRQ_STAT_SNAPSHOT
113+
bool
114+
111115
# Support forced irq threading
112116
config IRQ_FORCED_THREADING
113117
bool

kernel/irq/irqdesc.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,31 @@ static unsigned int kstat_irqs(unsigned int irq)
994994
return sum;
995995
}
996996

997+
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
998+
999+
void kstat_snapshot_irqs(void)
1000+
{
1001+
struct irq_desc *desc;
1002+
unsigned int irq;
1003+
1004+
for_each_irq_desc(irq, desc) {
1005+
if (!desc->kstat_irqs)
1006+
continue;
1007+
this_cpu_write(desc->kstat_irqs->ref, this_cpu_read(desc->kstat_irqs->cnt));
1008+
}
1009+
}
1010+
1011+
unsigned int kstat_get_irq_since_snapshot(unsigned int irq)
1012+
{
1013+
struct irq_desc *desc = irq_to_desc(irq);
1014+
1015+
if (!desc || !desc->kstat_irqs)
1016+
return 0;
1017+
return this_cpu_read(desc->kstat_irqs->cnt) - this_cpu_read(desc->kstat_irqs->ref);
1018+
}
1019+
1020+
#endif
1021+
9971022
/**
9981023
* kstat_irqs_usr - Get the statistics for an interrupt from thread context
9991024
* @irq: The interrupt number

0 commit comments

Comments
 (0)