Skip to content

Commit 8b20d2d

Browse files
avpatelpalmer-dabbelt
authored andcommitted
RISC-V: Show IPI stats
This patch provides arch_show_interrupts() implementation to show IPI stats via /proc/interrupts. Now the contents of /proc/interrupts" will look like below: CPU0 CPU1 CPU2 CPU3 8: 17 7 6 14 SiFive PLIC 8 virtio0 10: 10 10 9 11 SiFive PLIC 10 ttyS0 IPI0: 170 673 251 79 Rescheduling interrupts IPI1: 1 12 27 1 Function call interrupts Signed-off-by: Anup Patel <anup@brainfault.org> [Atish - Fixed checkpatch errors] Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Palmer Dabbelt <palmer@sifive.com> Changes since v2: - Remove use of IPI_CALL_WAKEUP because it's being removed Changes since v1: - Add stub inline show_ipi_stats() function for !CONFIG_SMP - Make ipi_names[] dynamically sized at compile time - Minor beautification of ipi_names[] using tabs Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
1 parent 4b26d22 commit 8b20d2d

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

arch/riscv/include/asm/smp.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,13 @@
2525
extern unsigned long __cpuid_to_hartid_map[NR_CPUS];
2626
#define cpuid_to_hartid_map(cpu) __cpuid_to_hartid_map[cpu]
2727

28+
struct seq_file;
29+
2830
#ifdef CONFIG_SMP
2931

32+
/* print IPI stats */
33+
void show_ipi_stats(struct seq_file *p, int prec);
34+
3035
/* SMP initialization hook for setup_arch */
3136
void __init setup_smp(void);
3237

@@ -47,6 +52,10 @@ void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out);
4752

4853
#else
4954

55+
static inline void show_ipi_stats(struct seq_file *p, int prec)
56+
{
57+
}
58+
5059
static inline int riscv_hartid_to_cpuid(int hartid)
5160
{
5261
return 0;

arch/riscv/kernel/irq.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <linux/interrupt.h>
99
#include <linux/irqchip.h>
1010
#include <linux/irqdomain.h>
11+
#include <linux/seq_file.h>
12+
#include <asm/smp.h>
1113

1214
/*
1315
* Possible interrupt causes:
@@ -24,6 +26,12 @@
2426
*/
2527
#define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1))
2628

29+
int arch_show_interrupts(struct seq_file *p, int prec)
30+
{
31+
show_ipi_stats(p, prec);
32+
return 0;
33+
}
34+
2735
asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs)
2836
{
2937
struct pt_regs *old_regs = set_irq_regs(regs);

arch/riscv/kernel/smp.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,24 @@
2222
#include <linux/interrupt.h>
2323
#include <linux/smp.h>
2424
#include <linux/sched.h>
25+
#include <linux/seq_file.h>
2526

2627
#include <asm/sbi.h>
2728
#include <asm/tlbflush.h>
2829
#include <asm/cacheflush.h>
2930

30-
/* A collection of single bit ipi messages. */
31-
static struct {
32-
unsigned long bits ____cacheline_aligned;
33-
} ipi_data[NR_CPUS] __cacheline_aligned;
34-
3531
enum ipi_message_type {
3632
IPI_RESCHEDULE,
3733
IPI_CALL_FUNC,
3834
IPI_MAX
3935
};
4036

37+
/* A collection of single bit ipi messages. */
38+
static struct {
39+
unsigned long stats[IPI_MAX] ____cacheline_aligned;
40+
unsigned long bits ____cacheline_aligned;
41+
} ipi_data[NR_CPUS] __cacheline_aligned;
42+
4143
int riscv_hartid_to_cpuid(int hartid)
4244
{
4345
int i = -1;
@@ -67,6 +69,7 @@ int setup_profiling_timer(unsigned int multiplier)
6769
void riscv_software_interrupt(void)
6870
{
6971
unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
72+
unsigned long *stats = ipi_data[smp_processor_id()].stats;
7073

7174
/* Clear pending IPI */
7275
csr_clear(sip, SIE_SSIE);
@@ -81,11 +84,15 @@ void riscv_software_interrupt(void)
8184
if (ops == 0)
8285
return;
8386

84-
if (ops & (1 << IPI_RESCHEDULE))
87+
if (ops & (1 << IPI_RESCHEDULE)) {
88+
stats[IPI_RESCHEDULE]++;
8589
scheduler_ipi();
90+
}
8691

87-
if (ops & (1 << IPI_CALL_FUNC))
92+
if (ops & (1 << IPI_CALL_FUNC)) {
93+
stats[IPI_CALL_FUNC]++;
8894
generic_smp_call_function_interrupt();
95+
}
8996

9097
BUG_ON((ops >> IPI_MAX) != 0);
9198

@@ -111,6 +118,24 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
111118
sbi_send_ipi(cpumask_bits(&hartid_mask));
112119
}
113120

121+
static const char * const ipi_names[] = {
122+
[IPI_RESCHEDULE] = "Rescheduling interrupts",
123+
[IPI_CALL_FUNC] = "Function call interrupts",
124+
};
125+
126+
void show_ipi_stats(struct seq_file *p, int prec)
127+
{
128+
unsigned int cpu, i;
129+
130+
for (i = 0; i < IPI_MAX; i++) {
131+
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
132+
prec >= 4 ? " " : "");
133+
for_each_online_cpu(cpu)
134+
seq_printf(p, "%10lu ", ipi_data[cpu].stats[i]);
135+
seq_printf(p, " %s\n", ipi_names[i]);
136+
}
137+
}
138+
114139
void arch_send_call_function_ipi_mask(struct cpumask *mask)
115140
{
116141
send_ipi_message(mask, IPI_CALL_FUNC);

0 commit comments

Comments
 (0)