Skip to content

Commit 6ea0f26

Browse files
Christoph Hellwigpalmer-dabbelt
authored andcommitted
RISC-V: implement low-level interrupt handling
Add support for a routine that dispatches exceptions with the interrupt flags set to either the IPI or irqdomain code (and the clock source in the future). Loosely based on the irq-riscv-int.c irqchip driver from the RISC-V tree. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
1 parent bec2e6a commit 6ea0f26

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

arch/riscv/kernel/entry.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ ENTRY(handle_exception)
168168

169169
/* Handle interrupts */
170170
move a0, sp /* pt_regs */
171-
REG_L a1, handle_arch_irq
172-
jr a1
171+
move a1, s4 /* scause */
172+
tail do_IRQ
173173
1:
174174
/* Exceptions run with interrupts enabled */
175175
csrs sstatus, SR_SIE

arch/riscv/kernel/irq.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,55 @@
1+
// SPDX-License-Identifier: GPL-2.0
12
/*
23
* Copyright (C) 2012 Regents of the University of California
34
* Copyright (C) 2017 SiFive
4-
*
5-
* This program is free software; you can redistribute it and/or
6-
* modify it under the terms of the GNU General Public License
7-
* as published by the Free Software Foundation, version 2.
8-
*
9-
* This program is distributed in the hope that it will be useful,
10-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-
* GNU General Public License for more details.
5+
* Copyright (C) 2018 Christoph Hellwig
136
*/
147

158
#include <linux/interrupt.h>
169
#include <linux/irqchip.h>
1710
#include <linux/irqdomain.h>
1811

12+
/*
13+
* Possible interrupt causes:
14+
*/
15+
#define INTERRUPT_CAUSE_SOFTWARE 1
16+
#define INTERRUPT_CAUSE_TIMER 5
17+
#define INTERRUPT_CAUSE_EXTERNAL 9
18+
19+
/*
20+
* The high order bit of the trap cause register is always set for
21+
* interrupts, which allows us to differentiate them from exceptions
22+
* quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we
23+
* need to mask it off.
24+
*/
25+
#define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1))
26+
27+
asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long cause)
28+
{
29+
struct pt_regs *old_regs = set_irq_regs(regs);
30+
31+
irq_enter();
32+
switch (cause & ~INTERRUPT_CAUSE_FLAG) {
33+
#ifdef CONFIG_SMP
34+
case INTERRUPT_CAUSE_SOFTWARE:
35+
/*
36+
* We only use software interrupts to pass IPIs, so if a non-SMP
37+
* system gets one, then we don't know what to do.
38+
*/
39+
riscv_software_interrupt();
40+
break;
41+
#endif
42+
case INTERRUPT_CAUSE_EXTERNAL:
43+
handle_arch_irq(regs);
44+
break;
45+
default:
46+
panic("unexpected interrupt cause");
47+
}
48+
irq_exit();
49+
50+
set_irq_regs(old_regs);
51+
}
52+
1953
void __init init_IRQ(void)
2054
{
2155
irqchip_init();

0 commit comments

Comments
 (0)