8b20d2db0a
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>
68 lines
1.5 KiB
C
68 lines
1.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2012 Regents of the University of California
|
|
* Copyright (C) 2017 SiFive
|
|
* Copyright (C) 2018 Christoph Hellwig
|
|
*/
|
|
|
|
#include <linux/interrupt.h>
|
|
#include <linux/irqchip.h>
|
|
#include <linux/irqdomain.h>
|
|
#include <linux/seq_file.h>
|
|
#include <asm/smp.h>
|
|
|
|
/*
|
|
* Possible interrupt causes:
|
|
*/
|
|
#define INTERRUPT_CAUSE_SOFTWARE 1
|
|
#define INTERRUPT_CAUSE_TIMER 5
|
|
#define INTERRUPT_CAUSE_EXTERNAL 9
|
|
|
|
/*
|
|
* The high order bit of the trap cause register is always set for
|
|
* interrupts, which allows us to differentiate them from exceptions
|
|
* quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we
|
|
* need to mask it off.
|
|
*/
|
|
#define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1))
|
|
|
|
int arch_show_interrupts(struct seq_file *p, int prec)
|
|
{
|
|
show_ipi_stats(p, prec);
|
|
return 0;
|
|
}
|
|
|
|
asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs)
|
|
{
|
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
|
|
|
irq_enter();
|
|
switch (regs->scause & ~INTERRUPT_CAUSE_FLAG) {
|
|
case INTERRUPT_CAUSE_TIMER:
|
|
riscv_timer_interrupt();
|
|
break;
|
|
#ifdef CONFIG_SMP
|
|
case INTERRUPT_CAUSE_SOFTWARE:
|
|
/*
|
|
* We only use software interrupts to pass IPIs, so if a non-SMP
|
|
* system gets one, then we don't know what to do.
|
|
*/
|
|
riscv_software_interrupt();
|
|
break;
|
|
#endif
|
|
case INTERRUPT_CAUSE_EXTERNAL:
|
|
handle_arch_irq(regs);
|
|
break;
|
|
default:
|
|
panic("unexpected interrupt cause");
|
|
}
|
|
irq_exit();
|
|
|
|
set_irq_regs(old_regs);
|
|
}
|
|
|
|
void __init init_IRQ(void)
|
|
{
|
|
irqchip_init();
|
|
}
|