diff options
Diffstat (limited to 'arch/riscv')
-rw-r--r-- | arch/riscv/Makefile | 3 | ||||
-rw-r--r-- | arch/riscv/configs/defconfig | 1 | ||||
-rw-r--r-- | arch/riscv/include/asm/csr.h | 1 | ||||
-rw-r--r-- | arch/riscv/include/asm/irq.h | 5 | ||||
-rw-r--r-- | arch/riscv/include/asm/perf_event.h | 1 | ||||
-rw-r--r-- | arch/riscv/include/asm/smp.h | 6 | ||||
-rw-r--r-- | arch/riscv/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/riscv/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/riscv/kernel/irq.c | 55 | ||||
-rw-r--r-- | arch/riscv/kernel/perf_event.c | 1 | ||||
-rw-r--r-- | arch/riscv/kernel/setup.c | 27 | ||||
-rw-r--r-- | arch/riscv/kernel/smp.c | 6 | ||||
-rw-r--r-- | arch/riscv/kernel/smpboot.c | 1 | ||||
-rw-r--r-- | arch/riscv/kernel/time.c | 30 | ||||
-rw-r--r-- | arch/riscv/kernel/traps.c | 1 | ||||
-rw-r--r-- | arch/riscv/kernel/vdso/Makefile | 4 | ||||
-rw-r--r-- | arch/riscv/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/riscv/lib/tishift.S | 42 |
18 files changed, 132 insertions, 59 deletions
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) KBUILD_CFLAGS += -mabi=lp64 KBUILD_AFLAGS += -mabi=lp64 + + KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128) + KBUILD_MARCH = rv64im LDFLAGS += -melf64lriscv else 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 CONFIG_CRYPTO_USER_API_HASH=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y +CONFIG_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 @@ /* Interrupt Enable and Interrupt Pending flags */ #define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */ #define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */ +#define SIE_SEIE _AC(0x00000200, UL) /* External Interrupt Enable */ #define EXC_INST_MISALIGNED 0 #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 @@ #define NR_IRQS 0 -#define INTERRUPT_CAUSE_SOFTWARE 1 -#define INTERRUPT_CAUSE_TIMER 5 -#define INTERRUPT_CAUSE_EXTERNAL 9 - void riscv_timer_interrupt(void); +void riscv_software_interrupt(void); #include <asm-generic/irq.h> 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 @@ #include <linux/perf_event.h> #include <linux/ptrace.h> +#include <linux/interrupt.h> #define RISCV_BASE_COUNTERS 2 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 @@ #ifdef CONFIG_SMP /* SMP initialization hook for setup_arch */ -void __init init_clockevent(void); - -/* SMP initialization hook for setup_arch */ void __init setup_smp(void); /* Hook for the generic smp_call_function_many() routine. */ @@ -44,9 +41,6 @@ void arch_send_call_function_single_ipi(int cpu); */ #define raw_smp_processor_id() (*((int*)((char*)get_current() + TASK_TI_CPU))) -/* Interprocessor interrupt handler */ -irqreturn_t handle_ipi(void); - #endif /* CONFIG_SMP */ #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) /* Handle interrupts */ move a0, sp /* pt_regs */ - REG_L a1, handle_arch_irq - jr a1 + move a1, s4 /* scause */ + tail do_IRQ 1: /* Exceptions run with interrupts enabled */ 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: or a0, a0, a1 sfence.vma csrw sptbr, a0 +.align 2 1: /* Set trap vector to spin forever to help debug */ la a0, .Lsecondary_park @@ -143,6 +144,7 @@ relocate: tail smp_callin #endif +.align 2 .Lsecondary_park: /* We lack SMP support or have too many harts, so park this hart */ 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 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2012 Regents of the University of California * Copyright (C) 2017 SiFive - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Copyright (C) 2018 Christoph Hellwig */ #include <linux/interrupt.h> #include <linux/irqchip.h> #include <linux/irqdomain.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)) + +asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long cause) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + + irq_enter(); + switch (cause & ~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(); 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 @@ #include <linux/mutex.h> #include <linux/bitmap.h> #include <linux/irq.h> -#include <linux/interrupt.h> #include <linux/perf_event.h> #include <linux/atomic.h> #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 @@ #include <asm/tlbflush.h> #include <asm/thread_info.h> +#ifdef CONFIG_EARLY_PRINTK +static void sbi_console_write(struct console *co, const char *buf, + unsigned int n) +{ + int i; + + for (i = 0; i < n; ++i) { + if (buf[i] == '\n') + sbi_console_putchar('\r'); + sbi_console_putchar(buf[i]); + } +} + +struct console riscv_sbi_early_console_dev __initdata = { + .name = "early", + .write = sbi_console_write, + .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME, + .index = -1 +}; +#endif + #ifdef CONFIG_DUMMY_CONSOLE struct screen_info screen_info = { .orig_video_lines = 30, @@ -195,6 +216,12 @@ static void __init setup_bootmem(void) void __init setup_arch(char **cmdline_p) { +#if defined(CONFIG_EARLY_PRINTK) + if (likely(early_console == NULL)) { + early_console = &riscv_sbi_early_console_dev; + register_console(early_console); + } +#endif *cmdline_p = boot_command_line; 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) return -EINVAL; } -irqreturn_t handle_ipi(void) +void riscv_software_interrupt(void) { unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; @@ -60,7 +60,7 @@ irqreturn_t handle_ipi(void) ops = xchg(pending_ipis, 0); if (ops == 0) - return IRQ_HANDLED; + return; if (ops & (1 << IPI_RESCHEDULE)) scheduler_ipi(); @@ -73,8 +73,6 @@ irqreturn_t handle_ipi(void) /* Order data access and bit testing. */ mb(); } - - return IRQ_HANDLED; } static 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) current->active_mm = mm; trap_init(); - init_clockevent(); notify_cpu_starting(smp_processor_id()); set_cpu_online(smp_processor_id(), 1); 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 @@ */ #include <linux/clocksource.h> -#include <linux/clockchips.h> #include <linux/delay.h> - -#ifdef CONFIG_RISCV_TIMER -#include <linux/timer_riscv.h> -#endif - #include <asm/sbi.h> unsigned long riscv_timebase; -DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event); - -void riscv_timer_interrupt(void) -{ -#ifdef CONFIG_RISCV_TIMER - /* - * FIXME: This needs to be cleaned up along with the rest of the IRQ - * handling cleanup. See irq.c for more details. - */ - struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event); - - evdev->event_handler(evdev); -#endif -} - -void __init init_clockevent(void) -{ - timer_probe(); - csr_set(sie, SIE_STIE); -} - void __init time_init(void) { struct device_node *cpu; @@ -56,6 +29,5 @@ void __init time_init(void) riscv_timebase = prop; lpj_fine = riscv_timebase / HZ; - - init_clockevent(); + timer_probe(); } 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) #endif /* CONFIG_GENERIC_BUG */ force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)(regs->sepc), current); - regs->sepc += 0x4; } #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 # Add -lgcc so rv32 gets static muldi3 and lshrdi3 definitions. # Make sure only to export the intended __vdso_xxx symbol offsets. quiet_cmd_vdsold = VDSOLD $@ - cmd_vdsold = $(CC) $(KCFLAGS) $(call cc-option, -no-pie) -nostdlib $(SYSCFLAGS_$(@F)) \ - -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp -lgcc && \ + cmd_vdsold = $(CC) $(KBUILD_CFLAGS) $(call cc-option, -no-pie) -nostdlib -nostartfiles $(SYSCFLAGS_$(@F)) \ + -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp && \ $(CROSS_COMPILE)objcopy \ $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ 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 lib-y += memcpy.o lib-y += memset.o lib-y += uaccess.o +lib-y += tishift.o lib-$(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 @@ +/* + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + .globl __lshrti3 +__lshrti3: + beqz a2, .L1 + li a5,64 + sub a5,a5,a2 + addi sp,sp,-16 + sext.w a4,a5 + blez a5, .L2 + sext.w a2,a2 + sll a4,a1,a4 + srl a0,a0,a2 + srl a1,a1,a2 + or a0,a0,a4 + sd a1,8(sp) + sd a0,0(sp) + ld a0,0(sp) + ld a1,8(sp) + addi sp,sp,16 + ret +.L1: + ret +.L2: + negw a4,a4 + srl a1,a1,a4 + sd a1,0(sp) + sd zero,8(sp) + ld a0,0(sp) + ld a1,8(sp) + addi sp,sp,16 + ret |