aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-19 12:56:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-19 12:56:38 -0400
commit1009aa1205c2c5e9101437dcadfa195708d863bf (patch)
tree49e76c84522866fae25ba37372aef241b8713c3f
parent1d0926e99de7b486321e3db924b445531eea5e18 (diff)
parent627672cf431b0379c07cc8d146f907cda6797222 (diff)
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
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt44
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.txt58
-rw-r--r--arch/riscv/Makefile3
-rw-r--r--arch/riscv/configs/defconfig1
-rw-r--r--arch/riscv/include/asm/csr.h1
-rw-r--r--arch/riscv/include/asm/irq.h5
-rw-r--r--arch/riscv/include/asm/perf_event.h1
-rw-r--r--arch/riscv/include/asm/smp.h6
-rw-r--r--arch/riscv/kernel/entry.S4
-rw-r--r--arch/riscv/kernel/head.S2
-rw-r--r--arch/riscv/kernel/irq.c55
-rw-r--r--arch/riscv/kernel/perf_event.c1
-rw-r--r--arch/riscv/kernel/setup.c27
-rw-r--r--arch/riscv/kernel/smp.c6
-rw-r--r--arch/riscv/kernel/smpboot.c1
-rw-r--r--arch/riscv/kernel/time.c30
-rw-r--r--arch/riscv/kernel/traps.c1
-rw-r--r--arch/riscv/kernel/vdso/Makefile4
-rw-r--r--arch/riscv/lib/Makefile1
-rw-r--r--arch/riscv/lib/tishift.S42
-rw-r--r--drivers/clocksource/Kconfig11
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/riscv_timer.c105
-rw-r--r--drivers/irqchip/Kconfig12
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-sifive-plic.c260
-rw-r--r--include/linux/cpuhotplug.h1
27 files changed, 625 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
new file mode 100644
index 000000000000..b0a8af51c388
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
@@ -0,0 +1,44 @@
1RISC-V Hart-Level Interrupt Controller (HLIC)
2---------------------------------------------
3
4RISC-V cores include Control Status Registers (CSRs) which are local to each
5CPU core (HART in RISC-V terminology) and can be read or written by software.
6Some of these CSRs are used to control local interrupts connected to the core.
7Every interrupt is ultimately routed through a hart's HLIC before it
8interrupts that hart.
9
10The RISC-V supervisor ISA manual specifies three interrupt sources that are
11attached to every HLIC: software interrupts, the timer interrupt, and external
12interrupts. Software interrupts are used to send IPIs between cores. The
13timer interrupt comes from an architecturally mandated real-time timer that is
14controller via Supervisor Binary Interface (SBI) calls and CSR reads. External
15interrupts connect all other device interrupts to the HLIC, which are routed
16via the platform-level interrupt controller (PLIC).
17
18All RISC-V systems that conform to the supervisor ISA specification are
19required to have a HLIC with these three interrupt sources present. Since the
20interrupt map is defined by the ISA it's not listed in the HLIC's device tree
21entry, though external interrupt controllers (like the PLIC, for example) will
22need to define how their interrupts map to the relevant HLICs. This means
23a PLIC interrupt property will typically list the HLICs for all present HARTs
24in the system.
25
26Required properties:
27- compatible : "riscv,cpu-intc"
28- #interrupt-cells : should be <1>
29- interrupt-controller : Identifies the node as an interrupt controller
30
31Furthermore, this interrupt-controller MUST be embedded inside the cpu
32definition of the hart whose CSRs control these local interrupts.
33
34An 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 };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.txt b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.txt
new file mode 100644
index 000000000000..6adf7a6e8825
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.txt
@@ -0,0 +1,58 @@
1SiFive Platform-Level Interrupt Controller (PLIC)
2-------------------------------------------------
3
4SiFive SOCs include an implementation of the Platform-Level Interrupt Controller
5(PLIC) high-level specification in the RISC-V Privileged Architecture
6specification. The PLIC connects all external interrupts in the system to all
7hart contexts in the system, via the external interrupt source in each hart.
8
9A hart context is a privilege mode in a hardware execution thread. For example,
10in an 4 core system with 2-way SMT, you have 8 harts and probably at least two
11privilege modes per hart; machine mode and supervisor mode.
12
13Each interrupt can be enabled on per-context basis. Any context can claim
14a pending enabled interrupt and then release it once it has been handled.
15
16Each interrupt has a configurable priority. Higher priority interrupts are
17serviced first. Each context can specify a priority threshold. Interrupts
18with priority below this threshold will not cause the PLIC to raise its
19interrupt line leading to the context.
20
21While the PLIC supports both edge-triggered and level-triggered interrupts,
22interrupt handlers are oblivious to this distinction and therefore it is not
23specified in the PLIC device-tree binding.
24
25While 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
27contains a specific memory layout, which is documented in chapter 8 of the
28SiFive U5 Coreplex Series Manual <https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf>.
29
30Required 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
43Example:
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 };
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 2627e4813edf..9ddd88bb30b7 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -25,6 +25,9 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
25 25
26 KBUILD_CFLAGS += -mabi=lp64 26 KBUILD_CFLAGS += -mabi=lp64
27 KBUILD_AFLAGS += -mabi=lp64 27 KBUILD_AFLAGS += -mabi=lp64
28
29 KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128)
30
28 KBUILD_MARCH = rv64im 31 KBUILD_MARCH = rv64im
29 LDFLAGS += -melf64lriscv 32 LDFLAGS += -melf64lriscv
30else 33else
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 07326466871b..36473d7dbaac 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -76,3 +76,4 @@ CONFIG_ROOT_NFS=y
76CONFIG_CRYPTO_USER_API_HASH=y 76CONFIG_CRYPTO_USER_API_HASH=y
77CONFIG_MODULES=y 77CONFIG_MODULES=y
78CONFIG_MODULE_UNLOAD=y 78CONFIG_MODULE_UNLOAD=y
79CONFIG_SIFIVE_PLIC=y
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 421fa3585798..28a0d1cb374c 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -54,6 +54,7 @@
54/* Interrupt Enable and Interrupt Pending flags */ 54/* Interrupt Enable and Interrupt Pending flags */
55#define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */ 55#define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */
56#define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */ 56#define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */
57#define SIE_SEIE _AC(0x00000200, UL) /* External Interrupt Enable */
57 58
58#define EXC_INST_MISALIGNED 0 59#define EXC_INST_MISALIGNED 0
59#define EXC_INST_ACCESS 1 60#define EXC_INST_ACCESS 1
diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 4dee9d4c13c0..996b6fbe17a6 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -17,11 +17,8 @@
17 17
18#define NR_IRQS 0 18#define NR_IRQS 0
19 19
20#define INTERRUPT_CAUSE_SOFTWARE 1
21#define INTERRUPT_CAUSE_TIMER 5
22#define INTERRUPT_CAUSE_EXTERNAL 9
23
24void riscv_timer_interrupt(void); 20void riscv_timer_interrupt(void);
21void riscv_software_interrupt(void);
25 22
26#include <asm-generic/irq.h> 23#include <asm-generic/irq.h>
27 24
diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
index 0e638a0c3feb..aefbfaa6a781 100644
--- a/arch/riscv/include/asm/perf_event.h
+++ b/arch/riscv/include/asm/perf_event.h
@@ -10,6 +10,7 @@
10 10
11#include <linux/perf_event.h> 11#include <linux/perf_event.h>
12#include <linux/ptrace.h> 12#include <linux/ptrace.h>
13#include <linux/interrupt.h>
13 14
14#define RISCV_BASE_COUNTERS 2 15#define RISCV_BASE_COUNTERS 2
15 16
diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
index 85e4220839b0..36016845461d 100644
--- a/arch/riscv/include/asm/smp.h
+++ b/arch/riscv/include/asm/smp.h
@@ -25,9 +25,6 @@
25#ifdef CONFIG_SMP 25#ifdef CONFIG_SMP
26 26
27/* SMP initialization hook for setup_arch */ 27/* SMP initialization hook for setup_arch */
28void __init init_clockevent(void);
29
30/* SMP initialization hook for setup_arch */
31void __init setup_smp(void); 28void __init setup_smp(void);
32 29
33/* Hook for the generic smp_call_function_many() routine. */ 30/* Hook for the generic smp_call_function_many() routine. */
@@ -44,9 +41,6 @@ void arch_send_call_function_single_ipi(int cpu);
44 */ 41 */
45#define raw_smp_processor_id() (*((int*)((char*)get_current() + TASK_TI_CPU))) 42#define raw_smp_processor_id() (*((int*)((char*)get_current() + TASK_TI_CPU)))
46 43
47/* Interprocessor interrupt handler */
48irqreturn_t handle_ipi(void);
49
50#endif /* CONFIG_SMP */ 44#endif /* CONFIG_SMP */
51 45
52#endif /* _ASM_RISCV_SMP_H */ 46#endif /* _ASM_RISCV_SMP_H */
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..fa2c08e3c05e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -168,8 +168,8 @@ ENTRY(handle_exception)
168 168
169 /* Handle interrupts */ 169 /* Handle interrupts */
170 move a0, sp /* pt_regs */ 170 move a0, sp /* pt_regs */
171 REG_L a1, handle_arch_irq 171 move a1, s4 /* scause */
172 jr a1 172 tail do_IRQ
1731: 1731:
174 /* Exceptions run with interrupts enabled */ 174 /* Exceptions run with interrupts enabled */
175 csrs sstatus, SR_SIE 175 csrs sstatus, SR_SIE
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index 6e07ed37bbff..c4d2c63f9a29 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -94,6 +94,7 @@ relocate:
94 or a0, a0, a1 94 or a0, a0, a1
95 sfence.vma 95 sfence.vma
96 csrw sptbr, a0 96 csrw sptbr, a0
97.align 2
971: 981:
98 /* Set trap vector to spin forever to help debug */ 99 /* Set trap vector to spin forever to help debug */
99 la a0, .Lsecondary_park 100 la a0, .Lsecondary_park
@@ -143,6 +144,7 @@ relocate:
143 tail smp_callin 144 tail smp_callin
144#endif 145#endif
145 146
147.align 2
146.Lsecondary_park: 148.Lsecondary_park:
147 /* We lack SMP support or have too many harts, so park this hart */ 149 /* We lack SMP support or have too many harts, so park this hart */
148 wfi 150 wfi
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index 7bcdaed15703..0cfac48a1272 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -1,21 +1,58 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2012 Regents of the University of California 3 * Copyright (C) 2012 Regents of the University of California
3 * Copyright (C) 2017 SiFive 4 * Copyright (C) 2017 SiFive
4 * 5 * Copyright (C) 2018 Christoph Hellwig
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.
13 */ 6 */
14 7
15#include <linux/interrupt.h> 8#include <linux/interrupt.h>
16#include <linux/irqchip.h> 9#include <linux/irqchip.h>
17#include <linux/irqdomain.h> 10#include <linux/irqdomain.h>
18 11
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
27asmlinkage 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
19void __init init_IRQ(void) 56void __init init_IRQ(void)
20{ 57{
21 irqchip_init(); 58 irqchip_init();
diff --git a/arch/riscv/kernel/perf_event.c b/arch/riscv/kernel/perf_event.c
index b0e10c4e9f77..a243fae1c1db 100644
--- a/arch/riscv/kernel/perf_event.c
+++ b/arch/riscv/kernel/perf_event.c
@@ -27,7 +27,6 @@
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <linux/bitmap.h> 28#include <linux/bitmap.h>
29#include <linux/irq.h> 29#include <linux/irq.h>
30#include <linux/interrupt.h>
31#include <linux/perf_event.h> 30#include <linux/perf_event.h>
32#include <linux/atomic.h> 31#include <linux/atomic.h>
33#include <linux/of.h> 32#include <linux/of.h>
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index f0d2070866d4..db20dc630e7e 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -39,6 +39,27 @@
39#include <asm/tlbflush.h> 39#include <asm/tlbflush.h>
40#include <asm/thread_info.h> 40#include <asm/thread_info.h>
41 41
42#ifdef CONFIG_EARLY_PRINTK
43static 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
55struct 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
42#ifdef CONFIG_DUMMY_CONSOLE 63#ifdef CONFIG_DUMMY_CONSOLE
43struct screen_info screen_info = { 64struct screen_info screen_info = {
44 .orig_video_lines = 30, 65 .orig_video_lines = 30,
@@ -195,6 +216,12 @@ static void __init setup_bootmem(void)
195 216
196void __init setup_arch(char **cmdline_p) 217void __init setup_arch(char **cmdline_p)
197{ 218{
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
198 *cmdline_p = boot_command_line; 225 *cmdline_p = boot_command_line;
199 226
200 parse_early_param(); 227 parse_early_param();
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index 6d3962435720..906fe21ea21b 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -45,7 +45,7 @@ int setup_profiling_timer(unsigned int multiplier)
45 return -EINVAL; 45 return -EINVAL;
46} 46}
47 47
48irqreturn_t handle_ipi(void) 48void riscv_software_interrupt(void)
49{ 49{
50 unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; 50 unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
51 51
@@ -60,7 +60,7 @@ irqreturn_t handle_ipi(void)
60 60
61 ops = xchg(pending_ipis, 0); 61 ops = xchg(pending_ipis, 0);
62 if (ops == 0) 62 if (ops == 0)
63 return IRQ_HANDLED; 63 return;
64 64
65 if (ops & (1 << IPI_RESCHEDULE)) 65 if (ops & (1 << IPI_RESCHEDULE))
66 scheduler_ipi(); 66 scheduler_ipi();
@@ -73,8 +73,6 @@ irqreturn_t handle_ipi(void)
73 /* Order data access and bit testing. */ 73 /* Order data access and bit testing. */
74 mb(); 74 mb();
75 } 75 }
76
77 return IRQ_HANDLED;
78} 76}
79 77
80static void 78static void
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
index f741458c5a3f..56abab6a9812 100644
--- a/arch/riscv/kernel/smpboot.c
+++ b/arch/riscv/kernel/smpboot.c
@@ -104,7 +104,6 @@ asmlinkage void __init smp_callin(void)
104 current->active_mm = mm; 104 current->active_mm = mm;
105 105
106 trap_init(); 106 trap_init();
107 init_clockevent();
108 notify_cpu_starting(smp_processor_id()); 107 notify_cpu_starting(smp_processor_id());
109 set_cpu_online(smp_processor_id(), 1); 108 set_cpu_online(smp_processor_id(), 1);
110 local_flush_tlb_all(); 109 local_flush_tlb_all();
diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
index 2463fcca719e..1911c8f6b8a6 100644
--- a/arch/riscv/kernel/time.c
+++ b/arch/riscv/kernel/time.c
@@ -13,38 +13,11 @@
13 */ 13 */
14 14
15#include <linux/clocksource.h> 15#include <linux/clocksource.h>
16#include <linux/clockchips.h>
17#include <linux/delay.h> 16#include <linux/delay.h>
18
19#ifdef CONFIG_RISCV_TIMER
20#include <linux/timer_riscv.h>
21#endif
22
23#include <asm/sbi.h> 17#include <asm/sbi.h>
24 18
25unsigned long riscv_timebase; 19unsigned long riscv_timebase;
26 20
27DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event);
28
29void 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
42void __init init_clockevent(void)
43{
44 timer_probe();
45 csr_set(sie, SIE_STIE);
46}
47
48void __init time_init(void) 21void __init time_init(void)
49{ 22{
50 struct device_node *cpu; 23 struct device_node *cpu;
@@ -56,6 +29,5 @@ void __init time_init(void)
56 riscv_timebase = prop; 29 riscv_timebase = prop;
57 30
58 lpj_fine = riscv_timebase / HZ; 31 lpj_fine = riscv_timebase / HZ;
59 32 timer_probe();
60 init_clockevent();
61} 33}
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 81a1952015a6..24a9333dda2c 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -138,7 +138,6 @@ asmlinkage void do_trap_break(struct pt_regs *regs)
138#endif /* CONFIG_GENERIC_BUG */ 138#endif /* CONFIG_GENERIC_BUG */
139 139
140 force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)(regs->sepc), current); 140 force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)(regs->sepc), current);
141 regs->sepc += 0x4;
142} 141}
143 142
144#ifdef CONFIG_GENERIC_BUG 143#ifdef CONFIG_GENERIC_BUG
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index f6561b783b61..eed1c137f618 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -52,8 +52,8 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
52# Add -lgcc so rv32 gets static muldi3 and lshrdi3 definitions. 52# Add -lgcc so rv32 gets static muldi3 and lshrdi3 definitions.
53# Make sure only to export the intended __vdso_xxx symbol offsets. 53# Make sure only to export the intended __vdso_xxx symbol offsets.
54quiet_cmd_vdsold = VDSOLD $@ 54quiet_cmd_vdsold = VDSOLD $@
55 cmd_vdsold = $(CC) $(KCFLAGS) $(call cc-option, -no-pie) -nostdlib $(SYSCFLAGS_$(@F)) \ 55 cmd_vdsold = $(CC) $(KBUILD_CFLAGS) $(call cc-option, -no-pie) -nostdlib -nostartfiles $(SYSCFLAGS_$(@F)) \
56 -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp -lgcc && \ 56 -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp && \
57 $(CROSS_COMPILE)objcopy \ 57 $(CROSS_COMPILE)objcopy \
58 $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ 58 $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@
59 59
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 596c2ca40d63..445ec84f9a47 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -2,5 +2,6 @@ lib-y += delay.o
2lib-y += memcpy.o 2lib-y += memcpy.o
3lib-y += memset.o 3lib-y += memset.o
4lib-y += uaccess.o 4lib-y += uaccess.o
5lib-y += tishift.o
5 6
6lib-$(CONFIG_32BIT) += udivdi3.o 7lib-$(CONFIG_32BIT) += udivdi3.o
diff --git a/arch/riscv/lib/tishift.S b/arch/riscv/lib/tishift.S
new file mode 100644
index 000000000000..69abb1277234
--- /dev/null
+++ b/arch/riscv/lib/tishift.S
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2018 Free Software Foundation, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13 .globl __lshrti3
14__lshrti3:
15 beqz a2, .L1
16 li a5,64
17 sub a5,a5,a2
18 addi sp,sp,-16
19 sext.w a4,a5
20 blez a5, .L2
21 sext.w a2,a2
22 sll a4,a1,a4
23 srl a0,a0,a2
24 srl a1,a1,a2
25 or a0,a0,a4
26 sd a1,8(sp)
27 sd a0,0(sp)
28 ld a0,0(sp)
29 ld a1,8(sp)
30 addi sp,sp,16
31 ret
32.L1:
33 ret
34.L2:
35 negw a4,a4
36 srl a1,a1,a4
37 sd a1,0(sp)
38 sd zero,8(sp)
39 ld a0,0(sp)
40 ld a1,8(sp)
41 addi sp,sp,16
42 ret
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index dec0dd88ec15..a11f4ba98b05 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -609,4 +609,15 @@ config ATCPIT100_TIMER
609 help 609 help
610 This option enables support for the Andestech ATCPIT100 timers. 610 This option enables support for the Andestech ATCPIT100 timers.
611 611
612config RISCV_TIMER
613 bool "Timer for the RISC-V platform"
614 depends on RISCV
615 default y
616 select TIMER_PROBE
617 select TIMER_OF
618 help
619 This enables the per-hart timer built into all RISC-V systems, which
620 is accessed via both the SBI and the rdcycle instruction. This is
621 required for all RISC-V systems.
622
612endmenu 623endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index c070cc7992e9..db51b2427e8a 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -78,3 +78,4 @@ obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
78obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o 78obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
79obj-$(CONFIG_X86_NUMACHIP) += numachip.o 79obj-$(CONFIG_X86_NUMACHIP) += numachip.o
80obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o 80obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o
81obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o
diff --git a/drivers/clocksource/riscv_timer.c b/drivers/clocksource/riscv_timer.c
new file mode 100644
index 000000000000..4e8b347e43e2
--- /dev/null
+++ b/drivers/clocksource/riscv_timer.c
@@ -0,0 +1,105 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2012 Regents of the University of California
4 * Copyright (C) 2017 SiFive
5 */
6#include <linux/clocksource.h>
7#include <linux/clockchips.h>
8#include <linux/cpu.h>
9#include <linux/delay.h>
10#include <linux/irq.h>
11#include <asm/sbi.h>
12
13/*
14 * All RISC-V systems have a timer attached to every hart. These timers can be
15 * read by the 'rdcycle' pseudo instruction, and can use the SBI to setup
16 * events. In order to abstract the architecture-specific timer reading and
17 * setting functions away from the clock event insertion code, we provide
18 * function pointers to the clockevent subsystem that perform two basic
19 * operations: rdtime() reads the timer on the current CPU, and
20 * next_event(delta) sets the next timer event to 'delta' cycles in the future.
21 * As the timers are inherently a per-cpu resource, these callbacks perform
22 * operations on the current hart. There is guaranteed to be exactly one timer
23 * per hart on all RISC-V systems.
24 */
25
26static int riscv_clock_next_event(unsigned long delta,
27 struct clock_event_device *ce)
28{
29 csr_set(sie, SIE_STIE);
30 sbi_set_timer(get_cycles64() + delta);
31 return 0;
32}
33
34static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
35 .name = "riscv_timer_clockevent",
36 .features = CLOCK_EVT_FEAT_ONESHOT,
37 .rating = 100,
38 .set_next_event = riscv_clock_next_event,
39};
40
41/*
42 * It is guaranteed that all the timers across all the harts are synchronized
43 * within one tick of each other, so while this could technically go
44 * backwards when hopping between CPUs, practically it won't happen.
45 */
46static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs)
47{
48 return get_cycles64();
49}
50
51static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = {
52 .name = "riscv_clocksource",
53 .rating = 300,
54 .mask = CLOCKSOURCE_MASK(BITS_PER_LONG),
55 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
56 .read = riscv_clocksource_rdtime,
57};
58
59static int riscv_timer_starting_cpu(unsigned int cpu)
60{
61 struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu);
62
63 ce->cpumask = cpumask_of(cpu);
64 clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
65
66 csr_set(sie, SIE_STIE);
67 return 0;
68}
69
70static int riscv_timer_dying_cpu(unsigned int cpu)
71{
72 csr_clear(sie, SIE_STIE);
73 return 0;
74}
75
76/* called directly from the low-level interrupt handler */
77void riscv_timer_interrupt(void)
78{
79 struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
80
81 csr_clear(sie, SIE_STIE);
82 evdev->event_handler(evdev);
83}
84
85static int __init riscv_timer_init_dt(struct device_node *n)
86{
87 int cpu_id = riscv_of_processor_hart(n), error;
88 struct clocksource *cs;
89
90 if (cpu_id != smp_processor_id())
91 return 0;
92
93 cs = per_cpu_ptr(&riscv_clocksource, cpu_id);
94 clocksource_register_hz(cs, riscv_timebase);
95
96 error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
97 "clockevents/riscv/timer:starting",
98 riscv_timer_starting_cpu, riscv_timer_dying_cpu);
99 if (error)
100 pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
101 error, cpu_id);
102 return error;
103}
104
105TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d564d21245c5..383e7b70221d 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -372,3 +372,15 @@ config QCOM_PDC
372 IRQs for Qualcomm Technologies Inc (QTI) mobile chips. 372 IRQs for Qualcomm Technologies Inc (QTI) mobile chips.
373 373
374endmenu 374endmenu
375
376config SIFIVE_PLIC
377 bool "SiFive Platform-Level Interrupt Controller"
378 depends on RISCV
379 help
380 This enables support for the PLIC chip found in SiFive (and
381 potentially other) RISC-V systems. The PLIC controls devices
382 interrupts and connects them to each core's local interrupt
383 controller. Aside from timer and software interrupts, all other
384 interrupt sources are subordinate to the PLIC.
385
386 If you don't know what to do here, say Y.
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 15f268f646bf..fbd1ec8070ef 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -87,3 +87,4 @@ obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o
87obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o 87obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o
88obj-$(CONFIG_NDS32) += irq-ativic32.o 88obj-$(CONFIG_NDS32) += irq-ativic32.o
89obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o 89obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o
90obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
new file mode 100644
index 000000000000..532e9d68c704
--- /dev/null
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -0,0 +1,260 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2017 SiFive
4 * Copyright (C) 2018 Christoph Hellwig
5 */
6#define pr_fmt(fmt) "plic: " fmt
7#include <linux/interrupt.h>
8#include <linux/io.h>
9#include <linux/irq.h>
10#include <linux/irqchip.h>
11#include <linux/irqdomain.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_address.h>
15#include <linux/of_irq.h>
16#include <linux/platform_device.h>
17#include <linux/spinlock.h>
18
19/*
20 * This driver implements a version of the RISC-V PLIC with the actual layout
21 * specified in chapter 8 of the SiFive U5 Coreplex Series Manual:
22 *
23 * https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf
24 *
25 * The largest number supported by devices marked as 'sifive,plic-1.0.0', is
26 * 1024, of which device 0 is defined as non-existent by the RISC-V Privileged
27 * Spec.
28 */
29
30#define MAX_DEVICES 1024
31#define MAX_CONTEXTS 15872
32
33/*
34 * Each interrupt source has a priority register associated with it.
35 * We always hardwire it to one in Linux.
36 */
37#define PRIORITY_BASE 0
38#define PRIORITY_PER_ID 4
39
40/*
41 * Each hart context has a vector of interrupt enable bits associated with it.
42 * There's one bit for each interrupt source.
43 */
44#define ENABLE_BASE 0x2000
45#define ENABLE_PER_HART 0x80
46
47/*
48 * Each hart context has a set of control registers associated with it. Right
49 * now there's only two: a source priority threshold over which the hart will
50 * take an interrupt, and a register to claim interrupts.
51 */
52#define CONTEXT_BASE 0x200000
53#define CONTEXT_PER_HART 0x1000
54#define CONTEXT_THRESHOLD 0x00
55#define CONTEXT_CLAIM 0x04
56
57static void __iomem *plic_regs;
58
59struct plic_handler {
60 bool present;
61 int ctxid;
62};
63static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
64
65static inline void __iomem *plic_hart_offset(int ctxid)
66{
67 return plic_regs + CONTEXT_BASE + ctxid * CONTEXT_PER_HART;
68}
69
70static inline u32 __iomem *plic_enable_base(int ctxid)
71{
72 return plic_regs + ENABLE_BASE + ctxid * ENABLE_PER_HART;
73}
74
75/*
76 * Protect mask operations on the registers given that we can't assume that
77 * atomic memory operations work on them.
78 */
79static DEFINE_RAW_SPINLOCK(plic_toggle_lock);
80
81static inline void plic_toggle(int ctxid, int hwirq, int enable)
82{
83 u32 __iomem *reg = plic_enable_base(ctxid) + (hwirq / 32);
84 u32 hwirq_mask = 1 << (hwirq % 32);
85
86 raw_spin_lock(&plic_toggle_lock);
87 if (enable)
88 writel(readl(reg) | hwirq_mask, reg);
89 else
90 writel(readl(reg) & ~hwirq_mask, reg);
91 raw_spin_unlock(&plic_toggle_lock);
92}
93
94static inline void plic_irq_toggle(struct irq_data *d, int enable)
95{
96 int cpu;
97
98 writel(enable, plic_regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
99 for_each_cpu(cpu, irq_data_get_affinity_mask(d)) {
100 struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
101
102 if (handler->present)
103 plic_toggle(handler->ctxid, d->hwirq, enable);
104 }
105}
106
107static void plic_irq_enable(struct irq_data *d)
108{
109 plic_irq_toggle(d, 1);
110}
111
112static void plic_irq_disable(struct irq_data *d)
113{
114 plic_irq_toggle(d, 0);
115}
116
117static struct irq_chip plic_chip = {
118 .name = "SiFive PLIC",
119 /*
120 * There is no need to mask/unmask PLIC interrupts. They are "masked"
121 * by reading claim and "unmasked" when writing it back.
122 */
123 .irq_enable = plic_irq_enable,
124 .irq_disable = plic_irq_disable,
125};
126
127static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
128 irq_hw_number_t hwirq)
129{
130 irq_set_chip_and_handler(irq, &plic_chip, handle_simple_irq);
131 irq_set_chip_data(irq, NULL);
132 irq_set_noprobe(irq);
133 return 0;
134}
135
136static const struct irq_domain_ops plic_irqdomain_ops = {
137 .map = plic_irqdomain_map,
138 .xlate = irq_domain_xlate_onecell,
139};
140
141static struct irq_domain *plic_irqdomain;
142
143/*
144 * Handling an interrupt is a two-step process: first you claim the interrupt
145 * by reading the claim register, then you complete the interrupt by writing
146 * that source ID back to the same claim register. This automatically enables
147 * and disables the interrupt, so there's nothing else to do.
148 */
149static void plic_handle_irq(struct pt_regs *regs)
150{
151 struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
152 void __iomem *claim = plic_hart_offset(handler->ctxid) + CONTEXT_CLAIM;
153 irq_hw_number_t hwirq;
154
155 WARN_ON_ONCE(!handler->present);
156
157 csr_clear(sie, SIE_SEIE);
158 while ((hwirq = readl(claim))) {
159 int irq = irq_find_mapping(plic_irqdomain, hwirq);
160
161 if (unlikely(irq <= 0))
162 pr_warn_ratelimited("can't find mapping for hwirq %lu\n",
163 hwirq);
164 else
165 generic_handle_irq(irq);
166 writel(hwirq, claim);
167 }
168 csr_set(sie, SIE_SEIE);
169}
170
171/*
172 * Walk up the DT tree until we find an active RISC-V core (HART) node and
173 * extract the cpuid from it.
174 */
175static int plic_find_hart_id(struct device_node *node)
176{
177 for (; node; node = node->parent) {
178 if (of_device_is_compatible(node, "riscv"))
179 return riscv_of_processor_hart(node);
180 }
181
182 return -1;
183}
184
185static int __init plic_init(struct device_node *node,
186 struct device_node *parent)
187{
188 int error = 0, nr_handlers, nr_mapped = 0, i;
189 u32 nr_irqs;
190
191 if (plic_regs) {
192 pr_warn("PLIC already present.\n");
193 return -ENXIO;
194 }
195
196 plic_regs = of_iomap(node, 0);
197 if (WARN_ON(!plic_regs))
198 return -EIO;
199
200 error = -EINVAL;
201 of_property_read_u32(node, "riscv,ndev", &nr_irqs);
202 if (WARN_ON(!nr_irqs))
203 goto out_iounmap;
204
205 nr_handlers = of_irq_count(node);
206 if (WARN_ON(!nr_handlers))
207 goto out_iounmap;
208 if (WARN_ON(nr_handlers < num_possible_cpus()))
209 goto out_iounmap;
210
211 error = -ENOMEM;
212 plic_irqdomain = irq_domain_add_linear(node, nr_irqs + 1,
213 &plic_irqdomain_ops, NULL);
214 if (WARN_ON(!plic_irqdomain))
215 goto out_iounmap;
216
217 for (i = 0; i < nr_handlers; i++) {
218 struct of_phandle_args parent;
219 struct plic_handler *handler;
220 irq_hw_number_t hwirq;
221 int cpu;
222
223 if (of_irq_parse_one(node, i, &parent)) {
224 pr_err("failed to parse parent for context %d.\n", i);
225 continue;
226 }
227
228 /* skip context holes */
229 if (parent.args[0] == -1)
230 continue;
231
232 cpu = plic_find_hart_id(parent.np);
233 if (cpu < 0) {
234 pr_warn("failed to parse hart ID for context %d.\n", i);
235 continue;
236 }
237
238 handler = per_cpu_ptr(&plic_handlers, cpu);
239 handler->present = true;
240 handler->ctxid = i;
241
242 /* priority must be > threshold to trigger an interrupt */
243 writel(0, plic_hart_offset(i) + CONTEXT_THRESHOLD);
244 for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
245 plic_toggle(i, hwirq, 0);
246 nr_mapped++;
247 }
248
249 pr_info("mapped %d interrupts to %d (out of %d) handlers.\n",
250 nr_irqs, nr_mapped, nr_handlers);
251 set_handle_irq(plic_handle_irq);
252 return 0;
253
254out_iounmap:
255 iounmap(plic_regs);
256 return error;
257}
258
259IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init);
260IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 4cf06a64bc02..c49843c4d031 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -125,6 +125,7 @@ enum cpuhp_state {
125 CPUHP_AP_MARCO_TIMER_STARTING, 125 CPUHP_AP_MARCO_TIMER_STARTING,
126 CPUHP_AP_MIPS_GIC_TIMER_STARTING, 126 CPUHP_AP_MIPS_GIC_TIMER_STARTING,
127 CPUHP_AP_ARC_TIMER_STARTING, 127 CPUHP_AP_ARC_TIMER_STARTING,
128 CPUHP_AP_RISCV_TIMER_STARTING,
128 CPUHP_AP_KVM_STARTING, 129 CPUHP_AP_KVM_STARTING,
129 CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING, 130 CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
130 CPUHP_AP_KVM_ARM_VGIC_STARTING, 131 CPUHP_AP_KVM_ARM_VGIC_STARTING,