Skip to content

Commit 1009aa1

Browse files
committed
Merge tag 'riscv-for-linus-4.19-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux
Pull RISC-V updates from Palmer Dabbelt: "This contains some major improvements to the RISC-V port, including the necessary interrupt controller and timer support to actually make it to userspace. Support for three devices has been added: - the ISA-mandated timers on RISC-V systems. - the ISA-mandated first-level interrupt controller on RISC-V systems, which is handled as part of our core arch code because it's very small and tightly tied to the ISA. - SiFive's platform-level interrupt controller, which talks to the actual devices. In addition to these new devices, there are a handful of cleanups all over the RISC-V tree: - build fixes for various configurations: * A fix to the vDSO build's makefile so it respects CFLAGS. * The addition of __lshrti3, a libgcc derived function necessary for some 32-bit configurations. * !SMP && PERF_EVENTS - Cleanups to the arch code to remove the remnants of old versions of the drivers that were just properly submitted. * Some dead code from the timer driver, most of which wasn't ever even compiled. * Cleanups of some interrupt #defines, which are now local to the interrupt handling code. - Fixes to ptrace(), which while not being sufficient to fully make GDB work are at least sufficient to get simple GDB tasks to work. - Early printk support via RISC-V's architecturally mandated SBI console device. - A fix to our early debug trap handler to ensure it's always aligned. These patches have all been through a fairly extensive review process, but as this enables a whole pile of functionality (ie, userspace) I'm confident we'll need to submit a few more patches. The only concrete issues I know about are the sys_riscv_flush_icache patches, but as I managed to screw those up on Friday I figured it'd be best to let them bake another week. This tag boots a Fedora root filesystem on QEMU's master branch for me, and before this morning's rebase (from 4.18-rc8 to 4.18) it booted on the HiFive Unleashed. Thanks to Christoph Hellwig and the other guys at WD for getting the new drivers in shape!" * tag 'riscv-for-linus-4.19-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux: dt-bindings: interrupt-controller: SiFive Plaform Level Interrupt Controller dt-bindings: interrupt-controller: RISC-V local interrupt controller RISC-V: Fix !CONFIG_SMP compilation error irqchip: add a SiFive PLIC driver RISC-V: Add the directive for alignment of stvec's value clocksource: new RISC-V SBI timer driver RISC-V: implement low-level interrupt handling RISC-V: add a definition for the SIE SEIE bit RISC-V: remove INTERRUPT_CAUSE_* defines from asm/irq.h RISC-V: simplify software interrupt / IPI code RISC-V: remove timer leftovers RISC-V: Add early printk support via the SBI console RISC-V: Don't increment sepc after breakpoint. RISC-V: implement __lshrti3. RISC-V: Use KBUILD_CFLAGS instead of KCFLAGS when building the vDSO
2 parents 1d0926e + 627672c commit 1009aa1

File tree

27 files changed

+625
-59
lines changed

27 files changed

+625
-59
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
RISC-V Hart-Level Interrupt Controller (HLIC)
2+
---------------------------------------------
3+
4+
RISC-V cores include Control Status Registers (CSRs) which are local to each
5+
CPU core (HART in RISC-V terminology) and can be read or written by software.
6+
Some of these CSRs are used to control local interrupts connected to the core.
7+
Every interrupt is ultimately routed through a hart's HLIC before it
8+
interrupts that hart.
9+
10+
The RISC-V supervisor ISA manual specifies three interrupt sources that are
11+
attached to every HLIC: software interrupts, the timer interrupt, and external
12+
interrupts. Software interrupts are used to send IPIs between cores. The
13+
timer interrupt comes from an architecturally mandated real-time timer that is
14+
controller via Supervisor Binary Interface (SBI) calls and CSR reads. External
15+
interrupts connect all other device interrupts to the HLIC, which are routed
16+
via the platform-level interrupt controller (PLIC).
17+
18+
All RISC-V systems that conform to the supervisor ISA specification are
19+
required to have a HLIC with these three interrupt sources present. Since the
20+
interrupt map is defined by the ISA it's not listed in the HLIC's device tree
21+
entry, though external interrupt controllers (like the PLIC, for example) will
22+
need to define how their interrupts map to the relevant HLICs. This means
23+
a PLIC interrupt property will typically list the HLICs for all present HARTs
24+
in the system.
25+
26+
Required properties:
27+
- compatible : "riscv,cpu-intc"
28+
- #interrupt-cells : should be <1>
29+
- interrupt-controller : Identifies the node as an interrupt controller
30+
31+
Furthermore, this interrupt-controller MUST be embedded inside the cpu
32+
definition of the hart whose CSRs control these local interrupts.
33+
34+
An example device tree entry for a HLIC is show below.
35+
36+
cpu1: cpu@1 {
37+
compatible = "riscv";
38+
...
39+
cpu1-intc: interrupt-controller {
40+
#interrupt-cells = <1>;
41+
compatible = "riscv,cpu-intc", "sifive,fu540-c000-cpu-intc";
42+
interrupt-controller;
43+
};
44+
};
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
SiFive Platform-Level Interrupt Controller (PLIC)
2+
-------------------------------------------------
3+
4+
SiFive SOCs include an implementation of the Platform-Level Interrupt Controller
5+
(PLIC) high-level specification in the RISC-V Privileged Architecture
6+
specification. The PLIC connects all external interrupts in the system to all
7+
hart contexts in the system, via the external interrupt source in each hart.
8+
9+
A hart context is a privilege mode in a hardware execution thread. For example,
10+
in an 4 core system with 2-way SMT, you have 8 harts and probably at least two
11+
privilege modes per hart; machine mode and supervisor mode.
12+
13+
Each interrupt can be enabled on per-context basis. Any context can claim
14+
a pending enabled interrupt and then release it once it has been handled.
15+
16+
Each interrupt has a configurable priority. Higher priority interrupts are
17+
serviced first. Each context can specify a priority threshold. Interrupts
18+
with priority below this threshold will not cause the PLIC to raise its
19+
interrupt line leading to the context.
20+
21+
While the PLIC supports both edge-triggered and level-triggered interrupts,
22+
interrupt handlers are oblivious to this distinction and therefore it is not
23+
specified in the PLIC device-tree binding.
24+
25+
While the RISC-V ISA doesn't specify a memory layout for the PLIC, the
26+
"sifive,plic-1.0.0" device is a concrete implementation of the PLIC that
27+
contains a specific memory layout, which is documented in chapter 8 of the
28+
SiFive U5 Coreplex Series Manual <https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf>.
29+
30+
Required properties:
31+
- compatible : "sifive,plic-1.0.0" and a string identifying the actual
32+
detailed implementation in case that specific bugs need to be worked around.
33+
- #address-cells : should be <0> or more.
34+
- #interrupt-cells : should be <1> or more.
35+
- interrupt-controller : Identifies the node as an interrupt controller.
36+
- reg : Should contain 1 register range (address and length).
37+
- interrupts-extended : Specifies which contexts are connected to the PLIC,
38+
with "-1" specifying that a context is not present. Each node pointed
39+
to should be a riscv,cpu-intc node, which has a riscv node as parent.
40+
- riscv,ndev: Specifies how many external interrupts are supported by
41+
this controller.
42+
43+
Example:
44+
45+
plic: interrupt-controller@c000000 {
46+
#address-cells = <0>;
47+
#interrupt-cells = <1>;
48+
compatible = "sifive,plic-1.0.0", "sifive,fu540-c000-plic";
49+
interrupt-controller;
50+
interrupts-extended = <
51+
&cpu0-intc 11
52+
&cpu1-intc 11 &cpu1-intc 9
53+
&cpu2-intc 11 &cpu2-intc 9
54+
&cpu3-intc 11 &cpu3-intc 9
55+
&cpu4-intc 11 &cpu4-intc 9>;
56+
reg = <0xc000000 0x4000000>;
57+
riscv,ndev = <10>;
58+
};

arch/riscv/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
2525

2626
KBUILD_CFLAGS += -mabi=lp64
2727
KBUILD_AFLAGS += -mabi=lp64
28+
29+
KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128)
30+
2831
KBUILD_MARCH = rv64im
2932
LDFLAGS += -melf64lriscv
3033
else

arch/riscv/configs/defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,4 @@ CONFIG_ROOT_NFS=y
7676
CONFIG_CRYPTO_USER_API_HASH=y
7777
CONFIG_MODULES=y
7878
CONFIG_MODULE_UNLOAD=y
79+
CONFIG_SIFIVE_PLIC=y

arch/riscv/include/asm/csr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
/* Interrupt Enable and Interrupt Pending flags */
5555
#define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */
5656
#define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */
57+
#define SIE_SEIE _AC(0x00000200, UL) /* External Interrupt Enable */
5758

5859
#define EXC_INST_MISALIGNED 0
5960
#define EXC_INST_ACCESS 1

arch/riscv/include/asm/irq.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717

1818
#define NR_IRQS 0
1919

20-
#define INTERRUPT_CAUSE_SOFTWARE 1
21-
#define INTERRUPT_CAUSE_TIMER 5
22-
#define INTERRUPT_CAUSE_EXTERNAL 9
23-
2420
void riscv_timer_interrupt(void);
21+
void riscv_software_interrupt(void);
2522

2623
#include <asm-generic/irq.h>
2724

arch/riscv/include/asm/perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <linux/perf_event.h>
1212
#include <linux/ptrace.h>
13+
#include <linux/interrupt.h>
1314

1415
#define RISCV_BASE_COUNTERS 2
1516

arch/riscv/include/asm/smp.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424

2525
#ifdef CONFIG_SMP
2626

27-
/* SMP initialization hook for setup_arch */
28-
void __init init_clockevent(void);
29-
3027
/* SMP initialization hook for setup_arch */
3128
void __init setup_smp(void);
3229

@@ -44,9 +41,6 @@ void arch_send_call_function_single_ipi(int cpu);
4441
*/
4542
#define raw_smp_processor_id() (*((int*)((char*)get_current() + TASK_TI_CPU)))
4643

47-
/* Interprocessor interrupt handler */
48-
irqreturn_t handle_ipi(void);
49-
5044
#endif /* CONFIG_SMP */
5145

5246
#endif /* _ASM_RISCV_SMP_H */

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/head.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ relocate:
9494
or a0, a0, a1
9595
sfence.vma
9696
csrw sptbr, a0
97+
.align 2
9798
1:
9899
/* Set trap vector to spin forever to help debug */
99100
la a0, .Lsecondary_park
@@ -143,6 +144,7 @@ relocate:
143144
tail smp_callin
144145
#endif
145146

147+
.align 2
146148
.Lsecondary_park:
147149
/* We lack SMP support or have too many harts, so park this hart */
148150
wfi

arch/riscv/kernel/irq.c

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,58 @@
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+
case INTERRUPT_CAUSE_TIMER:
34+
riscv_timer_interrupt();
35+
break;
36+
#ifdef CONFIG_SMP
37+
case INTERRUPT_CAUSE_SOFTWARE:
38+
/*
39+
* We only use software interrupts to pass IPIs, so if a non-SMP
40+
* system gets one, then we don't know what to do.
41+
*/
42+
riscv_software_interrupt();
43+
break;
44+
#endif
45+
case INTERRUPT_CAUSE_EXTERNAL:
46+
handle_arch_irq(regs);
47+
break;
48+
default:
49+
panic("unexpected interrupt cause");
50+
}
51+
irq_exit();
52+
53+
set_irq_regs(old_regs);
54+
}
55+
1956
void __init init_IRQ(void)
2057
{
2158
irqchip_init();

arch/riscv/kernel/perf_event.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <linux/mutex.h>
2828
#include <linux/bitmap.h>
2929
#include <linux/irq.h>
30-
#include <linux/interrupt.h>
3130
#include <linux/perf_event.h>
3231
#include <linux/atomic.h>
3332
#include <linux/of.h>

arch/riscv/kernel/setup.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,27 @@
3939
#include <asm/tlbflush.h>
4040
#include <asm/thread_info.h>
4141

42+
#ifdef CONFIG_EARLY_PRINTK
43+
static void sbi_console_write(struct console *co, const char *buf,
44+
unsigned int n)
45+
{
46+
int i;
47+
48+
for (i = 0; i < n; ++i) {
49+
if (buf[i] == '\n')
50+
sbi_console_putchar('\r');
51+
sbi_console_putchar(buf[i]);
52+
}
53+
}
54+
55+
struct console riscv_sbi_early_console_dev __initdata = {
56+
.name = "early",
57+
.write = sbi_console_write,
58+
.flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
59+
.index = -1
60+
};
61+
#endif
62+
4263
#ifdef CONFIG_DUMMY_CONSOLE
4364
struct screen_info screen_info = {
4465
.orig_video_lines = 30,
@@ -195,6 +216,12 @@ static void __init setup_bootmem(void)
195216

196217
void __init setup_arch(char **cmdline_p)
197218
{
219+
#if defined(CONFIG_EARLY_PRINTK)
220+
if (likely(early_console == NULL)) {
221+
early_console = &riscv_sbi_early_console_dev;
222+
register_console(early_console);
223+
}
224+
#endif
198225
*cmdline_p = boot_command_line;
199226

200227
parse_early_param();

arch/riscv/kernel/smp.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ int setup_profiling_timer(unsigned int multiplier)
4545
return -EINVAL;
4646
}
4747

48-
irqreturn_t handle_ipi(void)
48+
void riscv_software_interrupt(void)
4949
{
5050
unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
5151

@@ -60,7 +60,7 @@ irqreturn_t handle_ipi(void)
6060

6161
ops = xchg(pending_ipis, 0);
6262
if (ops == 0)
63-
return IRQ_HANDLED;
63+
return;
6464

6565
if (ops & (1 << IPI_RESCHEDULE))
6666
scheduler_ipi();
@@ -73,8 +73,6 @@ irqreturn_t handle_ipi(void)
7373
/* Order data access and bit testing. */
7474
mb();
7575
}
76-
77-
return IRQ_HANDLED;
7876
}
7977

8078
static void

arch/riscv/kernel/smpboot.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ asmlinkage void __init smp_callin(void)
104104
current->active_mm = mm;
105105

106106
trap_init();
107-
init_clockevent();
108107
notify_cpu_starting(smp_processor_id());
109108
set_cpu_online(smp_processor_id(), 1);
110109
local_flush_tlb_all();

arch/riscv/kernel/time.c

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,11 @@
1313
*/
1414

1515
#include <linux/clocksource.h>
16-
#include <linux/clockchips.h>
1716
#include <linux/delay.h>
18-
19-
#ifdef CONFIG_RISCV_TIMER
20-
#include <linux/timer_riscv.h>
21-
#endif
22-
2317
#include <asm/sbi.h>
2418

2519
unsigned long riscv_timebase;
2620

27-
DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event);
28-
29-
void riscv_timer_interrupt(void)
30-
{
31-
#ifdef CONFIG_RISCV_TIMER
32-
/*
33-
* FIXME: This needs to be cleaned up along with the rest of the IRQ
34-
* handling cleanup. See irq.c for more details.
35-
*/
36-
struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
37-
38-
evdev->event_handler(evdev);
39-
#endif
40-
}
41-
42-
void __init init_clockevent(void)
43-
{
44-
timer_probe();
45-
csr_set(sie, SIE_STIE);
46-
}
47-
4821
void __init time_init(void)
4922
{
5023
struct device_node *cpu;
@@ -56,6 +29,5 @@ void __init time_init(void)
5629
riscv_timebase = prop;
5730

5831
lpj_fine = riscv_timebase / HZ;
59-
60-
init_clockevent();
32+
timer_probe();
6133
}

0 commit comments

Comments
 (0)