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
This commit is contained in:
Linus Torvalds
2018-08-19 09:56:38 -07:00
27 changed files with 625 additions and 59 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -10,6 +10,7 @@
#include <linux/perf_event.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#define RISCV_BASE_COUNTERS 2

View File

@@ -24,9 +24,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);
@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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>

View File

@@ -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();

View File

@@ -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

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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 $@

View File

@@ -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

42
arch/riscv/lib/tishift.S Normal file
View File

@@ -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