Merge tag 'riscv/for-v5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Nov 2019 19:27:59 +0000 (11:27 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Nov 2019 19:27:59 +0000 (11:27 -0800)
Pull RISC-V updates from Paul Walmsley:
 "New features:
   - SECCOMP support
   - nommu support
   - SBI-less system support
   - M-Mode support
   - TLB flush optimizations

  Other improvements:
   - Pass the complete RISC-V ISA string supported by the CPU cores to
     userspace, rather than redacting parts of it in the kernel
   - Add platform DMA IP block data to the HiFive Unleashed board DT
     file
   - Add Makefile support for BZ2, LZ4, LZMA, LZO kernel image
     compression formats, in line with other architectures

  Cleanups:
   - Remove unnecessary PTE_PARENT_SIZE macro
   - Standardize include guard naming across arch/riscv"

* tag 'riscv/for-v5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (22 commits)
  riscv: provide a flat image loader
  riscv: add nommu support
  riscv: clear the instruction cache and all registers when booting
  riscv: read the hart ID from mhartid on boot
  riscv: provide native clint access for M-mode
  riscv: dts: add support for PDMA device of HiFive Unleashed Rev A00
  riscv: add support for MMIO access to the timer registers
  riscv: implement remote sfence.i using IPIs
  riscv: cleanup the default power off implementation
  riscv: poison SBI calls for M-mode
  riscv: don't allow selecting SBI based drivers for M-mode
  RISC-V: Add multiple compression image format.
  riscv: clean up the macro format in each header file
  riscv: Use PMD_SIZE to replace PTE_PARENT_SIZE
  riscv: abstract out CSR names for supervisor vs machine mode
  riscv: separate MMIO functions into their own header file
  riscv: enter WFI in default_power_off() if SBI does not shutdown
  RISC-V: Issue a tlb page flush if possible
  RISC-V: Issue a local tlbflush if possible.
  RISC-V: Do not invoke SBI call if cpumask is empty
  ...

74 files changed:
arch/riscv/Kconfig
arch/riscv/Makefile
arch/riscv/boot/Makefile
arch/riscv/boot/dts/sifive/fu540-c000.dtsi
arch/riscv/boot/loader.S [new file with mode: 0644]
arch/riscv/boot/loader.lds.S [new file with mode: 0644]
arch/riscv/configs/nommu_virt_defconfig [new file with mode: 0644]
arch/riscv/include/asm/asm-prototypes.h
arch/riscv/include/asm/cache.h
arch/riscv/include/asm/clint.h [new file with mode: 0644]
arch/riscv/include/asm/csr.h
arch/riscv/include/asm/current.h
arch/riscv/include/asm/elf.h
arch/riscv/include/asm/fixmap.h
arch/riscv/include/asm/ftrace.h
arch/riscv/include/asm/futex.h
arch/riscv/include/asm/hwcap.h
arch/riscv/include/asm/image.h
arch/riscv/include/asm/io.h
arch/riscv/include/asm/irqflags.h
arch/riscv/include/asm/kprobes.h
arch/riscv/include/asm/mmio.h [new file with mode: 0644]
arch/riscv/include/asm/mmiowb.h
arch/riscv/include/asm/mmu.h
arch/riscv/include/asm/page.h
arch/riscv/include/asm/pci.h
arch/riscv/include/asm/pgalloc.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/processor.h
arch/riscv/include/asm/ptrace.h
arch/riscv/include/asm/sbi.h
arch/riscv/include/asm/seccomp.h [new file with mode: 0644]
arch/riscv/include/asm/sparsemem.h
arch/riscv/include/asm/spinlock_types.h
arch/riscv/include/asm/switch_to.h
arch/riscv/include/asm/thread_info.h
arch/riscv/include/asm/timex.h
arch/riscv/include/asm/tlbflush.h
arch/riscv/include/asm/uaccess.h
arch/riscv/include/uapi/asm/elf.h
arch/riscv/include/uapi/asm/hwcap.h
arch/riscv/include/uapi/asm/ucontext.h
arch/riscv/kernel/Makefile
arch/riscv/kernel/asm-offsets.c
arch/riscv/kernel/clint.c [new file with mode: 0644]
arch/riscv/kernel/cpu.c
arch/riscv/kernel/entry.S
arch/riscv/kernel/fpu.S
arch/riscv/kernel/head.S
arch/riscv/kernel/irq.c
arch/riscv/kernel/perf_callchain.c
arch/riscv/kernel/process.c
arch/riscv/kernel/ptrace.c
arch/riscv/kernel/reset.c
arch/riscv/kernel/sbi.c [new file with mode: 0644]
arch/riscv/kernel/setup.c
arch/riscv/kernel/signal.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/smpboot.c
arch/riscv/kernel/traps.c
arch/riscv/lib/Makefile
arch/riscv/lib/uaccess.S
arch/riscv/mm/Makefile
arch/riscv/mm/cacheflush.c
arch/riscv/mm/context.c
arch/riscv/mm/extable.c
arch/riscv/mm/fault.c
arch/riscv/mm/init.c
arch/riscv/mm/tlbflush.c
drivers/clocksource/timer-riscv.c
drivers/irqchip/irq-sifive-plic.c
drivers/tty/hvc/Kconfig
drivers/tty/serial/Kconfig
tools/testing/selftests/seccomp/seccomp_bpf.c

index 75a6c91..9f7f5dc 100644 (file)
@@ -26,14 +26,15 @@ config RISCV
        select GENERIC_IRQ_SHOW
        select GENERIC_PCI_IOMAP
        select GENERIC_SCHED_CLOCK
-       select GENERIC_STRNCPY_FROM_USER
-       select GENERIC_STRNLEN_USER
+       select GENERIC_STRNCPY_FROM_USER if MMU
+       select GENERIC_STRNLEN_USER if MMU
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_ARCH_AUDITSYSCALL
+       select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ASM_MODVERSIONS
        select HAVE_MEMBLOCK_NODE_MAP
-       select HAVE_DMA_CONTIGUOUS
+       select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_PERF_EVENTS
        select HAVE_PERF_REGS
@@ -50,6 +51,7 @@ config RISCV
        select PCI_DOMAINS_GENERIC if PCI
        select PCI_MSI if PCI
        select RISCV_TIMER
+       select UACCESS_MEMCPY if !MMU
        select GENERIC_IRQ_MULTI_HANDLER
        select GENERIC_ARCH_TOPOLOGY if SMP
        select ARCH_HAS_PTE_SPECIAL
@@ -60,7 +62,7 @@ config RISCV
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
        select SPARSEMEM_STATIC if 32BIT
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
-       select HAVE_ARCH_MMAP_RND_BITS
+       select HAVE_ARCH_MMAP_RND_BITS if MMU
 
 config ARCH_MMAP_RND_BITS_MIN
        default 18 if 64BIT
@@ -72,8 +74,23 @@ config ARCH_MMAP_RND_BITS_MAX
        default 24 if 64BIT # SV39 based
        default 17
 
+# set if we run in machine mode, cleared if we run in supervisor mode
+config RISCV_M_MODE
+       bool
+       default !MMU
+
+# set if we are running in S-mode and can use SBI calls
+config RISCV_SBI
+       bool
+       depends on !RISCV_M_MODE
+       default y
+
 config MMU
-       def_bool y
+       bool "MMU-based Paged Memory Management Support"
+       default y
+       help
+         Select if you want MMU-based virtualised addressing space
+         support by paged memory management. If unsure, say 'Y'.
 
 config ZONE_DMA32
        bool
@@ -92,6 +109,7 @@ config PA_BITS
 config PAGE_OFFSET
        hex
        default 0xC0000000 if 32BIT && MAXPHYSMEM_2GB
+       default 0x80000000 if 64BIT && !MMU
        default 0xffffffff80000000 if 64BIT && MAXPHYSMEM_2GB
        default 0xffffffe000000000 if 64BIT && MAXPHYSMEM_128GB
 
@@ -135,7 +153,7 @@ config GENERIC_HWEIGHT
        def_bool y
 
 config FIX_EARLYCON_MEM
-       def_bool y
+       def_bool CONFIG_MMU
 
 config PGTABLE_LEVELS
        int
@@ -160,6 +178,7 @@ config ARCH_RV32I
        select GENERIC_LIB_ASHRDI3
        select GENERIC_LIB_LSHRDI3
        select GENERIC_LIB_UCMPDI2
+       select MMU
 
 config ARCH_RV64I
        bool "RV64I"
@@ -168,9 +187,9 @@ config ARCH_RV64I
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FTRACE_MCOUNT_RECORD
-       select HAVE_DYNAMIC_FTRACE
-       select HAVE_DYNAMIC_FTRACE_WITH_REGS
-       select SWIOTLB
+       select HAVE_DYNAMIC_FTRACE if MMU
+       select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
+       select SWIOTLB if MMU
 
 endchoice
 
@@ -272,6 +291,19 @@ menu "Kernel features"
 
 source "kernel/Kconfig.hz"
 
+config SECCOMP
+       bool "Enable seccomp to safely compute untrusted bytecode"
+       help
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
 endmenu
 
 menu "Boot options"
index f5e9142..b9009a2 100644 (file)
@@ -83,13 +83,18 @@ PHONY += vdso_install
 vdso_install:
        $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
 
-all: Image.gz
+ifeq ($(CONFIG_RISCV_M_MODE),y)
+KBUILD_IMAGE := $(boot)/loader
+else
+KBUILD_IMAGE := $(boot)/Image.gz
+endif
+BOOT_TARGETS := Image Image.gz loader
 
-Image: vmlinux
-       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+all:   $(notdir $(KBUILD_IMAGE))
 
-Image.%: Image
+$(BOOT_TARGETS): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+       @$(kecho) '  Kernel: $(boot)/$@ is ready'
 
 zinstall install:
        $(Q)$(MAKE) $(build)=$(boot) $@
index 0990a9f..a474f98 100644 (file)
@@ -16,7 +16,7 @@
 
 OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
 
-targets := Image
+targets := Image loader
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
@@ -24,6 +24,23 @@ $(obj)/Image: vmlinux FORCE
 $(obj)/Image.gz: $(obj)/Image FORCE
        $(call if_changed,gzip)
 
+loader.o: $(src)/loader.S $(obj)/Image
+
+$(obj)/loader: $(obj)/loader.o $(obj)/Image $(obj)/loader.lds FORCE
+       $(Q)$(LD) -T $(obj)/loader.lds -o $@ $(obj)/loader.o
+
+$(obj)/Image.bz2: $(obj)/Image FORCE
+       $(call if_changed,bzip2)
+
+$(obj)/Image.lz4: $(obj)/Image FORCE
+       $(call if_changed,lz4)
+
+$(obj)/Image.lzma: $(obj)/Image FORCE
+       $(call if_changed,lzma)
+
+$(obj)/Image.lzo: $(obj)/Image FORCE
+       $(call if_changed,lzo)
+
 install:
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image System.map "$(INSTALL_PATH)"
index afa43c7..70a1891 100644 (file)
                        clocks = <&prci PRCI_CLK_TLCLK>;
                        status = "disabled";
                };
+               dma: dma@3000000 {
+                       compatible = "sifive,fu540-c000-pdma";
+                       reg = <0x0 0x3000000 0x0 0x8000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <23 24 25 26 27 28 29 30>;
+                       #dma-cells = <1>;
+               };
                uart1: serial@10011000 {
                        compatible = "sifive,fu540-c000-uart", "sifive,uart0";
                        reg = <0x0 0x10011000 0x0 0x1000>;
diff --git a/arch/riscv/boot/loader.S b/arch/riscv/boot/loader.S
new file mode 100644 (file)
index 0000000..dcf88cf
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+       .align 4
+       .section .payload, "ax", %progbits
+       .globl _start
+_start:
+       .incbin "arch/riscv/boot/Image"
+
diff --git a/arch/riscv/boot/loader.lds.S b/arch/riscv/boot/loader.lds.S
new file mode 100644 (file)
index 0000000..47a5003
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <asm/page.h>
+
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+
+SECTIONS
+{
+       . = PAGE_OFFSET;
+
+       .payload : {
+               *(.payload)
+               . = ALIGN(8);
+       }
+}
diff --git a/arch/riscv/configs/nommu_virt_defconfig b/arch/riscv/configs/nommu_virt_defconfig
new file mode 100644 (file)
index 0000000..cf74e17
--- /dev/null
@@ -0,0 +1,78 @@
+# CONFIG_CPU_ISOLATION is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+# CONFIG_SYSFS_SYSCALL is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_IO_URING is not set
+# CONFIG_ADVISE_SYSCALLS is not set
+# CONFIG_MEMBARRIER is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+# CONFIG_SLAB_MERGE_DEFAULT is not set
+# CONFIG_MMU is not set
+CONFIG_MAXPHYSMEM_2GB=y
+CONFIG_SMP=y
+CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
+CONFIG_CMDLINE_FORCE=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
+CONFIG_BINFMT_FLAT=y
+# CONFIG_COREDUMP is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_VIRTIO_BLK=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_LDISC_AUTOLOAD is not set
+# CONFIG_DEVMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_LCD_CLASS_DEVICE is not set
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+CONFIG_SIFIVE_PLIC=y
+# CONFIG_VALIDATE_FS_PARSER is not set
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_LSM="[]"
+CONFIG_PRINTK_TIME=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
index c9fecd1..dd62b69 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _ASM_RISCV_PROTOTYPES_H
+#define _ASM_RISCV_PROTOTYPES_H
 
 #include <linux/ftrace.h>
 #include <asm-generic/asm-prototypes.h>
index bfd523e..9b58b10 100644 (file)
 
 #define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
 
+/*
+ * RISC-V requires the stack pointer to be 16-byte aligned, so ensure that
+ * the flat loader aligns it accordingly.
+ */
+#ifndef CONFIG_MMU
+#define ARCH_SLAB_MINALIGN     16
+#endif
+
 #endif /* _ASM_RISCV_CACHE_H */
diff --git a/arch/riscv/include/asm/clint.h b/arch/riscv/include/asm/clint.h
new file mode 100644 (file)
index 0000000..6eaa2ee
--- /dev/null
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_CLINT_H
+#define _ASM_RISCV_CLINT_H 1
+
+#include <linux/io.h>
+#include <linux/smp.h>
+
+#ifdef CONFIG_RISCV_M_MODE
+extern u32 __iomem *clint_ipi_base;
+
+void clint_init_boot_cpu(void);
+
+static inline void clint_send_ipi_single(unsigned long hartid)
+{
+       writel(1, clint_ipi_base + hartid);
+}
+
+static inline void clint_send_ipi_mask(const struct cpumask *hartid_mask)
+{
+       int hartid;
+
+       for_each_cpu(hartid, hartid_mask)
+               clint_send_ipi_single(hartid);
+}
+
+static inline void clint_clear_ipi(unsigned long hartid)
+{
+       writel(0, clint_ipi_base + hartid);
+}
+#else /* CONFIG_RISCV_M_MODE */
+#define clint_init_boot_cpu()  do { } while (0)
+
+/* stubs to for code is only reachable under IS_ENABLED(CONFIG_RISCV_M_MODE): */
+void clint_send_ipi_single(unsigned long hartid);
+void clint_send_ipi_mask(const struct cpumask *hartid_mask);
+void clint_clear_ipi(unsigned long hartid);
+#endif /* CONFIG_RISCV_M_MODE */
+
+#endif /* _ASM_RISCV_CLINT_H */
index a18923f..0a62d2d 100644 (file)
 
 /* Status register flags */
 #define SR_SIE         _AC(0x00000002, UL) /* Supervisor Interrupt Enable */
+#define SR_MIE         _AC(0x00000008, UL) /* Machine Interrupt Enable */
 #define SR_SPIE                _AC(0x00000020, UL) /* Previous Supervisor IE */
+#define SR_MPIE                _AC(0x00000080, UL) /* Previous Machine IE */
 #define SR_SPP         _AC(0x00000100, UL) /* Previously Supervisor */
+#define SR_MPP         _AC(0x00001800, UL) /* Previously Machine */
 #define SR_SUM         _AC(0x00040000, UL) /* Supervisor User Memory Access */
 
 #define SR_FS          _AC(0x00006000, UL) /* Floating-point Status */
 #define SATP_MODE      SATP_MODE_39
 #endif
 
-/* SCAUSE */
-#define SCAUSE_IRQ_FLAG                (_AC(1, UL) << (__riscv_xlen - 1))
+/* Exception cause high bit - is an interrupt if set */
+#define CAUSE_IRQ_FLAG         (_AC(1, UL) << (__riscv_xlen - 1))
 
+/* Interrupt causes (minus the high bit) */
 #define IRQ_U_SOFT             0
 #define IRQ_S_SOFT             1
 #define IRQ_M_SOFT             3
@@ -57,6 +61,7 @@
 #define IRQ_S_EXT              9
 #define IRQ_M_EXT              11
 
+/* Exception causes */
 #define EXC_INST_MISALIGNED    0
 #define EXC_INST_ACCESS                1
 #define EXC_BREAKPOINT         3
 #define EXC_LOAD_PAGE_FAULT    13
 #define EXC_STORE_PAGE_FAULT   15
 
-/* SIE (Interrupt Enable) and SIP (Interrupt Pending) flags */
-#define SIE_SSIE               (_AC(0x1, UL) << IRQ_S_SOFT)
-#define SIE_STIE               (_AC(0x1, UL) << IRQ_S_TIMER)
-#define SIE_SEIE               (_AC(0x1, UL) << IRQ_S_EXT)
-
+/* symbolic CSR names: */
 #define CSR_CYCLE              0xc00
 #define CSR_TIME               0xc01
 #define CSR_INSTRET            0xc02
+#define CSR_CYCLEH             0xc80
+#define CSR_TIMEH              0xc81
+#define CSR_INSTRETH           0xc82
+
 #define CSR_SSTATUS            0x100
 #define CSR_SIE                        0x104
 #define CSR_STVEC              0x105
 #define CSR_STVAL              0x143
 #define CSR_SIP                        0x144
 #define CSR_SATP               0x180
-#define CSR_CYCLEH             0xc80
-#define CSR_TIMEH              0xc81
-#define CSR_INSTRETH           0xc82
+
+#define CSR_MSTATUS            0x300
+#define CSR_MISA               0x301
+#define CSR_MIE                        0x304
+#define CSR_MTVEC              0x305
+#define CSR_MSCRATCH           0x340
+#define CSR_MEPC               0x341
+#define CSR_MCAUSE             0x342
+#define CSR_MTVAL              0x343
+#define CSR_MIP                        0x344
+#define CSR_MHARTID            0xf14
+
+#ifdef CONFIG_RISCV_M_MODE
+# define CSR_STATUS    CSR_MSTATUS
+# define CSR_IE                CSR_MIE
+# define CSR_TVEC      CSR_MTVEC
+# define CSR_SCRATCH   CSR_MSCRATCH
+# define CSR_EPC       CSR_MEPC
+# define CSR_CAUSE     CSR_MCAUSE
+# define CSR_TVAL      CSR_MTVAL
+# define CSR_IP                CSR_MIP
+
+# define SR_IE         SR_MIE
+# define SR_PIE                SR_MPIE
+# define SR_PP         SR_MPP
+
+# define IRQ_SOFT      IRQ_M_SOFT
+# define IRQ_TIMER     IRQ_M_TIMER
+# define IRQ_EXT       IRQ_M_EXT
+#else /* CONFIG_RISCV_M_MODE */
+# define CSR_STATUS    CSR_SSTATUS
+# define CSR_IE                CSR_SIE
+# define CSR_TVEC      CSR_STVEC
+# define CSR_SCRATCH   CSR_SSCRATCH
+# define CSR_EPC       CSR_SEPC
+# define CSR_CAUSE     CSR_SCAUSE
+# define CSR_TVAL      CSR_STVAL
+# define CSR_IP                CSR_SIP
+
+# define SR_IE         SR_SIE
+# define SR_PIE                SR_SPIE
+# define SR_PP         SR_SPP
+
+# define IRQ_SOFT      IRQ_S_SOFT
+# define IRQ_TIMER     IRQ_S_TIMER
+# define IRQ_EXT       IRQ_S_EXT
+#endif /* CONFIG_RISCV_M_MODE */
+
+/* IE/IP (Supervisor/Machine Interrupt Enable/Pending) flags */
+#define IE_SIE         (_AC(0x1, UL) << IRQ_SOFT)
+#define IE_TIE         (_AC(0x1, UL) << IRQ_TIMER)
+#define IE_EIE         (_AC(0x1, UL) << IRQ_EXT)
 
 #ifndef __ASSEMBLY__
 
index 44dcf7f..dd973ef 100644 (file)
@@ -7,8 +7,8 @@
  */
 
 
-#ifndef __ASM_CURRENT_H
-#define __ASM_CURRENT_H
+#ifndef _ASM_RISCV_CURRENT_H
+#define _ASM_RISCV_CURRENT_H
 
 #include <linux/bug.h>
 #include <linux/compiler.h>
@@ -34,4 +34,4 @@ static __always_inline struct task_struct *get_current(void)
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* __ASM_CURRENT_H */
+#endif /* _ASM_RISCV_CURRENT_H */
index ef04084..d83a4ef 100644 (file)
@@ -56,16 +56,16 @@ extern unsigned long elf_hwcap;
  */
 #define ELF_PLATFORM   (NULL)
 
+#ifdef CONFIG_MMU
 #define ARCH_DLINFO                                            \
 do {                                                           \
        NEW_AUX_ENT(AT_SYSINFO_EHDR,                            \
                (elf_addr_t)current->mm->context.vdso);         \
 } while (0)
-
-
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
        int uses_interp);
+#endif /* CONFIG_MMU */
 
 #endif /* _ASM_RISCV_ELF_H */
index 161f28d..42d2c42 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_MMU
 /*
  * Here we define all the compile-time 'special' virtual addresses.
  * The point is to have a constant address at compile time, but to
@@ -42,4 +43,5 @@ extern void __set_fixmap(enum fixed_addresses idx,
 
 #include <asm-generic/fixmap.h>
 
+#endif /* CONFIG_MMU */
 #endif /* _ASM_RISCV_FIXMAP_H */
index c6dcc52..ace8a6e 100644 (file)
@@ -1,6 +1,9 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Copyright (C) 2017 Andes Technology Corporation */
 
+#ifndef _ASM_RISCV_FTRACE_H
+#define _ASM_RISCV_FTRACE_H
+
 /*
  * The graph frame test is not possible if CONFIG_FRAME_POINTER is not enabled.
  * Check arch/riscv/kernel/mcount.S for detail.
@@ -64,3 +67,5 @@ do {                                                                  \
  */
 #define MCOUNT_INSN_SIZE 8
 #endif
+
+#endif /* _ASM_RISCV_FTRACE_H */
index 4ad6409..fdfaf7f 100644 (file)
@@ -4,14 +4,20 @@
  * Copyright (c) 2018  Jim Wilson (jimw@sifive.com)
  */
 
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_RISCV_FUTEX_H
+#define _ASM_RISCV_FUTEX_H
 
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 #include <asm/asm.h>
 
+/* We don't even really need the extable code, but for now keep it simple */
+#ifndef CONFIG_MMU
+#define __enable_user_access()         do { } while (0)
+#define __disable_user_access()                do { } while (0)
+#endif
+
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)     \
 {                                                              \
        uintptr_t tmp;                                          \
@@ -112,4 +118,4 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
        return ret;
 }
 
-#endif /* _ASM_FUTEX_H */
+#endif /* _ASM_RISCV_FUTEX_H */
index 7ecb7c6..1bb0cd0 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (C) 2012 ARM Ltd.
  * Copyright (C) 2017 SiFive
  */
-#ifndef __ASM_HWCAP_H
-#define __ASM_HWCAP_H
+#ifndef _ASM_RISCV_HWCAP_H
+#define _ASM_RISCV_HWCAP_H
 
 #include <uapi/asm/hwcap.h>
 
@@ -23,4 +23,5 @@ enum {
 
 extern unsigned long elf_hwcap;
 #endif
-#endif
+
+#endif /* _ASM_RISCV_HWCAP_H */
index 344db52..7b0f92b 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
-#ifndef __ASM_IMAGE_H
-#define __ASM_IMAGE_H
+#ifndef _ASM_RISCV_IMAGE_H
+#define _ASM_RISCV_IMAGE_H
 
 #define RISCV_IMAGE_MAGIC      "RISCV\0\0\0"
 #define RISCV_IMAGE_MAGIC2     "RSC\x05"
@@ -62,4 +62,4 @@ struct riscv_image_header {
        u32 res4;
 };
 #endif /* __ASSEMBLY__ */
-#endif /* __ASM_IMAGE_H */
+#endif /* _ASM_RISCV_IMAGE_H */
index 3ba4d93..0f47720 100644 (file)
 #include <asm/mmiowb.h>
 #include <asm/pgtable.h>
 
-extern void __iomem *ioremap(phys_addr_t offset, unsigned long size);
-
-/*
- * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't
- * change the properties of memory regions.  This should be fixed by the
- * upcoming platform spec.
- */
-#define ioremap_nocache(addr, size) ioremap((addr), (size))
-#define ioremap_wc(addr, size) ioremap((addr), (size))
-#define ioremap_wt(addr, size) ioremap((addr), (size))
-
-extern void iounmap(volatile void __iomem *addr);
-
-/* Generic IO read/write.  These perform native-endian accesses. */
-#define __raw_writeb __raw_writeb
-static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
-{
-       asm volatile("sb %0, 0(%1)" : : "r" (val), "r" (addr));
-}
-
-#define __raw_writew __raw_writew
-static inline void __raw_writew(u16 val, volatile void __iomem *addr)
-{
-       asm volatile("sh %0, 0(%1)" : : "r" (val), "r" (addr));
-}
-
-#define __raw_writel __raw_writel
-static inline void __raw_writel(u32 val, volatile void __iomem *addr)
-{
-       asm volatile("sw %0, 0(%1)" : : "r" (val), "r" (addr));
-}
-
-#ifdef CONFIG_64BIT
-#define __raw_writeq __raw_writeq
-static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
-{
-       asm volatile("sd %0, 0(%1)" : : "r" (val), "r" (addr));
-}
-#endif
-
-#define __raw_readb __raw_readb
-static inline u8 __raw_readb(const volatile void __iomem *addr)
-{
-       u8 val;
-
-       asm volatile("lb %0, 0(%1)" : "=r" (val) : "r" (addr));
-       return val;
-}
-
-#define __raw_readw __raw_readw
-static inline u16 __raw_readw(const volatile void __iomem *addr)
-{
-       u16 val;
-
-       asm volatile("lh %0, 0(%1)" : "=r" (val) : "r" (addr));
-       return val;
-}
-
-#define __raw_readl __raw_readl
-static inline u32 __raw_readl(const volatile void __iomem *addr)
-{
-       u32 val;
-
-       asm volatile("lw %0, 0(%1)" : "=r" (val) : "r" (addr));
-       return val;
-}
-
-#ifdef CONFIG_64BIT
-#define __raw_readq __raw_readq
-static inline u64 __raw_readq(const volatile void __iomem *addr)
-{
-       u64 val;
-
-       asm volatile("ld %0, 0(%1)" : "=r" (val) : "r" (addr));
-       return val;
-}
-#endif
-
 /*
- * Unordered I/O memory access primitives.  These are even more relaxed than
- * the relaxed versions, as they don't even order accesses between successive
- * operations to the I/O regions.
+ * MMIO access functions are separated out to break dependency cycles
+ * when using {read,write}* fns in low-level headers
  */
-#define readb_cpu(c)           ({ u8  __r = __raw_readb(c); __r; })
-#define readw_cpu(c)           ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
-#define readl_cpu(c)           ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
-
-#define writeb_cpu(v,c)                ((void)__raw_writeb((v),(c)))
-#define writew_cpu(v,c)                ((void)__raw_writew((__force u16)cpu_to_le16(v),(c)))
-#define writel_cpu(v,c)                ((void)__raw_writel((__force u32)cpu_to_le32(v),(c)))
-
-#ifdef CONFIG_64BIT
-#define readq_cpu(c)           ({ u64 __r = le64_to_cpu((__force __le64)__raw_readq(c)); __r; })
-#define writeq_cpu(v,c)                ((void)__raw_writeq((__force u64)cpu_to_le64(v),(c)))
-#endif
-
-/*
- * Relaxed I/O memory access primitives. These follow the Device memory
- * ordering rules but do not guarantee any ordering relative to Normal memory
- * accesses.  These are defined to order the indicated access (either a read or
- * write) with all other I/O memory accesses. Since the platform specification
- * defines that all I/O regions are strongly ordered on channel 2, no explicit
- * fences are required to enforce this ordering.
- */
-/* FIXME: These are now the same as asm-generic */
-#define __io_rbr()             do {} while (0)
-#define __io_rar()             do {} while (0)
-#define __io_rbw()             do {} while (0)
-#define __io_raw()             do {} while (0)
-
-#define readb_relaxed(c)       ({ u8  __v; __io_rbr(); __v = readb_cpu(c); __io_rar(); __v; })
-#define readw_relaxed(c)       ({ u16 __v; __io_rbr(); __v = readw_cpu(c); __io_rar(); __v; })
-#define readl_relaxed(c)       ({ u32 __v; __io_rbr(); __v = readl_cpu(c); __io_rar(); __v; })
-
-#define writeb_relaxed(v,c)    ({ __io_rbw(); writeb_cpu((v),(c)); __io_raw(); })
-#define writew_relaxed(v,c)    ({ __io_rbw(); writew_cpu((v),(c)); __io_raw(); })
-#define writel_relaxed(v,c)    ({ __io_rbw(); writel_cpu((v),(c)); __io_raw(); })
-
-#ifdef CONFIG_64BIT
-#define readq_relaxed(c)       ({ u64 __v; __io_rbr(); __v = readq_cpu(c); __io_rar(); __v; })
-#define writeq_relaxed(v,c)    ({ __io_rbw(); writeq_cpu((v),(c)); __io_raw(); })
-#endif
-
-/*
- * I/O memory access primitives. Reads are ordered relative to any
- * following Normal memory access. Writes are ordered relative to any prior
- * Normal memory access.  The memory barriers here are necessary as RISC-V
- * doesn't define any ordering between the memory space and the I/O space.
- */
-#define __io_br()      do {} while (0)
-#define __io_ar(v)     __asm__ __volatile__ ("fence i,r" : : : "memory");
-#define __io_bw()      __asm__ __volatile__ ("fence w,o" : : : "memory");
-#define __io_aw()      mmiowb_set_pending()
-
-#define readb(c)       ({ u8  __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; })
-#define readw(c)       ({ u16 __v; __io_br(); __v = readw_cpu(c); __io_ar(__v); __v; })
-#define readl(c)       ({ u32 __v; __io_br(); __v = readl_cpu(c); __io_ar(__v); __v; })
-
-#define writeb(v,c)    ({ __io_bw(); writeb_cpu((v),(c)); __io_aw(); })
-#define writew(v,c)    ({ __io_bw(); writew_cpu((v),(c)); __io_aw(); })
-#define writel(v,c)    ({ __io_bw(); writel_cpu((v),(c)); __io_aw(); })
-
-#ifdef CONFIG_64BIT
-#define readq(c)       ({ u64 __v; __io_br(); __v = readq_cpu(c); __io_ar(__v); __v; })
-#define writeq(v,c)    ({ __io_bw(); writeq_cpu((v),(c)); __io_aw(); })
-#endif
+#include <asm/mmio.h>
 
 /*
  *  I/O port access constants.
  */
+#ifdef CONFIG_MMU
 #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
 #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
+#endif /* CONFIG_MMU */
 
 /*
  * Emulation routines for the port-mapped IO space used by some PCI drivers.
index e70f647..08d4d6a 100644 (file)
 /* read interrupt enabled status */
 static inline unsigned long arch_local_save_flags(void)
 {
-       return csr_read(CSR_SSTATUS);
+       return csr_read(CSR_STATUS);
 }
 
 /* unconditionally enable interrupts */
 static inline void arch_local_irq_enable(void)
 {
-       csr_set(CSR_SSTATUS, SR_SIE);
+       csr_set(CSR_STATUS, SR_IE);
 }
 
 /* unconditionally disable interrupts */
 static inline void arch_local_irq_disable(void)
 {
-       csr_clear(CSR_SSTATUS, SR_SIE);
+       csr_clear(CSR_STATUS, SR_IE);
 }
 
 /* get status and disable interrupts */
 static inline unsigned long arch_local_irq_save(void)
 {
-       return csr_read_clear(CSR_SSTATUS, SR_SIE);
+       return csr_read_clear(CSR_STATUS, SR_IE);
 }
 
 /* test flags */
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-       return !(flags & SR_SIE);
+       return !(flags & SR_IE);
 }
 
 /* test hardware interrupt enable bit */
@@ -49,7 +49,7 @@ static inline int arch_irqs_disabled(void)
 /* set interrupt enabled status */
 static inline void arch_local_irq_restore(unsigned long flags)
 {
-       csr_set(CSR_SSTATUS, flags & SR_SIE);
+       csr_set(CSR_STATUS, flags & SR_IE);
 }
 
 #endif /* _ASM_RISCV_IRQFLAGS_H */
index 96e30ef..56a98ea 100644 (file)
@@ -6,9 +6,9 @@
  * Copyright (C) 2017 SiFive
  */
 
-#ifndef _RISCV_KPROBES_H
-#define _RISCV_KPROBES_H
+#ifndef _ASM_RISCV_KPROBES_H
+#define _ASM_RISCV_KPROBES_H
 
 #include <asm-generic/kprobes.h>
 
-#endif /* _RISCV_KPROBES_H */
+#endif /* _ASM_RISCV_KPROBES_H */
diff --git a/arch/riscv/include/asm/mmio.h b/arch/riscv/include/asm/mmio.h
new file mode 100644 (file)
index 0000000..a297a83
--- /dev/null
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * {read,write}{b,w,l,q} based on arch/arm64/include/asm/io.h
+ *   which was based on arch/arm/include/io.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2014 Regents of the University of California
+ */
+
+#ifndef _ASM_RISCV_MMIO_H
+#define _ASM_RISCV_MMIO_H
+
+#include <linux/types.h>
+#include <asm/mmiowb.h>
+
+#ifdef CONFIG_MMU
+void __iomem *ioremap(phys_addr_t offset, unsigned long size);
+
+/*
+ * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't
+ * change the properties of memory regions.  This should be fixed by the
+ * upcoming platform spec.
+ */
+#define ioremap_nocache(addr, size) ioremap((addr), (size))
+#define ioremap_wc(addr, size) ioremap((addr), (size))
+#define ioremap_wt(addr, size) ioremap((addr), (size))
+
+void iounmap(volatile void __iomem *addr);
+#else
+#define pgprot_noncached(x)    (x)
+#endif /* CONFIG_MMU */
+
+/* Generic IO read/write.  These perform native-endian accesses. */
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+       asm volatile("sb %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+       asm volatile("sh %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+       asm volatile("sw %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+
+#ifdef CONFIG_64BIT
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+{
+       asm volatile("sd %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+#endif
+
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+       u8 val;
+
+       asm volatile("lb %0, 0(%1)" : "=r" (val) : "r" (addr));
+       return val;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+       u16 val;
+
+       asm volatile("lh %0, 0(%1)" : "=r" (val) : "r" (addr));
+       return val;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+       u32 val;
+
+       asm volatile("lw %0, 0(%1)" : "=r" (val) : "r" (addr));
+       return val;
+}
+
+#ifdef CONFIG_64BIT
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+       u64 val;
+
+       asm volatile("ld %0, 0(%1)" : "=r" (val) : "r" (addr));
+       return val;
+}
+#endif
+
+/*
+ * Unordered I/O memory access primitives.  These are even more relaxed than
+ * the relaxed versions, as they don't even order accesses between successive
+ * operations to the I/O regions.
+ */
+#define readb_cpu(c)           ({ u8  __r = __raw_readb(c); __r; })
+#define readw_cpu(c)           ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
+#define readl_cpu(c)           ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
+
+#define writeb_cpu(v, c)       ((void)__raw_writeb((v), (c)))
+#define writew_cpu(v, c)       ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
+#define writel_cpu(v, c)       ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
+
+#ifdef CONFIG_64BIT
+#define readq_cpu(c)           ({ u64 __r = le64_to_cpu((__force __le64)__raw_readq(c)); __r; })
+#define writeq_cpu(v, c)       ((void)__raw_writeq((__force u64)cpu_to_le64(v), (c)))
+#endif
+
+/*
+ * Relaxed I/O memory access primitives. These follow the Device memory
+ * ordering rules but do not guarantee any ordering relative to Normal memory
+ * accesses.  These are defined to order the indicated access (either a read or
+ * write) with all other I/O memory accesses. Since the platform specification
+ * defines that all I/O regions are strongly ordered on channel 2, no explicit
+ * fences are required to enforce this ordering.
+ */
+/* FIXME: These are now the same as asm-generic */
+#define __io_rbr()             do {} while (0)
+#define __io_rar()             do {} while (0)
+#define __io_rbw()             do {} while (0)
+#define __io_raw()             do {} while (0)
+
+#define readb_relaxed(c)       ({ u8  __v; __io_rbr(); __v = readb_cpu(c); __io_rar(); __v; })
+#define readw_relaxed(c)       ({ u16 __v; __io_rbr(); __v = readw_cpu(c); __io_rar(); __v; })
+#define readl_relaxed(c)       ({ u32 __v; __io_rbr(); __v = readl_cpu(c); __io_rar(); __v; })
+
+#define writeb_relaxed(v, c)   ({ __io_rbw(); writeb_cpu((v), (c)); __io_raw(); })
+#define writew_relaxed(v, c)   ({ __io_rbw(); writew_cpu((v), (c)); __io_raw(); })
+#define writel_relaxed(v, c)   ({ __io_rbw(); writel_cpu((v), (c)); __io_raw(); })
+
+#ifdef CONFIG_64BIT
+#define readq_relaxed(c)       ({ u64 __v; __io_rbr(); __v = readq_cpu(c); __io_rar(); __v; })
+#define writeq_relaxed(v, c)   ({ __io_rbw(); writeq_cpu((v), (c)); __io_raw(); })
+#endif
+
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.  The memory barriers here are necessary as RISC-V
+ * doesn't define any ordering between the memory space and the I/O space.
+ */
+#define __io_br()      do {} while (0)
+#define __io_ar(v)     __asm__ __volatile__ ("fence i,r" : : : "memory")
+#define __io_bw()      __asm__ __volatile__ ("fence w,o" : : : "memory")
+#define __io_aw()      mmiowb_set_pending()
+
+#define readb(c)       ({ u8  __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; })
+#define readw(c)       ({ u16 __v; __io_br(); __v = readw_cpu(c); __io_ar(__v); __v; })
+#define readl(c)       ({ u32 __v; __io_br(); __v = readl_cpu(c); __io_ar(__v); __v; })
+
+#define writeb(v, c)   ({ __io_bw(); writeb_cpu((v), (c)); __io_aw(); })
+#define writew(v, c)   ({ __io_bw(); writew_cpu((v), (c)); __io_aw(); })
+#define writel(v, c)   ({ __io_bw(); writel_cpu((v), (c)); __io_aw(); })
+
+#ifdef CONFIG_64BIT
+#define readq(c)       ({ u64 __v; __io_br(); __v = readq_cpu(c); __io_ar(__v); __v; })
+#define writeq(v, c)   ({ __io_bw(); writeq_cpu((v), (c)); __io_aw(); })
+#endif
+
+#endif /* _ASM_RISCV_MMIO_H */
index 5d7e3a2..bb4091f 100644 (file)
@@ -11,4 +11,4 @@
 
 #include <asm-generic/mmiowb.h>
 
-#endif /* ASM_RISCV_MMIOWB_H */
+#endif /* _ASM_RISCV_MMIOWB_H */
index 151476f..967eacb 100644 (file)
@@ -10,6 +10,9 @@
 #ifndef __ASSEMBLY__
 
 typedef struct {
+#ifndef CONFIG_MMU
+       unsigned long   end_brk;
+#endif
        void *vdso;
 #ifdef CONFIG_SMP
        /* A local icache flush is needed before user execution can resume. */
index 3db261c..ac69924 100644 (file)
@@ -88,8 +88,14 @@ typedef struct page *pgtable_t;
 #define PTE_FMT "%08lx"
 #endif
 
+#ifdef CONFIG_MMU
 extern unsigned long va_pa_offset;
 extern unsigned long pfn_base;
+#define ARCH_PFN_OFFSET                (pfn_base)
+#else
+#define va_pa_offset           0
+#define ARCH_PFN_OFFSET                (PAGE_OFFSET >> PAGE_SHIFT)
+#endif /* CONFIG_MMU */
 
 extern unsigned long max_low_pfn;
 extern unsigned long min_low_pfn;
@@ -112,11 +118,9 @@ extern unsigned long min_low_pfn;
 
 #ifdef CONFIG_FLATMEM
 #define pfn_valid(pfn) \
-       (((pfn) >= pfn_base) && (((pfn)-pfn_base) < max_mapnr))
+       (((pfn) >= ARCH_PFN_OFFSET) && (((pfn) - ARCH_PFN_OFFSET) < max_mapnr))
 #endif
 
-#define ARCH_PFN_OFFSET                (pfn_base)
-
 #endif /* __ASSEMBLY__ */
 
 #define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr)))
index 5ac8daa..1c473a1 100644 (file)
@@ -3,8 +3,8 @@
  * Copyright (C) 2016 SiFive
  */
 
-#ifndef __ASM_RISCV_PCI_H
-#define __ASM_RISCV_PCI_H
+#ifndef _ASM_RISCV_PCI_H
+#define _ASM_RISCV_PCI_H
 
 #include <linux/types.h>
 #include <linux/slab.h>
@@ -34,4 +34,4 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif  /* CONFIG_PCI */
 
-#endif  /* __ASM_PCI_H */
+#endif  /* _ASM_RISCV_PCI_H */
index d59ea92..3f601ee 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <asm/tlb.h>
 
+#ifdef CONFIG_MMU
 #include <asm-generic/pgalloc.h>       /* for pte_{alloc,free}_one */
 
 static inline void pmd_populate_kernel(struct mm_struct *mm,
@@ -81,5 +82,6 @@ do {                                    \
        pgtable_pte_page_dtor(pte);     \
        tlb_remove_page((tlb), pte);    \
 } while (0)
+#endif /* CONFIG_MMU */
 
 #endif /* _ASM_RISCV_PGALLOC_H */
index d322101..beb5f08 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/pgtable-32.h>
 #endif /* CONFIG_64BIT */
 
+#ifdef CONFIG_MMU
 /* Number of entries in the page global directory */
 #define PTRS_PER_PGD    (PAGE_SIZE / sizeof(pgd_t))
 /* Number of entries in the page table */
@@ -32,7 +33,6 @@
 
 /* Number of PGD entries that a user-mode program can use */
 #define USER_PTRS_PER_PGD   (TASK_SIZE / PGDIR_SIZE)
-#define FIRST_USER_ADDRESS  0
 
 /* Page protection bits */
 #define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER)
@@ -84,42 +84,6 @@ extern pgd_t swapper_pg_dir[];
 #define __S110 PAGE_SHARED_EXEC
 #define __S111 PAGE_SHARED_EXEC
 
-#define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
-#define VMALLOC_END      (PAGE_OFFSET - 1)
-#define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
-#define PCI_IO_SIZE      SZ_16M
-
-/*
- * Roughly size the vmemmap space to be large enough to fit enough
- * struct pages to map half the virtual address space. Then
- * position vmemmap directly below the VMALLOC region.
- */
-#define VMEMMAP_SHIFT \
-       (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
-#define VMEMMAP_SIZE   BIT(VMEMMAP_SHIFT)
-#define VMEMMAP_END    (VMALLOC_START - 1)
-#define VMEMMAP_START  (VMALLOC_START - VMEMMAP_SIZE)
-
-#define vmemmap                ((struct page *)VMEMMAP_START)
-
-#define PCI_IO_END       VMEMMAP_START
-#define PCI_IO_START     (PCI_IO_END - PCI_IO_SIZE)
-#define FIXADDR_TOP      PCI_IO_START
-
-#ifdef CONFIG_64BIT
-#define FIXADDR_SIZE     PMD_SIZE
-#else
-#define FIXADDR_SIZE     PGDIR_SIZE
-#endif
-#define FIXADDR_START    (FIXADDR_TOP - FIXADDR_SIZE)
-
-/*
- * ZERO_PAGE is a global shared page that is always zero,
- * used for zero-mapped memory areas, etc.
- */
-extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-
 static inline int pmd_present(pmd_t pmd)
 {
        return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
@@ -430,11 +394,34 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
 
-#define kern_addr_valid(addr)   (1) /* FIXME */
+#define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
+#define VMALLOC_END      (PAGE_OFFSET - 1)
+#define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
 
-extern void *dtb_early_va;
-extern void setup_bootmem(void);
-extern void paging_init(void);
+/*
+ * Roughly size the vmemmap space to be large enough to fit enough
+ * struct pages to map half the virtual address space. Then
+ * position vmemmap directly below the VMALLOC region.
+ */
+#define VMEMMAP_SHIFT \
+       (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
+#define VMEMMAP_SIZE   BIT(VMEMMAP_SHIFT)
+#define VMEMMAP_END    (VMALLOC_START - 1)
+#define VMEMMAP_START  (VMALLOC_START - VMEMMAP_SIZE)
+
+#define vmemmap                ((struct page *)VMEMMAP_START)
+
+#define PCI_IO_SIZE      SZ_16M
+#define PCI_IO_END       VMEMMAP_START
+#define PCI_IO_START     (PCI_IO_END - PCI_IO_SIZE)
+
+#define FIXADDR_TOP      PCI_IO_START
+#ifdef CONFIG_64BIT
+#define FIXADDR_SIZE     PMD_SIZE
+#else
+#define FIXADDR_SIZE     PGDIR_SIZE
+#endif
+#define FIXADDR_START    (FIXADDR_TOP - FIXADDR_SIZE)
 
 /*
  * Task size is 0x4000000000 for RV64 or 0x9fc00000 for RV32.
@@ -446,6 +433,31 @@ extern void paging_init(void);
 #define TASK_SIZE FIXADDR_START
 #endif
 
+#else /* CONFIG_MMU */
+
+#define PAGE_KERNEL            __pgprot(0)
+#define swapper_pg_dir         NULL
+#define VMALLOC_START          0
+
+#define TASK_SIZE 0xffffffffUL
+
+#endif /* !CONFIG_MMU */
+
+#define kern_addr_valid(addr)   (1) /* FIXME */
+
+extern void *dtb_early_va;
+void setup_bootmem(void);
+void paging_init(void);
+
+#define FIRST_USER_ADDRESS  0
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero,
+ * used for zero-mapped memory areas, etc.
+ */
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
 #include <asm-generic/pgtable.h>
 
 #endif /* !__ASSEMBLY__ */
index f539149..3ddb798 100644 (file)
@@ -42,7 +42,7 @@ struct thread_struct {
        ((struct pt_regs *)(task_stack_page(tsk) + THREAD_SIZE          \
                            - ALIGN(sizeof(struct pt_regs), STACK_ALIGN)))
 
-#define KSTK_EIP(tsk)          (task_pt_regs(tsk)->sepc)
+#define KSTK_EIP(tsk)          (task_pt_regs(tsk)->epc)
 #define KSTK_ESP(tsk)          (task_pt_regs(tsk)->sp)
 
 
index d48d1e1..ee49f80 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef __ASSEMBLY__
 
 struct pt_regs {
-       unsigned long sepc;
+       unsigned long epc;
        unsigned long ra;
        unsigned long sp;
        unsigned long gp;
@@ -44,10 +44,10 @@ struct pt_regs {
        unsigned long t4;
        unsigned long t5;
        unsigned long t6;
-       /* Supervisor CSRs */
-       unsigned long sstatus;
-       unsigned long sbadaddr;
-       unsigned long scause;
+       /* Supervisor/Machine CSRs */
+       unsigned long status;
+       unsigned long badaddr;
+       unsigned long cause;
        /* a0 value before the syscall */
        unsigned long orig_a0;
 };
@@ -58,18 +58,18 @@ struct pt_regs {
 #define REG_FMT "%08lx"
 #endif
 
-#define user_mode(regs) (((regs)->sstatus & SR_SPP) == 0)
+#define user_mode(regs) (((regs)->status & SR_PP) == 0)
 
 
 /* Helpers for working with the instruction pointer */
 static inline unsigned long instruction_pointer(struct pt_regs *regs)
 {
-       return regs->sepc;
+       return regs->epc;
 }
 static inline void instruction_pointer_set(struct pt_regs *regs,
                                           unsigned long val)
 {
-       regs->sepc = val;
+       regs->epc = val;
 }
 
 #define profile_pc(regs) instruction_pointer(regs)
index 21134b3..2570c1e 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 
+#ifdef CONFIG_RISCV_SBI
 #define SBI_SET_TIMER 0
 #define SBI_CONSOLE_PUTCHAR 1
 #define SBI_CONSOLE_GETCHAR 2
@@ -93,5 +94,11 @@ static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
 {
        SBI_CALL_4(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask, start, size, asid);
 }
-
-#endif
+#else /* CONFIG_RISCV_SBI */
+/* stubs for code that is only reachable under IS_ENABLED(CONFIG_RISCV_SBI): */
+void sbi_set_timer(uint64_t stime_value);
+void sbi_clear_ipi(void);
+void sbi_send_ipi(const unsigned long *hart_mask);
+void sbi_remote_fence_i(const unsigned long *hart_mask);
+#endif /* CONFIG_RISCV_SBI */
+#endif /* _ASM_RISCV_SBI_H */
diff --git a/arch/riscv/include/asm/seccomp.h b/arch/riscv/include/asm/seccomp.h
new file mode 100644 (file)
index 0000000..bf7744e
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_SECCOMP_H
+#define _ASM_SECCOMP_H
+
+#include <asm/unistd.h>
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_SECCOMP_H */
index b58ba2d..45a7018 100644 (file)
@@ -1,11 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
-#ifndef __ASM_SPARSEMEM_H
-#define __ASM_SPARSEMEM_H
+#ifndef _ASM_RISCV_SPARSEMEM_H
+#define _ASM_RISCV_SPARSEMEM_H
 
 #ifdef CONFIG_SPARSEMEM
 #define MAX_PHYSMEM_BITS       CONFIG_PA_BITS
 #define SECTION_SIZE_BITS      27
 #endif /* CONFIG_SPARSEMEM */
 
-#endif /* __ASM_SPARSEMEM_H */
+#endif /* _ASM_RISCV_SPARSEMEM_H */
index 888cbf8..f398e76 100644 (file)
@@ -22,4 +22,4 @@ typedef struct {
 
 #define __ARCH_RW_LOCK_UNLOCKED                { 0 }
 
-#endif
+#endif /* _ASM_RISCV_SPINLOCK_TYPES_H */
index ee4f0ac..407bcc9 100644 (file)
@@ -17,19 +17,19 @@ extern void __fstate_restore(struct task_struct *restore_from);
 
 static inline void __fstate_clean(struct pt_regs *regs)
 {
-       regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_CLEAN;
+       regs->status = (regs->status & ~SR_FS) | SR_FS_CLEAN;
 }
 
 static inline void fstate_off(struct task_struct *task,
                              struct pt_regs *regs)
 {
-       regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_OFF;
+       regs->status = (regs->status & ~SR_FS) | SR_FS_OFF;
 }
 
 static inline void fstate_save(struct task_struct *task,
                               struct pt_regs *regs)
 {
-       if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) {
+       if ((regs->status & SR_FS) == SR_FS_DIRTY) {
                __fstate_save(task);
                __fstate_clean(regs);
        }
@@ -38,7 +38,7 @@ static inline void fstate_save(struct task_struct *task,
 static inline void fstate_restore(struct task_struct *task,
                                  struct pt_regs *regs)
 {
-       if ((regs->sstatus & SR_FS) != SR_FS_OFF) {
+       if ((regs->status & SR_FS) != SR_FS_OFF) {
                __fstate_restore(task);
                __fstate_clean(regs);
        }
@@ -50,7 +50,7 @@ static inline void __switch_to_aux(struct task_struct *prev,
        struct pt_regs *regs;
 
        regs = task_pt_regs(prev);
-       if (unlikely(regs->sstatus & SR_SD))
+       if (unlikely(regs->status & SR_SD))
                fstate_save(prev, regs);
        fstate_restore(next, task_pt_regs(next));
 }
index 905372d..1dd12a0 100644 (file)
@@ -75,6 +75,7 @@ struct thread_info {
 #define TIF_MEMDIE             5       /* is terminating due to OOM killer */
 #define TIF_SYSCALL_TRACEPOINT  6       /* syscall tracepoint instrumentation */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing */
+#define TIF_SECCOMP            8       /* syscall secure computing */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
@@ -82,11 +83,13 @@ struct thread_info {
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 
 #define _TIF_WORK_MASK \
        (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
 #define _TIF_SYSCALL_WORK \
-       (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
+       (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT | \
+        _TIF_SECCOMP)
 
 #endif /* _ASM_RISCV_THREAD_INFO_H */
index c7ef131..bad2a7c 100644 (file)
@@ -7,12 +7,25 @@
 #define _ASM_RISCV_TIMEX_H
 
 #include <asm/csr.h>
+#include <asm/mmio.h>
 
 typedef unsigned long cycles_t;
 
+extern u64 __iomem *riscv_time_val;
+extern u64 __iomem *riscv_time_cmp;
+
+#ifdef CONFIG_64BIT
+#define mmio_get_cycles()      readq_relaxed(riscv_time_val)
+#else
+#define mmio_get_cycles()      readl_relaxed(riscv_time_val)
+#define mmio_get_cycles_hi()   readl_relaxed(((u32 *)riscv_time_val) + 1)
+#endif
+
 static inline cycles_t get_cycles(void)
 {
-       return csr_read(CSR_TIME);
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               return csr_read(CSR_TIME);
+       return mmio_get_cycles();
 }
 #define get_cycles get_cycles
 
@@ -24,7 +37,9 @@ static inline u64 get_cycles64(void)
 #else /* CONFIG_64BIT */
 static inline u32 get_cycles_hi(void)
 {
-       return csr_read(CSR_TIMEH);
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               return csr_read(CSR_TIMEH);
+       return mmio_get_cycles_hi();
 }
 
 static inline u64 get_cycles64(void)
index f02188a..394cfbc 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mm_types.h>
 #include <asm/smp.h>
 
+#ifdef CONFIG_MMU
 static inline void local_flush_tlb_all(void)
 {
        __asm__ __volatile__ ("sfence.vma" : : : "memory");
@@ -20,14 +21,19 @@ static inline void local_flush_tlb_page(unsigned long addr)
 {
        __asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory");
 }
+#else /* CONFIG_MMU */
+#define local_flush_tlb_all()                  do { } while (0)
+#define local_flush_tlb_page(addr)             do { } while (0)
+#endif /* CONFIG_MMU */
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && defined(CONFIG_MMU)
 void flush_tlb_all(void);
 void flush_tlb_mm(struct mm_struct *mm);
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                     unsigned long end);
-#else /* CONFIG_SMP */
+#else /* CONFIG_SMP && CONFIG_MMU */
+
 #define flush_tlb_all() local_flush_tlb_all()
 #define flush_tlb_page(vma, addr) local_flush_tlb_page(addr)
 
@@ -38,7 +44,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
 }
 
 #define flush_tlb_mm(mm) flush_tlb_all()
-#endif /* CONFIG_SMP */
+#endif /* !CONFIG_SMP || !CONFIG_MMU */
 
 /* Flush a range of kernel pages */
 static inline void flush_tlb_kernel_range(unsigned long start,
index e076437..f462a18 100644 (file)
@@ -11,6 +11,7 @@
 /*
  * User space memory access functions
  */
+#ifdef CONFIG_MMU
 #include <linux/errno.h>
 #include <linux/compiler.h>
 #include <linux/thread_info.h>
@@ -475,4 +476,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
        __ret;                                                  \
 })
 
+#else /* CONFIG_MMU */
+#include <asm-generic/uaccess.h>
+#endif /* CONFIG_MMU */
 #endif /* _ASM_RISCV_UACCESS_H */
index 644a00c..d696d66 100644 (file)
@@ -9,8 +9,8 @@
  * (at your option) any later version.
  */
 
-#ifndef _UAPI_ASM_ELF_H
-#define _UAPI_ASM_ELF_H
+#ifndef _UAPI_ASM_RISCV_ELF_H
+#define _UAPI_ASM_RISCV_ELF_H
 
 #include <asm/ptrace.h>
 
@@ -95,4 +95,4 @@ typedef union __riscv_fp_state elf_fpregset_t;
 #define R_RISCV_32_PCREL       57
 
 
-#endif /* _UAPI_ASM_ELF_H */
+#endif /* _UAPI_ASM_RISCV_ELF_H */
index 4e76460..dee98ee 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (C) 2012 ARM Ltd.
  * Copyright (C) 2017 SiFive
  */
-#ifndef __UAPI_ASM_HWCAP_H
-#define __UAPI_ASM_HWCAP_H
+#ifndef _UAPI_ASM_RISCV_HWCAP_H
+#define _UAPI_ASM_RISCV_HWCAP_H
 
 /*
  * Linux saves the floating-point registers according to the ISA Linux is
@@ -22,4 +22,4 @@
 #define COMPAT_HWCAP_ISA_D     (1 << ('D' - 'A'))
 #define COMPAT_HWCAP_ISA_C     (1 << ('C' - 'A'))
 
-#endif
+#endif /* _UAPI_ASM_RISCV_HWCAP_H */
index 411dd7b..44eb993 100644 (file)
@@ -5,8 +5,8 @@
  *
  * This file was copied from arch/arm64/include/uapi/asm/ucontext.h
  */
-#ifndef _UAPI__ASM_UCONTEXT_H
-#define _UAPI__ASM_UCONTEXT_H
+#ifndef _UAPI_ASM_RISCV_UCONTEXT_H
+#define _UAPI_ASM_RISCV_UCONTEXT_H
 
 #include <linux/types.h>
 
@@ -31,4 +31,4 @@ struct ucontext {
        struct sigcontext uc_mcontext;
 };
 
-#endif /* _UAPI__ASM_UCONTEXT_H */
+#endif /* _UAPI_ASM_RISCV_UCONTEXT_H */
index 696020f..f40205c 100644 (file)
@@ -25,10 +25,10 @@ obj-y       += time.o
 obj-y  += traps.o
 obj-y  += riscv_ksyms.o
 obj-y  += stacktrace.o
-obj-y  += vdso.o
 obj-y  += cacheinfo.o
-obj-y  += vdso/
+obj-$(CONFIG_MMU) += vdso.o vdso/
 
+obj-$(CONFIG_RISCV_M_MODE)     += clint.o
 obj-$(CONFIG_FPU)              += fpu.o
 obj-$(CONFIG_SMP)              += smpboot.o
 obj-$(CONFIG_SMP)              += smp.o
@@ -41,5 +41,6 @@ obj-$(CONFIG_DYNAMIC_FTRACE)  += mcount-dyn.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_callchain.o
 obj-$(CONFIG_HAVE_PERF_REGS)   += perf_regs.o
+obj-$(CONFIG_RISCV_SBI)                += sbi.o
 
 clean:
index 9f5628c..07cb9c1 100644 (file)
@@ -71,7 +71,7 @@ void asm_offsets(void)
        OFFSET(TASK_THREAD_FCSR, task_struct, thread.fstate.fcsr);
 
        DEFINE(PT_SIZE, sizeof(struct pt_regs));
-       OFFSET(PT_SEPC, pt_regs, sepc);
+       OFFSET(PT_EPC, pt_regs, epc);
        OFFSET(PT_RA, pt_regs, ra);
        OFFSET(PT_FP, pt_regs, s0);
        OFFSET(PT_S0, pt_regs, s0);
@@ -105,9 +105,9 @@ void asm_offsets(void)
        OFFSET(PT_T6, pt_regs, t6);
        OFFSET(PT_GP, pt_regs, gp);
        OFFSET(PT_ORIG_A0, pt_regs, orig_a0);
-       OFFSET(PT_SSTATUS, pt_regs, sstatus);
-       OFFSET(PT_SBADADDR, pt_regs, sbadaddr);
-       OFFSET(PT_SCAUSE, pt_regs, scause);
+       OFFSET(PT_STATUS, pt_regs, status);
+       OFFSET(PT_BADADDR, pt_regs, badaddr);
+       OFFSET(PT_CAUSE, pt_regs, cause);
 
        /*
         * THREAD_{F,X}* might be larger than a S-type offset can handle, but
diff --git a/arch/riscv/kernel/clint.c b/arch/riscv/kernel/clint.c
new file mode 100644 (file)
index 0000000..3647980
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Christoph Hellwig.
+ */
+
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/types.h>
+#include <asm/clint.h>
+#include <asm/csr.h>
+#include <asm/timex.h>
+#include <asm/smp.h>
+
+/*
+ * This is the layout used by the SiFive clint, which is also shared by the qemu
+ * virt platform, and the Kendryte KD210 at least.
+ */
+#define CLINT_IPI_OFF          0
+#define CLINT_TIME_CMP_OFF     0x4000
+#define CLINT_TIME_VAL_OFF     0xbff8
+
+u32 __iomem *clint_ipi_base;
+
+void clint_init_boot_cpu(void)
+{
+       struct device_node *np;
+       void __iomem *base;
+
+       np = of_find_compatible_node(NULL, NULL, "riscv,clint0");
+       if (!np) {
+               panic("clint not found");
+               return;
+       }
+
+       base = of_iomap(np, 0);
+       if (!base)
+               panic("could not map CLINT");
+
+       clint_ipi_base = base + CLINT_IPI_OFF;
+       riscv_time_cmp = base + CLINT_TIME_CMP_OFF;
+       riscv_time_val = base + CLINT_TIME_VAL_OFF;
+
+       clint_clear_ipi(boot_cpu_hartid);
+}
index 7da3c6a..40a3c44 100644 (file)
@@ -46,51 +46,12 @@ int riscv_of_processor_hartid(struct device_node *node)
 
 #ifdef CONFIG_PROC_FS
 
-static void print_isa(struct seq_file *f, const char *orig_isa)
+static void print_isa(struct seq_file *f, const char *isa)
 {
-       static const char *ext = "mafdcsu";
-       const char *isa = orig_isa;
-       const char *e;
-
-       /*
-        * Linux doesn't support rv32e or rv128i, and we only support booting
-        * kernels on harts with the same ISA that the kernel is compiled for.
-        */
-#if defined(CONFIG_32BIT)
-       if (strncmp(isa, "rv32i", 5) != 0)
-               return;
-#elif defined(CONFIG_64BIT)
-       if (strncmp(isa, "rv64i", 5) != 0)
-               return;
-#endif
-
-       /* Print the base ISA, as we already know it's legal. */
+       /* Print the entire ISA as it is */
        seq_puts(f, "isa\t\t: ");
-       seq_write(f, isa, 5);
-       isa += 5;
-
-       /*
-        * Check the rest of the ISA string for valid extensions, printing those
-        * we find.  RISC-V ISA strings define an order, so we only print the
-        * extension bits when they're in order. Hide the supervisor (S)
-        * extension from userspace as it's not accessible from there.
-        */
-       for (e = ext; *e != '\0'; ++e) {
-               if (isa[0] == e[0]) {
-                       if (isa[0] != 's')
-                               seq_write(f, isa, 1);
-
-                       isa++;
-               }
-       }
+       seq_write(f, isa, strlen(isa));
        seq_puts(f, "\n");
-
-       /*
-        * If we were given an unsupported ISA in the device tree then print
-        * a bit of info describing what went wrong.
-        */
-       if (isa[0] != '\0')
-               pr_info("unsupported ISA \"%s\" in device tree\n", orig_isa);
 }
 
 static void print_mmu(struct seq_file *f, const char *mmu_type)
index 8ca4798..a1349ca 100644 (file)
 
        /*
         * If coming from userspace, preserve the user thread pointer and load
-        * the kernel thread pointer.  If we came from the kernel, sscratch
-        * will contain 0, and we should continue on the current TP.
+        * the kernel thread pointer.  If we came from the kernel, the scratch
+        * register will contain 0, and we should continue on the current TP.
         */
-       csrrw tp, CSR_SSCRATCH, tp
+       csrrw tp, CSR_SCRATCH, tp
        bnez tp, _save_context
 
 _restore_kernel_tpsp:
-       csrr tp, CSR_SSCRATCH
+       csrr tp, CSR_SCRATCH
        REG_S sp, TASK_TI_KERNEL_SP(tp)
 _save_context:
        REG_S sp, TASK_TI_USER_SP(tp)
@@ -79,16 +79,16 @@ _save_context:
        li t0, SR_SUM | SR_FS
 
        REG_L s0, TASK_TI_USER_SP(tp)
-       csrrc s1, CSR_SSTATUS, t0
-       csrr s2, CSR_SEPC
-       csrr s3, CSR_STVAL
-       csrr s4, CSR_SCAUSE
-       csrr s5, CSR_SSCRATCH
+       csrrc s1, CSR_STATUS, t0
+       csrr s2, CSR_EPC
+       csrr s3, CSR_TVAL
+       csrr s4, CSR_CAUSE
+       csrr s5, CSR_SCRATCH
        REG_S s0, PT_SP(sp)
-       REG_S s1, PT_SSTATUS(sp)
-       REG_S s2, PT_SEPC(sp)
-       REG_S s3, PT_SBADADDR(sp)
-       REG_S s4, PT_SCAUSE(sp)
+       REG_S s1, PT_STATUS(sp)
+       REG_S s2, PT_EPC(sp)
+       REG_S s3, PT_BADADDR(sp)
+       REG_S s4, PT_CAUSE(sp)
        REG_S s5, PT_TP(sp)
        .endm
 
@@ -97,7 +97,7 @@ _save_context:
  * registers from the stack.
  */
        .macro RESTORE_ALL
-       REG_L a0, PT_SSTATUS(sp)
+       REG_L a0, PT_STATUS(sp)
        /*
         * The current load reservation is effectively part of the processor's
         * state, in the sense that load reservations cannot be shared between
@@ -115,11 +115,11 @@ _save_context:
         * completes, implementations are allowed to expand reservations to be
         * arbitrarily large.
         */
-       REG_L  a2, PT_SEPC(sp)
-       REG_SC x0, a2, PT_SEPC(sp)
+       REG_L  a2, PT_EPC(sp)
+       REG_SC x0, a2, PT_EPC(sp)
 
-       csrw CSR_SSTATUS, a0
-       csrw CSR_SEPC, a2
+       csrw CSR_STATUS, a0
+       csrw CSR_EPC, a2
 
        REG_L x1,  PT_RA(sp)
        REG_L x3,  PT_GP(sp)
@@ -163,10 +163,10 @@ ENTRY(handle_exception)
        SAVE_ALL
 
        /*
-        * Set sscratch register to 0, so that if a recursive exception
+        * Set the scratch register to 0, so that if a recursive exception
         * occurs, the exception vector knows it came from the kernel
         */
-       csrw CSR_SSCRATCH, x0
+       csrw CSR_SCRATCH, x0
 
        /* Load the global pointer */
 .option push
@@ -185,11 +185,13 @@ ENTRY(handle_exception)
        move a0, sp /* pt_regs */
        tail do_IRQ
 1:
-       /* Exceptions run with interrupts enabled or disabled
-          depending on the state of sstatus.SR_SPIE */
-       andi t0, s1, SR_SPIE
+       /*
+        * Exceptions run with interrupts enabled or disabled depending on the
+        * state of SR_PIE in m/sstatus.
+        */
+       andi t0, s1, SR_PIE
        beqz t0, 1f
-       csrs CSR_SSTATUS, SR_SIE
+       csrs CSR_STATUS, SR_IE
 
 1:
        /* Handle syscalls */
@@ -217,7 +219,7 @@ handle_syscall:
         * scall instruction on sret
         */
        addi s2, s2, 0x4
-       REG_S s2, PT_SEPC(sp)
+       REG_S s2, PT_EPC(sp)
        /* Trace syscalls, but only if requested by the user. */
        REG_L t0, TASK_TI_FLAGS(tp)
        andi t0, t0, _TIF_SYSCALL_WORK
@@ -226,8 +228,25 @@ check_syscall_nr:
        /* Check to make sure we don't jump to a bogus syscall number. */
        li t0, __NR_syscalls
        la s0, sys_ni_syscall
-       /* Syscall number held in a7 */
-       bgeu a7, t0, 1f
+       /*
+        * The tracer can change syscall number to valid/invalid value.
+        * We use syscall_set_nr helper in syscall_trace_enter thus we
+        * cannot trust the current value in a7 and have to reload from
+        * the current task pt_regs.
+        */
+       REG_L a7, PT_A7(sp)
+       /*
+        * Syscall number held in a7.
+        * If syscall number is above allowed value, redirect to ni_syscall.
+        */
+       bge a7, t0, 1f
+       /*
+        * Check if syscall is rejected by tracer or seccomp, i.e., a7 == -1.
+        * If yes, we pretend it was executed.
+        */
+       li t1, -1
+       beq a7, t1, ret_from_syscall_rejected
+       /* Call syscall */
        la s0, sys_call_table
        slli t0, a7, RISCV_LGPTR
        add s0, s0, t0
@@ -238,15 +257,27 @@ check_syscall_nr:
 ret_from_syscall:
        /* Set user a0 to kernel a0 */
        REG_S a0, PT_A0(sp)
+       /*
+        * We didn't execute the actual syscall.
+        * Seccomp already set return value for the current task pt_regs.
+        * (If it was configured with SECCOMP_RET_ERRNO/TRACE)
+        */
+ret_from_syscall_rejected:
        /* Trace syscalls, but only if requested by the user. */
        REG_L t0, TASK_TI_FLAGS(tp)
        andi t0, t0, _TIF_SYSCALL_WORK
        bnez t0, handle_syscall_trace_exit
 
 ret_from_exception:
-       REG_L s0, PT_SSTATUS(sp)
-       csrc CSR_SSTATUS, SR_SIE
+       REG_L s0, PT_STATUS(sp)
+       csrc CSR_STATUS, SR_IE
+#ifdef CONFIG_RISCV_M_MODE
+       /* the MPP value is too large to be used as an immediate arg for addi */
+       li t0, SR_MPP
+       and s0, s0, t0
+#else
        andi s0, s0, SR_SPP
+#endif
        bnez s0, resume_kernel
 
 resume_userspace:
@@ -260,14 +291,18 @@ resume_userspace:
        REG_S s0, TASK_TI_KERNEL_SP(tp)
 
        /*
-        * Save TP into sscratch, so we can find the kernel data structures
-        * again.
+        * Save TP into the scratch register , so we can find the kernel data
+        * structures again.
         */
-       csrw CSR_SSCRATCH, tp
+       csrw CSR_SCRATCH, tp
 
 restore_all:
        RESTORE_ALL
+#ifdef CONFIG_RISCV_M_MODE
+       mret
+#else
        sret
+#endif
 
 #if IS_ENABLED(CONFIG_PREEMPT)
 resume_kernel:
@@ -287,7 +322,7 @@ work_pending:
        bnez s1, work_resched
 work_notifysig:
        /* Handle pending signals and notify-resume requests */
-       csrs CSR_SSTATUS, SR_SIE /* Enable interrupts for do_notify_resume() */
+       csrs CSR_STATUS, SR_IE /* Enable interrupts for do_notify_resume() */
        move a0, sp /* pt_regs */
        move a1, s0 /* current_thread_info->flags */
        tail do_notify_resume
@@ -386,6 +421,10 @@ ENTRY(__switch_to)
        ret
 ENDPROC(__switch_to)
 
+#ifndef CONFIG_MMU
+#define do_page_fault do_trap_unknown
+#endif
+
        .section ".rodata"
        /* Exception vector table */
 ENTRY(excp_vect_table)
@@ -407,3 +446,10 @@ ENTRY(excp_vect_table)
        RISCV_PTR do_page_fault   /* store page fault */
 excp_vect_table_end:
 END(excp_vect_table)
+
+#ifndef CONFIG_MMU
+ENTRY(__user_rt_sigreturn)
+       li a7, __NR_rt_sigreturn
+       scall
+END(__user_rt_sigreturn)
+#endif
index 631d315..dd22054 100644 (file)
@@ -23,7 +23,7 @@ ENTRY(__fstate_save)
        li  a2,  TASK_THREAD_F0
        add a0, a0, a2
        li t1, SR_FS
-       csrs CSR_SSTATUS, t1
+       csrs CSR_STATUS, t1
        frcsr t0
        fsd f0,  TASK_THREAD_F0_F0(a0)
        fsd f1,  TASK_THREAD_F1_F0(a0)
@@ -58,7 +58,7 @@ ENTRY(__fstate_save)
        fsd f30, TASK_THREAD_F30_F0(a0)
        fsd f31, TASK_THREAD_F31_F0(a0)
        sw t0, TASK_THREAD_FCSR_F0(a0)
-       csrc CSR_SSTATUS, t1
+       csrc CSR_STATUS, t1
        ret
 ENDPROC(__fstate_save)
 
@@ -67,7 +67,7 @@ ENTRY(__fstate_restore)
        add a0, a0, a2
        li t1, SR_FS
        lw t0, TASK_THREAD_FCSR_F0(a0)
-       csrs CSR_SSTATUS, t1
+       csrs CSR_STATUS, t1
        fld f0,  TASK_THREAD_F0_F0(a0)
        fld f1,  TASK_THREAD_F1_F0(a0)
        fld f2,  TASK_THREAD_F2_F0(a0)
@@ -101,6 +101,6 @@ ENTRY(__fstate_restore)
        fld f30, TASK_THREAD_F30_F0(a0)
        fld f31, TASK_THREAD_F31_F0(a0)
        fscsr t0
-       csrc CSR_SSTATUS, t1
+       csrc CSR_STATUS, t1
        ret
 ENDPROC(__fstate_restore)
index 72f89b7..84a6f0a 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include <asm/csr.h>
+#include <asm/hwcap.h>
 #include <asm/image.h>
 
 __INIT
@@ -47,8 +48,22 @@ ENTRY(_start)
 .global _start_kernel
 _start_kernel:
        /* Mask all interrupts */
-       csrw CSR_SIE, zero
-       csrw CSR_SIP, zero
+       csrw CSR_IE, zero
+       csrw CSR_IP, zero
+
+#ifdef CONFIG_RISCV_M_MODE
+       /* flush the instruction cache */
+       fence.i
+
+       /* Reset all registers except ra, a0, a1 */
+       call reset_regs
+
+       /*
+        * The hartid in a0 is expected later on, and we have no firmware
+        * to hand it to us.
+        */
+       csrr a0, CSR_MHARTID
+#endif /* CONFIG_RISCV_M_MODE */
 
        /* Load the global pointer */
 .option push
@@ -61,7 +76,7 @@ _start_kernel:
         * floating point in kernel space
         */
        li t0, SR_FS
-       csrc CSR_SSTATUS, t0
+       csrc CSR_STATUS, t0
 
 #ifdef CONFIG_SMP
        li t0, CONFIG_NR_CPUS
@@ -94,8 +109,10 @@ clear_bss_done:
        la sp, init_thread_union + THREAD_SIZE
        mv a0, s1
        call setup_vm
+#ifdef CONFIG_MMU
        la a0, early_pg_dir
        call relocate
+#endif /* CONFIG_MMU */
 
        /* Restore C environment */
        la tp, init_task
@@ -106,6 +123,7 @@ clear_bss_done:
        call parse_dtb
        tail start_kernel
 
+#ifdef CONFIG_MMU
 relocate:
        /* Relocate return address */
        li a1, PAGE_OFFSET
@@ -116,7 +134,7 @@ relocate:
        /* Point stvec to virtual address of intruction after satp write */
        la a2, 1f
        add a2, a2, a1
-       csrw CSR_STVEC, a2
+       csrw CSR_TVEC, a2
 
        /* Compute satp for kernel page tables, but don't load it yet */
        srl a2, a0, PAGE_SHIFT
@@ -138,7 +156,7 @@ relocate:
 1:
        /* Set trap vector to spin forever to help debug */
        la a0, .Lsecondary_park
-       csrw CSR_STVEC, a0
+       csrw CSR_TVEC, a0
 
        /* Reload the global pointer */
 .option push
@@ -156,12 +174,13 @@ relocate:
        sfence.vma
 
        ret
+#endif /* CONFIG_MMU */
 
 .Lsecondary_start:
 #ifdef CONFIG_SMP
        /* Set trap vector to spin forever to help debug */
        la a3, .Lsecondary_park
-       csrw CSR_STVEC, a3
+       csrw CSR_TVEC, a3
 
        slli a3, a0, LGREG
        la a1, __cpu_up_stack_pointer
@@ -181,9 +200,11 @@ relocate:
        beqz tp, .Lwait_for_cpu_up
        fence
 
+#ifdef CONFIG_MMU
        /* Enable virtual memory and relocate to virtual address */
        la a0, swapper_pg_dir
        call relocate
+#endif
 
        tail smp_callin
 #endif
@@ -195,6 +216,85 @@ relocate:
        j .Lsecondary_park
 END(_start)
 
+#ifdef CONFIG_RISCV_M_MODE
+ENTRY(reset_regs)
+       li      sp, 0
+       li      gp, 0
+       li      tp, 0
+       li      t0, 0
+       li      t1, 0
+       li      t2, 0
+       li      s0, 0
+       li      s1, 0
+       li      a2, 0
+       li      a3, 0
+       li      a4, 0
+       li      a5, 0
+       li      a6, 0
+       li      a7, 0
+       li      s2, 0
+       li      s3, 0
+       li      s4, 0
+       li      s5, 0
+       li      s6, 0
+       li      s7, 0
+       li      s8, 0
+       li      s9, 0
+       li      s10, 0
+       li      s11, 0
+       li      t3, 0
+       li      t4, 0
+       li      t5, 0
+       li      t6, 0
+       csrw    sscratch, 0
+
+#ifdef CONFIG_FPU
+       csrr    t0, CSR_MISA
+       andi    t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
+       bnez    t0, .Lreset_regs_done
+
+       li      t1, SR_FS
+       csrs    CSR_STATUS, t1
+       fmv.s.x f0, zero
+       fmv.s.x f1, zero
+       fmv.s.x f2, zero
+       fmv.s.x f3, zero
+       fmv.s.x f4, zero
+       fmv.s.x f5, zero
+       fmv.s.x f6, zero
+       fmv.s.x f7, zero
+       fmv.s.x f8, zero
+       fmv.s.x f9, zero
+       fmv.s.x f10, zero
+       fmv.s.x f11, zero
+       fmv.s.x f12, zero
+       fmv.s.x f13, zero
+       fmv.s.x f14, zero
+       fmv.s.x f15, zero
+       fmv.s.x f16, zero
+       fmv.s.x f17, zero
+       fmv.s.x f18, zero
+       fmv.s.x f19, zero
+       fmv.s.x f20, zero
+       fmv.s.x f21, zero
+       fmv.s.x f22, zero
+       fmv.s.x f23, zero
+       fmv.s.x f24, zero
+       fmv.s.x f25, zero
+       fmv.s.x f26, zero
+       fmv.s.x f27, zero
+       fmv.s.x f28, zero
+       fmv.s.x f29, zero
+       fmv.s.x f30, zero
+       fmv.s.x f31, zero
+       csrw    fcsr, 0
+       /* note that the caller must clear SR_FS */
+#endif /* CONFIG_FPU */
+.Lreset_regs_done:
+       ret
+END(reset_regs)
+#endif /* CONFIG_RISCV_M_MODE */
+
 __PAGE_ALIGNED_BSS
        /* Empty zero page */
        .balign PAGE_SIZE
index fffac6d..3f07a91 100644 (file)
 #include <linux/seq_file.h>
 #include <asm/smp.h>
 
-/*
- * Possible interrupt causes:
- */
-#define INTERRUPT_CAUSE_SOFTWARE       IRQ_S_SOFT
-#define INTERRUPT_CAUSE_TIMER          IRQ_S_TIMER
-#define INTERRUPT_CAUSE_EXTERNAL       IRQ_S_EXT
-
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
        show_ipi_stats(p, prec);
@@ -29,12 +22,12 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
        struct pt_regs *old_regs = set_irq_regs(regs);
 
        irq_enter();
-       switch (regs->scause & ~SCAUSE_IRQ_FLAG) {
-       case INTERRUPT_CAUSE_TIMER:
+       switch (regs->cause & ~CAUSE_IRQ_FLAG) {
+       case IRQ_TIMER:
                riscv_timer_interrupt();
                break;
 #ifdef CONFIG_SMP
-       case INTERRUPT_CAUSE_SOFTWARE:
+       case IRQ_SOFT:
                /*
                 * We only use software interrupts to pass IPIs, so if a non-SMP
                 * system gets one, then we don't know what to do.
@@ -42,11 +35,11 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
                riscv_software_interrupt();
                break;
 #endif
-       case INTERRUPT_CAUSE_EXTERNAL:
+       case IRQ_EXT:
                handle_arch_irq(regs);
                break;
        default:
-               pr_alert("unexpected interrupt cause 0x%lx", regs->scause);
+               pr_alert("unexpected interrupt cause 0x%lx", regs->cause);
                BUG();
        }
        irq_exit();
index 8d2804f..cf19019 100644 (file)
@@ -67,7 +67,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
                return;
 
        fp = regs->s0;
-       perf_callchain_store(entry, regs->sepc);
+       perf_callchain_store(entry, regs->epc);
 
        fp = user_backtrace(entry, fp, regs->ra);
        while (fp && !(fp & 0x3) && entry->nr < entry->max_stack)
index 85e3c39..95a3031 100644 (file)
@@ -35,8 +35,8 @@ void show_regs(struct pt_regs *regs)
 {
        show_regs_print_info(KERN_DEFAULT);
 
-       pr_cont("sepc: " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n",
-               regs->sepc, regs->ra, regs->sp);
+       pr_cont("epc: " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n",
+               regs->epc, regs->ra, regs->sp);
        pr_cont(" gp : " REG_FMT " tp : " REG_FMT " t0 : " REG_FMT "\n",
                regs->gp, regs->tp, regs->t0);
        pr_cont(" t1 : " REG_FMT " t2 : " REG_FMT " s0 : " REG_FMT "\n",
@@ -58,23 +58,23 @@ void show_regs(struct pt_regs *regs)
        pr_cont(" t5 : " REG_FMT " t6 : " REG_FMT "\n",
                regs->t5, regs->t6);
 
-       pr_cont("sstatus: " REG_FMT " sbadaddr: " REG_FMT " scause: " REG_FMT "\n",
-               regs->sstatus, regs->sbadaddr, regs->scause);
+       pr_cont("status: " REG_FMT " badaddr: " REG_FMT " cause: " REG_FMT "\n",
+               regs->status, regs->badaddr, regs->cause);
 }
 
 void start_thread(struct pt_regs *regs, unsigned long pc,
        unsigned long sp)
 {
-       regs->sstatus = SR_SPIE;
+       regs->status = SR_PIE;
        if (has_fpu) {
-               regs->sstatus |= SR_FS_INITIAL;
+               regs->status |= SR_FS_INITIAL;
                /*
                 * Restore the initial value to the FP register
                 * before starting the user program.
                 */
                fstate_restore(current, regs);
        }
-       regs->sepc = pc;
+       regs->epc = pc;
        regs->sp = sp;
        set_fs(USER_DS);
 }
@@ -110,7 +110,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                const register unsigned long gp __asm__ ("gp");
                memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gp = gp;
-               childregs->sstatus = SR_SPP | SR_SPIE; /* Supervisor, irqs on */
+               /* Supervisor/Machine, irqs on: */
+               childregs->status = SR_PP | SR_PIE;
 
                p->thread.ra = (unsigned long)ret_from_kernel_thread;
                p->thread.s[0] = usp; /* fn */
index 1252113..0f84628 100644 (file)
@@ -154,6 +154,16 @@ __visible void do_syscall_trace_enter(struct pt_regs *regs)
                if (tracehook_report_syscall_entry(regs))
                        syscall_set_nr(current, regs, -1);
 
+       /*
+        * Do the secure computing after ptrace; failures should be fast.
+        * If this fails we might have return value in a0 from seccomp
+        * (via SECCOMP_RET_ERRNO/TRACE).
+        */
+       if (secure_computing(NULL) == -1) {
+               syscall_set_nr(current, regs, -1);
+               return;
+       }
+
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, syscall_get_nr(current, regs));
index aa56bb1..ee5878d 100644 (file)
@@ -5,12 +5,11 @@
 
 #include <linux/reboot.h>
 #include <linux/pm.h>
-#include <asm/sbi.h>
 
 static void default_power_off(void)
 {
-       sbi_shutdown();
-       while (1);
+       while (1)
+               wait_for_interrupt();
 }
 
 void (*pm_power_off)(void) = default_power_off;
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
new file mode 100644 (file)
index 0000000..f6c7c3e
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <asm/sbi.h>
+
+static void sbi_power_off(void)
+{
+       sbi_shutdown();
+}
+
+static int __init sbi_init(void)
+{
+       pm_power_off = sbi_power_off;
+       return 0;
+}
+early_initcall(sbi_init);
index 845ae0e..365ff84 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/sched/task.h>
 #include <linux/swiotlb.h>
 
+#include <asm/clint.h>
 #include <asm/setup.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
@@ -67,6 +68,7 @@ void __init setup_arch(char **cmdline_p)
        setup_bootmem();
        paging_init();
        unflatten_device_tree();
+       clint_init_boot_cpu();
 
 #ifdef CONFIG_SWIOTLB
        swiotlb_init(1);
index d0f6f21..17ba190 100644 (file)
 #include <asm/switch_to.h>
 #include <asm/csr.h>
 
+extern u32 __user_rt_sigreturn[2];
+
 #define DEBUG_SIG 0
 
 struct rt_sigframe {
        struct siginfo info;
        struct ucontext uc;
+#ifndef CONFIG_MMU
+       u32 sigreturn_code[2];
+#endif
 };
 
 #ifdef CONFIG_FPU
@@ -124,7 +129,7 @@ badframe:
                pr_info_ratelimited(
                        "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
                        task->comm, task_pid_nr(task), __func__,
-                       frame, (void *)regs->sepc, (void *)regs->sp);
+                       frame, (void *)regs->epc, (void *)regs->sp);
        }
        force_sig(SIGSEGV);
        return 0;
@@ -166,7 +171,6 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
        return (void __user *)sp;
 }
 
-
 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        struct pt_regs *regs)
 {
@@ -189,8 +193,19 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
 
        /* Set up to return from userspace. */
+#ifdef CONFIG_MMU
        regs->ra = (unsigned long)VDSO_SYMBOL(
                current->mm->context.vdso, rt_sigreturn);
+#else
+       /*
+        * For the nommu case we don't have a VDSO.  Instead we push two
+        * instructions to call the rt_sigreturn syscall onto the user stack.
+        */
+       if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
+                        sizeof(frame->sigreturn_code)))
+               return -EFAULT;
+       regs->ra = (unsigned long)&frame->sigreturn_code;
+#endif /* CONFIG_MMU */
 
        /*
         * Set up registers for signal handler.
@@ -199,7 +214,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
         * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
         * since some things rely on this (e.g. glibc's debug/segfault.c).
         */
-       regs->sepc = (unsigned long)ksig->ka.sa.sa_handler;
+       regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
        regs->sp = (unsigned long)frame;
        regs->a0 = ksig->sig;                     /* a0: signal number */
        regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
@@ -208,7 +223,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 #if DEBUG_SIG
        pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
                current->comm, task_pid_nr(current), ksig->sig,
-               (void *)regs->sepc, (void *)regs->ra, frame);
+               (void *)regs->epc, (void *)regs->ra, frame);
 #endif
 
        return 0;
@@ -220,10 +235,9 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
        int ret;
 
        /* Are we from a system call? */
-       if (regs->scause == EXC_SYSCALL) {
+       if (regs->cause == EXC_SYSCALL) {
                /* Avoid additional syscall restarting via ret_from_exception */
-               regs->scause = -1UL;
-
+               regs->cause = -1UL;
                /* If so, check system call restarting.. */
                switch (regs->a0) {
                case -ERESTART_RESTARTBLOCK:
@@ -239,7 +253,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
                        /* fallthrough */
                case -ERESTARTNOINTR:
                         regs->a0 = regs->orig_a0;
-                       regs->sepc -= 0x4;
+                       regs->epc -= 0x4;
                        break;
                }
        }
@@ -261,9 +275,9 @@ static void do_signal(struct pt_regs *regs)
        }
 
        /* Did we come from a system call? */
-       if (regs->scause == EXC_SYSCALL) {
+       if (regs->cause == EXC_SYSCALL) {
                /* Avoid additional syscall restarting via ret_from_exception */
-               regs->scause = -1UL;
+               regs->cause = -1UL;
 
                /* Restart the system call - no handlers present */
                switch (regs->a0) {
@@ -271,12 +285,12 @@ static void do_signal(struct pt_regs *regs)
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
                         regs->a0 = regs->orig_a0;
-                       regs->sepc -= 0x4;
+                       regs->epc -= 0x4;
                        break;
                case -ERESTART_RESTARTBLOCK:
                         regs->a0 = regs->orig_a0;
                        regs->a7 = __NR_restart_syscall;
-                       regs->sepc -= 0x4;
+                       regs->epc -= 0x4;
                        break;
                }
        }
index 5c9ec78..eb878ab 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/seq_file.h>
 #include <linux/delay.h>
 
+#include <asm/clint.h>
 #include <asm/sbi.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
@@ -92,7 +93,10 @@ static void send_ipi_mask(const struct cpumask *mask, enum ipi_message_type op)
        smp_mb__after_atomic();
 
        riscv_cpuid_to_hartid_mask(mask, &hartid_mask);
-       sbi_send_ipi(cpumask_bits(&hartid_mask));
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               sbi_send_ipi(cpumask_bits(&hartid_mask));
+       else
+               clint_send_ipi_mask(&hartid_mask);
 }
 
 static void send_ipi_single(int cpu, enum ipi_message_type op)
@@ -103,12 +107,18 @@ static void send_ipi_single(int cpu, enum ipi_message_type op)
        set_bit(op, &ipi_data[cpu].bits);
        smp_mb__after_atomic();
 
-       sbi_send_ipi(cpumask_bits(cpumask_of(hartid)));
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               sbi_send_ipi(cpumask_bits(cpumask_of(hartid)));
+       else
+               clint_send_ipi_single(hartid);
 }
 
 static inline void clear_ipi(void)
 {
-       csr_clear(CSR_SIP, SIE_SSIE);
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               csr_clear(CSR_IP, IE_SIE);
+       else
+               clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id()));
 }
 
 void riscv_software_interrupt(void)
index 261f408..8bc01f0 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/sched/task_stack.h>
 #include <linux/sched/mm.h>
+#include <asm/clint.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
@@ -137,6 +138,9 @@ asmlinkage __visible void __init smp_callin(void)
 {
        struct mm_struct *mm = &init_mm;
 
+       if (!IS_ENABLED(CONFIG_RISCV_SBI))
+               clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id()));
+
        /* All kernel threads share the same mm context.  */
        mmgrab(mm);
        current->active_mm = mm;
index 473de3a..f4cad51 100644 (file)
@@ -41,7 +41,7 @@ void die(struct pt_regs *regs, const char *str)
        print_modules();
        show_regs(regs);
 
-       ret = notify_die(DIE_OOPS, str, regs, 0, regs->scause, SIGSEGV);
+       ret = notify_die(DIE_OOPS, str, regs, 0, regs->cause, SIGSEGV);
 
        bust_spinlocks(0);
        add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
@@ -86,7 +86,7 @@ static void do_trap_error(struct pt_regs *regs, int signo, int code,
 #define DO_ERROR_INFO(name, signo, code, str)                          \
 asmlinkage __visible void name(struct pt_regs *regs)                   \
 {                                                                      \
-       do_trap_error(regs, signo, code, regs->sepc, "Oops - " str);    \
+       do_trap_error(regs, signo, code, regs->epc, "Oops - " str);     \
 }
 
 DO_ERROR_INFO(do_trap_unknown,
@@ -124,9 +124,9 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
 asmlinkage __visible void do_trap_break(struct pt_regs *regs)
 {
        if (user_mode(regs))
-               force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->sepc);
-       else if (report_bug(regs->sepc, regs) == BUG_TRAP_TYPE_WARN)
-               regs->sepc += get_break_insn_length(regs->sepc);
+               force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->epc);
+       else if (report_bug(regs->epc, regs) == BUG_TRAP_TYPE_WARN)
+               regs->epc += get_break_insn_length(regs->epc);
        else
                die(regs, "Kernel BUG");
 }
@@ -153,9 +153,9 @@ void __init trap_init(void)
         * Set sup0 scratch register to 0, indicating to exception vector
         * that we are presently executing in the kernel
         */
-       csr_write(CSR_SSCRATCH, 0);
+       csr_write(CSR_SCRATCH, 0);
        /* Set the exception vector address */
-       csr_write(CSR_STVEC, &handle_exception);
+       csr_write(CSR_TVEC, &handle_exception);
        /* Enable all interrupts */
-       csr_write(CSR_SIE, -1);
+       csr_write(CSR_IE, -1);
 }
index 267feaa..47e7a82 100644 (file)
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
-lib-y  += delay.o
-lib-y  += memcpy.o
-lib-y  += memset.o
-lib-y  += uaccess.o
-
-lib-$(CONFIG_64BIT) += tishift.o
+lib-y                  += delay.o
+lib-y                  += memcpy.o
+lib-y                  += memset.o
+lib-$(CONFIG_MMU)      += uaccess.o
+lib-$(CONFIG_64BIT)    += tishift.o
index ed2696c..fecd656 100644 (file)
@@ -18,7 +18,7 @@ ENTRY(__asm_copy_from_user)
 
        /* Enable access to user memory */
        li t6, SR_SUM
-       csrs CSR_SSTATUS, t6
+       csrs CSR_STATUS, t6
 
        add a3, a1, a2
        /* Use word-oriented copy only if low-order bits match */
@@ -47,7 +47,7 @@ ENTRY(__asm_copy_from_user)
 
 3:
        /* Disable access to user memory */
-       csrc CSR_SSTATUS, t6
+       csrc CSR_STATUS, t6
        li a0, 0
        ret
 4: /* Edge case: unalignment */
@@ -72,7 +72,7 @@ ENTRY(__clear_user)
 
        /* Enable access to user memory */
        li t6, SR_SUM
-       csrs CSR_SSTATUS, t6
+       csrs CSR_STATUS, t6
 
        add a3, a0, a1
        addi t0, a0, SZREG-1
@@ -94,7 +94,7 @@ ENTRY(__clear_user)
 
 3:
        /* Disable access to user memory */
-       csrc CSR_SSTATUS, t6
+       csrc CSR_STATUS, t6
        li a0, 0
        ret
 4: /* Edge case: unalignment */
@@ -114,11 +114,11 @@ ENDPROC(__clear_user)
        /* Fixup code for __copy_user(10) and __clear_user(11) */
 10:
        /* Disable access to user memory */
-       csrs CSR_SSTATUS, t6
+       csrs CSR_STATUS, t6
        mv a0, a2
        ret
 11:
-       csrs CSR_SSTATUS, t6
+       csrs CSR_STATUS, t6
        mv a0, a1
        ret
        .previous
index 9d9a173..44ab8f2 100644 (file)
@@ -6,9 +6,8 @@ CFLAGS_REMOVE_init.o = -pg
 endif
 
 obj-y += init.o
-obj-y += fault.o
 obj-y += extable.o
-obj-y += ioremap.o
+obj-$(CONFIG_MMU) += fault.o ioremap.o
 obj-y += cacheflush.o
 obj-y += context.o
 obj-y += sifive_l2_cache.o
index 3f15938..8f19006 100644 (file)
 
 #include <asm/sbi.h>
 
+static void ipi_remote_fence_i(void *info)
+{
+       return local_flush_icache_all();
+}
+
 void flush_icache_all(void)
 {
-       sbi_remote_fence_i(NULL);
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               sbi_remote_fence_i(NULL);
+       else
+               on_each_cpu(ipi_remote_fence_i, NULL, 1);
 }
 
 /*
@@ -28,7 +36,7 @@ void flush_icache_all(void)
 void flush_icache_mm(struct mm_struct *mm, bool local)
 {
        unsigned int cpu;
-       cpumask_t others, hmask, *mask;
+       cpumask_t others, *mask;
 
        preempt_disable();
 
@@ -46,10 +54,7 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
         */
        cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
        local |= cpumask_empty(&others);
-       if (mm != current->active_mm || !local) {
-               riscv_cpuid_to_hartid_mask(&others, &hmask);
-               sbi_remote_fence_i(hmask.bits);
-       } else {
+       if (mm == current->active_mm && local) {
                /*
                 * It's assumed that at least one strongly ordered operation is
                 * performed on this hart between setting a hart's cpumask bit
@@ -59,6 +64,13 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
                 * with flush_icache_deferred().
                 */
                smp_mb();
+       } else if (IS_ENABLED(CONFIG_RISCV_SBI)) {
+               cpumask_t hartid_mask;
+
+               riscv_cpuid_to_hartid_mask(&others, &hartid_mask);
+               sbi_remote_fence_i(cpumask_bits(&hartid_mask));
+       } else {
+               on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1);
        }
 
        preempt_enable();
@@ -66,6 +78,7 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_MMU
 void flush_icache_pte(pte_t pte)
 {
        struct page *page = pte_page(pte);
@@ -73,3 +86,4 @@ void flush_icache_pte(pte_t pte)
        if (!test_and_set_bit(PG_dcache_clean, &page->flags))
                flush_icache_all();
 }
+#endif /* CONFIG_MMU */
index ca66d44..613ec81 100644 (file)
@@ -58,8 +58,10 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
        cpumask_clear_cpu(cpu, mm_cpumask(prev));
        cpumask_set_cpu(cpu, mm_cpumask(next));
 
+#ifdef CONFIG_MMU
        csr_write(CSR_SATP, virt_to_pfn(next->pgd) | SATP_MODE);
        local_flush_tlb_all();
+#endif
 
        flush_icache_deferred(next);
 }
index 7aed917..2fc7294 100644 (file)
@@ -15,9 +15,9 @@ int fixup_exception(struct pt_regs *regs)
 {
        const struct exception_table_entry *fixup;
 
-       fixup = search_exception_tables(regs->sepc);
+       fixup = search_exception_tables(regs->epc);
        if (fixup) {
-               regs->sepc = fixup->fixup;
+               regs->epc = fixup->fixup;
                return 1;
        }
        return 0;
index 247b8c8..cf7248e 100644 (file)
@@ -34,8 +34,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs)
        int code = SEGV_MAPERR;
        vm_fault_t fault;
 
-       cause = regs->scause;
-       addr = regs->sbadaddr;
+       cause = regs->cause;
+       addr = regs->badaddr;
 
        tsk = current;
        mm = tsk->mm;
@@ -53,7 +53,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs)
                goto vmalloc_fault;
 
        /* Enable interrupts if they were enabled in the parent context. */
-       if (likely(regs->sstatus & SR_SPIE))
+       if (likely(regs->status & SR_PIE))
                local_irq_enable();
 
        /*
index 573463d..b2fe9d1 100644 (file)
@@ -26,6 +26,7 @@ unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
 EXPORT_SYMBOL(empty_zero_page);
 
 extern char _start[];
+void *dtb_early_va;
 
 static void __init zone_sizes_init(void)
 {
@@ -40,7 +41,7 @@ static void __init zone_sizes_init(void)
        free_area_init_nodes(max_zone_pfns);
 }
 
-void setup_zero_page(void)
+static void setup_zero_page(void)
 {
        memset((void *)empty_zero_page, 0, PAGE_SIZE);
 }
@@ -142,12 +143,12 @@ void __init setup_bootmem(void)
        }
 }
 
+#ifdef CONFIG_MMU
 unsigned long va_pa_offset;
 EXPORT_SYMBOL(va_pa_offset);
 unsigned long pfn_base;
 EXPORT_SYMBOL(pfn_base);
 
-void *dtb_early_va;
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
@@ -273,7 +274,6 @@ static void __init create_pmd_mapping(pmd_t *pmdp,
 #define get_pgd_next_virt(__pa)        get_pmd_virt(__pa)
 #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot)     \
        create_pmd_mapping(__nextp, __va, __pa, __sz, __prot)
-#define PTE_PARENT_SIZE                PMD_SIZE
 #define fixmap_pgd_next                fixmap_pmd
 #else
 #define pgd_next_t             pte_t
@@ -281,7 +281,6 @@ static void __init create_pmd_mapping(pmd_t *pmdp,
 #define get_pgd_next_virt(__pa)        get_pte_virt(__pa)
 #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot)     \
        create_pte_mapping(__nextp, __va, __pa, __sz, __prot)
-#define PTE_PARENT_SIZE                PGDIR_SIZE
 #define fixmap_pgd_next                fixmap_pte
 #endif
 
@@ -314,14 +313,11 @@ static void __init create_pgd_mapping(pgd_t *pgdp,
 
 static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
 {
-       uintptr_t map_size = PAGE_SIZE;
-
-       /* Upgrade to PMD/PGDIR mappings whenever possible */
-       if (!(base & (PTE_PARENT_SIZE - 1)) &&
-           !(size & (PTE_PARENT_SIZE - 1)))
-               map_size = PTE_PARENT_SIZE;
+       /* Upgrade to PMD_SIZE mappings whenever possible */
+       if ((base & (PMD_SIZE - 1)) || (size & (PMD_SIZE - 1)))
+               return PAGE_SIZE;
 
-       return map_size;
+       return PMD_SIZE;
 }
 
 /*
@@ -449,6 +445,16 @@ static void __init setup_vm_final(void)
        csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | SATP_MODE);
        local_flush_tlb_all();
 }
+#else
+asmlinkage void __init setup_vm(uintptr_t dtb_pa)
+{
+       dtb_early_va = (void *)dtb_pa;
+}
+
+static inline void setup_vm_final(void)
+{
+}
+#endif /* CONFIG_MMU */
 
 void __init paging_init(void)
 {
index 24cd33d..720b443 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/sched.h>
 #include <asm/sbi.h>
 
 void flush_tlb_all(void)
@@ -9,13 +10,33 @@ void flush_tlb_all(void)
        sbi_remote_sfence_vma(NULL, 0, -1);
 }
 
+/*
+ * This function must not be called with cmask being null.
+ * Kernel may panic if cmask is NULL.
+ */
 static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start,
                                  unsigned long size)
 {
        struct cpumask hmask;
+       unsigned int cpuid;
 
-       riscv_cpuid_to_hartid_mask(cmask, &hmask);
-       sbi_remote_sfence_vma(hmask.bits, start, size);
+       if (cpumask_empty(cmask))
+               return;
+
+       cpuid = get_cpu();
+
+       if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
+               /* local cpu is the only cpu present in cpumask */
+               if (size <= PAGE_SIZE)
+                       local_flush_tlb_page(start);
+               else
+                       local_flush_tlb_all();
+       } else {
+               riscv_cpuid_to_hartid_mask(cmask, &hmask);
+               sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size);
+       }
+
+       put_cpu();
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
index 470c7ef..4e54856 100644 (file)
@@ -3,9 +3,9 @@
  * Copyright (C) 2012 Regents of the University of California
  * Copyright (C) 2017 SiFive
  *
- * All RISC-V systems have a timer attached to every hart.  These timers can be
- * read from the "time" and "timeh" CSRs, and can use the SBI to setup
- * events.
+ * All RISC-V systems have a timer attached to every hart.  These timers can
+ * either be read from the "time" and "timeh" CSRs, and can use the SBI to
+ * setup events, or directly accessed using MMIO registers.
  */
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/sched_clock.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 #include <asm/smp.h>
 #include <asm/sbi.h>
 
+u64 __iomem *riscv_time_cmp;
+u64 __iomem *riscv_time_val;
+
+static inline void mmio_set_timer(u64 val)
+{
+       void __iomem *r;
+
+       r = riscv_time_cmp + cpuid_to_hartid_map(smp_processor_id());
+       writeq_relaxed(val, r);
+}
+
 static int riscv_clock_next_event(unsigned long delta,
                struct clock_event_device *ce)
 {
-       csr_set(sie, SIE_STIE);
-       sbi_set_timer(get_cycles64() + delta);
+       csr_set(CSR_IE, IE_TIE);
+       if (IS_ENABLED(CONFIG_RISCV_SBI))
+               sbi_set_timer(get_cycles64() + delta);
+       else
+               mmio_set_timer(get_cycles64() + delta);
        return 0;
 }
 
@@ -61,13 +76,13 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
        ce->cpumask = cpumask_of(cpu);
        clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
 
-       csr_set(sie, SIE_STIE);
+       csr_set(CSR_IE, IE_TIE);
        return 0;
 }
 
 static int riscv_timer_dying_cpu(unsigned int cpu)
 {
-       csr_clear(sie, SIE_STIE);
+       csr_clear(CSR_IE, IE_TIE);
        return 0;
 }
 
@@ -76,7 +91,7 @@ void riscv_timer_interrupt(void)
 {
        struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
 
-       csr_clear(sie, SIE_STIE);
+       csr_clear(CSR_IE, IE_TIE);
        evdev->event_handler(evdev);
 }
 
index 7d0a12f..8df547d 100644 (file)
@@ -181,7 +181,7 @@ static void plic_handle_irq(struct pt_regs *regs)
 
        WARN_ON_ONCE(!handler->present);
 
-       csr_clear(sie, SIE_SEIE);
+       csr_clear(CSR_IE, IE_EIE);
        while ((hwirq = readl(claim))) {
                int irq = irq_find_mapping(plic_irqdomain, hwirq);
 
@@ -191,7 +191,7 @@ static void plic_handle_irq(struct pt_regs *regs)
                else
                        generic_handle_irq(irq);
        }
-       csr_set(sie, SIE_SEIE);
+       csr_set(CSR_IE, IE_EIE);
 }
 
 /*
@@ -252,8 +252,11 @@ static int __init plic_init(struct device_node *node,
                        continue;
                }
 
-               /* skip contexts other than supervisor external interrupt */
-               if (parent.args[0] != IRQ_S_EXT)
+               /*
+                * Skip contexts other than external interrupts for our
+                * privilege level.
+                */
+               if (parent.args[0] != IRQ_EXT)
                        continue;
 
                hartid = plic_find_hart_id(parent.np);
index 4d22b91..4487a6b 100644 (file)
@@ -89,7 +89,7 @@ config HVC_DCC
 
 config HVC_RISCV_SBI
        bool "RISC-V SBI console support"
-       depends on RISCV
+       depends on RISCV_SBI
        select HVC_DRIVER
        help
          This enables support for console output via RISC-V SBI calls, which
index 67a9eb3..540142c 100644 (file)
@@ -88,7 +88,7 @@ config SERIAL_EARLYCON_ARM_SEMIHOST
 
 config SERIAL_EARLYCON_RISCV_SBI
        bool "Early console using RISC-V SBI"
-       depends on RISCV
+       depends on RISCV_SBI
        select SERIAL_CORE
        select SERIAL_CORE_CONSOLE
        select SERIAL_EARLYCON
index 7f8b5c8..aeb0fc3 100644 (file)
@@ -112,6 +112,8 @@ struct seccomp_data {
 #  define __NR_seccomp 383
 # elif defined(__aarch64__)
 #  define __NR_seccomp 277
+# elif defined(__riscv)
+#  define __NR_seccomp 277
 # elif defined(__hppa__)
 #  define __NR_seccomp 338
 # elif defined(__powerpc__)
@@ -1587,6 +1589,10 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # define ARCH_REGS     struct user_pt_regs
 # define SYSCALL_NUM   regs[8]
 # define SYSCALL_RET   regs[0]
+#elif defined(__riscv) && __riscv_xlen == 64
+# define ARCH_REGS     struct user_regs_struct
+# define SYSCALL_NUM   a7
+# define SYSCALL_RET   a0
 #elif defined(__hppa__)
 # define ARCH_REGS     struct user_regs_struct
 # define SYSCALL_NUM   gr[20]
@@ -1676,7 +1682,7 @@ void change_syscall(struct __test_metadata *_metadata,
        EXPECT_EQ(0, ret) {}
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
-    defined(__s390__) || defined(__hppa__)
+       defined(__s390__) || defined(__hppa__) || defined(__riscv)
        {
                regs.SYSCALL_NUM = syscall;
        }