]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
Merge tag 'riscv-for-linus-5.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Aug 2022 01:39:43 +0000 (18:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Aug 2022 01:39:43 +0000 (18:39 -0700)
Pull more RISC-V updates from Palmer Dabbelt:
 "There's still a handful of new features in here, but there are a lot
  of fixes/cleanups as well:

   - Support for the Zicbom extension for explicit cache-block
     management, along with the necessary bits to make the non-standard
     cache management ops on the Allwinner D1 function

   - Support for the Zihintpause extension, which codifies a go-slow
     instruction used for cpu_relax()

   - Support for the Sstc extension for supervisor-mode timer/counter
     management

   - Many device tree fixes and cleanups, including a large set for the
     Canaan device trees

   - A handful of fixes and cleanups for the PMU driver"

* tag 'riscv-for-linus-5.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (43 commits)
  dt-bindings: gpio: sifive: add gpio-line-names
  wireguard: selftests: set CONFIG_NONPORTABLE on riscv32
  RISC-V: KVM: Support sstc extension
  RISC-V: Improve SBI definitions
  RISC-V: Move counter info definition to sbi header file
  RISC-V: Fix SBI PMU calls for RV32
  RISC-V: Update user page mapping only once during start
  RISC-V: Fix counter restart during overflow for RV32
  RISC-V: Prefer sstc extension if available
  RISC-V: Enable sstc extension parsing from DT
  RISC-V: Add SSTC extension CSR details
  riscv:uprobe fix SR_SPIE set/clear handling
  dt-bindings: riscv: fix SiFive l2-cache's cache-sets
  riscv: ensure cpu_ops_sbi is declared
  RISC-V: cpu_ops_spinwait.c should include head.h
  RISC-V: Declare cpu_ops_spinwait in <asm/cpu_ops.h>
  riscv: dts: starfive: correct number of external interrupts
  riscv: dts: sifive unmatched: Add PWM controlled LEDs
  riscv/purgatory: Omit use of bin2c
  riscv/purgatory: hard-code obj-y in Makefile
  ...

54 files changed:
Documentation/devicetree/bindings/display/ilitek,ili9341.txt [deleted file]
Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
Documentation/devicetree/bindings/memory-controllers/canaan,k210-sram.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml
arch/riscv/Kconfig
arch/riscv/Kconfig.erratas
arch/riscv/Makefile
arch/riscv/boot/dts/canaan/Makefile
arch/riscv/boot/dts/canaan/canaan_kd233.dts
arch/riscv/boot/dts/canaan/k210.dtsi
arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
arch/riscv/boot/dts/starfive/jh7100.dtsi
arch/riscv/errata/thead/errata.c
arch/riscv/include/asm/cache.h
arch/riscv/include/asm/cacheflush.h
arch/riscv/include/asm/cpu_ops.h
arch/riscv/include/asm/cpu_ops_sbi.h
arch/riscv/include/asm/csr.h
arch/riscv/include/asm/errata_list.h
arch/riscv/include/asm/hwcap.h
arch/riscv/include/asm/kvm_vcpu_timer.h
arch/riscv/include/asm/sbi.h
arch/riscv/include/asm/vdso/processor.h
arch/riscv/include/uapi/asm/kvm.h
arch/riscv/kernel/cpu.c
arch/riscv/kernel/cpu_ops.c
arch/riscv/kernel/cpu_ops_spinwait.c
arch/riscv/kernel/cpufeature.c
arch/riscv/kernel/crash_save_regs.S
arch/riscv/kernel/machine_kexec.c
arch/riscv/kernel/probes/uprobes.c
arch/riscv/kernel/setup.c
arch/riscv/kernel/traps_misaligned.c
arch/riscv/kvm/vcpu.c
arch/riscv/kvm/vcpu_timer.c
arch/riscv/lib/uaccess.S
arch/riscv/mm/Makefile
arch/riscv/mm/dma-noncoherent.c [new file with mode: 0644]
arch/riscv/mm/init.c
arch/riscv/purgatory/.gitignore
arch/riscv/purgatory/Makefile
arch/riscv/purgatory/kexec-purgatory.S [new file with mode: 0644]
drivers/clocksource/timer-riscv.c
drivers/of/address.c
drivers/perf/riscv_pmu.c
drivers/perf/riscv_pmu_sbi.c
scripts/remove-stale-files
tools/testing/selftests/wireguard/qemu/arch/riscv32.config

diff --git a/Documentation/devicetree/bindings/display/ilitek,ili9341.txt b/Documentation/devicetree/bindings/display/ilitek,ili9341.txt
deleted file mode 100644 (file)
index 169b32e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-Ilitek ILI9341 display panels
-
-This binding is for display panels using an Ilitek ILI9341 controller in SPI
-mode.
-
-Required properties:
-- compatible:  "adafruit,yx240qv29", "ilitek,ili9341"
-- dc-gpios:    D/C pin
-- reset-gpios: Reset pin
-
-The node for this driver must be a child node of a SPI controller, hence
-all mandatory properties described in ../spi/spi-bus.txt must be specified.
-
-Optional properties:
-- rotation:    panel rotation in degrees counter clockwise (0,90,180,270)
-- backlight:   phandle of the backlight device attached to the panel
-
-Example:
-       display@0{
-               compatible = "adafruit,yx240qv29", "ilitek,ili9341";
-               reg = <0>;
-               spi-max-frequency = <32000000>;
-               dc-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
-               reset-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
-               rotation = <270>;
-               backlight = <&backlight>;
-       };
index 6058948a976497cbff0876faed17bb635a836626..99e0cb9440cf255a2a0d7c3255a8253c4b190849 100644 (file)
@@ -21,8 +21,10 @@ properties:
   compatible:
     items:
       - enum:
+          - adafruit,yx240qv29
           # ili9341 240*320 Color on stm32f429-disco board
           - st,sf-tc240t-9370-t
+          - canaan,kd233-tft
       - const: ilitek,ili9341
 
   reg: true
@@ -47,31 +49,50 @@ properties:
   vddi-led-supply:
     description: Voltage supply for the LED driver (1.65 .. 3.3 V)
 
-additionalProperties: false
+unevaluatedProperties: false
 
 required:
   - compatible
   - reg
   - dc-gpios
-  - port
+
+if:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - st,sf-tc240t-9370-t
+then:
+  required:
+    - port
 
 examples:
   - |+
+    #include <dt-bindings/gpio/gpio.h>
     spi {
         #address-cells = <1>;
         #size-cells = <0>;
         panel: display@0 {
-                 compatible = "st,sf-tc240t-9370-t",
-                              "ilitek,ili9341";
-                 reg = <0>;
-                 spi-3wire;
-                 spi-max-frequency = <10000000>;
-                 dc-gpios = <&gpiod 13 0>;
-                 port {
-                         panel_in: endpoint {
-                           remote-endpoint = <&display_out>;
-                      };
-                 };
-             };
+            compatible = "st,sf-tc240t-9370-t",
+                         "ilitek,ili9341";
+            reg = <0>;
+            spi-3wire;
+            spi-max-frequency = <10000000>;
+            dc-gpios = <&gpiod 13 0>;
+            port {
+                panel_in: endpoint {
+                    remote-endpoint = <&display_out>;
+                };
+            };
+        };
+        display@1{
+            compatible = "adafruit,yx240qv29", "ilitek,ili9341";
+            reg = <1>;
+            spi-max-frequency = <10000000>;
+            dc-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
+            reset-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+            rotation = <270>;
+            backlight = <&backlight>;
         };
+    };
 ...
index 939e31c4808116b4017e9c1016e14457611a256e..fc095646adeae0ef37ef92a19f88af651b44abd3 100644 (file)
@@ -46,6 +46,10 @@ properties:
     maximum: 32
     default: 16
 
+  gpio-line-names:
+    minItems: 1
+    maxItems: 32
+
   gpio-controller: true
 
 required:
diff --git a/Documentation/devicetree/bindings/memory-controllers/canaan,k210-sram.yaml b/Documentation/devicetree/bindings/memory-controllers/canaan,k210-sram.yaml
new file mode 100644 (file)
index 0000000..f81fb86
--- /dev/null
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/canaan,k210-sram.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Canaan K210 SRAM memory controller
+
+description:
+  The Canaan K210 SRAM memory controller is responsible for the system's 8 MiB
+  of SRAM. The controller is initialised by the bootloader, which configures
+  its clocks, before OS bringup.
+
+maintainers:
+  - Conor Dooley <conor@kernel.org>
+
+properties:
+  compatible:
+    enum:
+      - canaan,k210-sram
+
+  clocks:
+    minItems: 1
+    items:
+      - description: sram0 clock
+      - description: sram1 clock
+      - description: aisram clock
+
+  clock-names:
+    minItems: 1
+    items:
+      - const: sram0
+      - const: sram1
+      - const: aisram
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/k210-clk.h>
+    memory-controller {
+        compatible = "canaan,k210-sram";
+        clocks = <&sysclk K210_CLK_SRAM0>,
+                 <&sysclk K210_CLK_SRAM1>,
+                 <&sysclk K210_CLK_AI>;
+        clock-names = "sram0", "sram1", "aisram";
+    };
index d632ac76532e9b5a7b4975b070845a0a619b427b..873dd12f6e896d720fb3fe46fc27fb6139344d4d 100644 (file)
@@ -63,6 +63,11 @@ properties:
       - riscv,sv48
       - riscv,none
 
+  riscv,cbom-block-size:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      The blocksize in bytes for the Zicbom cache operations.
+
   riscv,isa:
     description:
       Identifies the specific RISC-V instruction set architecture
index e2d330bd4608ab973b2753c362bebe0e696df5c8..69cdab18d6294935e22f3ef0b5e78bf2bb2cde1f 100644 (file)
@@ -46,7 +46,7 @@ properties:
     const: 2
 
   cache-sets:
-    const: 1024
+    enum: [1024, 2048]
 
   cache-size:
     const: 2097152
@@ -84,6 +84,8 @@ then:
       description: |
         Must contain entries for DirError, DataError and DataFail signals.
       maxItems: 3
+    cache-sets:
+      const: 1024
 
 else:
   properties:
@@ -91,6 +93,8 @@ else:
       description: |
         Must contain entries for DirError, DataError, DataFail, DirFail signals.
       minItems: 4
+    cache-sets:
+      const: 2048
 
 additionalProperties: false
 
index 5c52a82e83a88e8de4c2a0b2ce2173dd694e4174..ed66c31e465590f94c447a1fee2b590e237073e2 100644 (file)
@@ -113,6 +113,7 @@ config RISCV
        select MODULES_USE_ELF_RELA if MODULES
        select MODULE_SECTIONS if MODULES
        select OF
+       select OF_DMA_DEFAULT_COHERENT
        select OF_EARLY_FLATTREE
        select OF_IRQ
        select PCI_DOMAINS_GENERIC if PCI
@@ -218,6 +219,14 @@ config PGTABLE_LEVELS
 config LOCKDEP_SUPPORT
        def_bool y
 
+config RISCV_DMA_NONCOHERENT
+       bool
+       select ARCH_HAS_DMA_PREP_COHERENT
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
+       select ARCH_HAS_SYNC_DMA_FOR_CPU
+       select ARCH_HAS_SETUP_DMA_OPS
+       select DMA_DIRECT_REMAP
+
 source "arch/riscv/Kconfig.socs"
 source "arch/riscv/Kconfig.erratas"
 
@@ -392,6 +401,28 @@ config RISCV_ISA_SVPBMT
 
           If you don't know what to do here, say Y.
 
+config CC_HAS_ZICBOM
+       bool
+       default y if 64BIT && $(cc-option,-mabi=lp64 -march=rv64ima_zicbom)
+       default y if 32BIT && $(cc-option,-mabi=ilp32 -march=rv32ima_zicbom)
+
+config RISCV_ISA_ZICBOM
+       bool "Zicbom extension support for non-coherent DMA operation"
+       depends on CC_HAS_ZICBOM
+       depends on !XIP_KERNEL && MMU
+       select RISCV_DMA_NONCOHERENT
+       select RISCV_ALTERNATIVE
+       default y
+       help
+          Adds support to dynamically detect the presence of the ZICBOM
+          extension (Cache Block Management Operations) and enable its
+          usage.
+
+          The Zicbom extension can be used to handle for example
+          non-coherent DMA support on devices that need it.
+
+          If you don't know what to do here, say Y.
+
 config FPU
        bool "FPU support"
        default y
@@ -463,7 +494,6 @@ config KEXEC_FILE
 
 config ARCH_HAS_KEXEC_PURGATORY
        def_bool KEXEC_FILE
-       select BUILD_BIN2C
        depends on CRYPTO=y
        depends on CRYPTO_SHA256=y
 
index f62b62807e853a7a608bb47a516c02220b25f64b..6850e9389930240eab28852e1c4f8f7bd3f07fc3 100644 (file)
@@ -55,4 +55,15 @@ config ERRATA_THEAD_PBMT
 
          If you don't know what to do here, say "Y".
 
+config ERRATA_THEAD_CMO
+       bool "Apply T-Head cache management errata"
+       depends on ERRATA_THEAD
+       select RISCV_DMA_NONCOHERENT
+       default y
+       help
+         This will apply the cache management errata to handle the
+         non-standard handling on non-coherent operations on T-Head SoCs.
+
+         If you don't know what to do here, say "Y".
+
 endmenu # "CPU errata selection"
index 81029d40a6727a887d4cb142d0ad5e8659b82b98..3fa8ef336822438570a95b613d7d89d2ed8872ce 100644 (file)
@@ -56,6 +56,14 @@ riscv-march-$(CONFIG_RISCV_ISA_C)    := $(riscv-march-y)c
 toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
 riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
 
+# Check if the toolchain supports Zicbom extension
+toolchain-supports-zicbom := $(call cc-option-yn, -march=$(riscv-march-y)_zicbom)
+riscv-march-$(toolchain-supports-zicbom) := $(riscv-march-y)_zicbom
+
+# Check if the toolchain supports Zihintpause extension
+toolchain-supports-zihintpause := $(call cc-option-yn, -march=$(riscv-march-y)_zihintpause)
+riscv-march-$(toolchain-supports-zihintpause) := $(riscv-march-y)_zihintpause
+
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
 
index c61b08ac8554dcb5fb001ca34d1f8a80d06326da..befe4eb7527b8fff59c37121dfbbf8404c37d41d 100644 (file)
@@ -1,3 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += $(addsuffix .dtb, $(CONFIG_SOC_CANAAN_K210_DTB_SOURCE))
-obj-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += $(addsuffix .o, $(dtb-y))
+dtb-$(CONFIG_SOC_CANAAN) += canaan_kd233.dtb
+dtb-$(CONFIG_SOC_CANAAN) += k210_generic.dtb
+dtb-$(CONFIG_SOC_CANAAN) += sipeed_maix_bit.dtb
+dtb-$(CONFIG_SOC_CANAAN) += sipeed_maix_dock.dtb
+dtb-$(CONFIG_SOC_CANAAN) += sipeed_maix_go.dtb
+dtb-$(CONFIG_SOC_CANAAN) += sipeed_maixduino.dtb
+
+obj-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += $(addsuffix .dtb.o, $(CONFIG_SOC_CANAAN_K210_DTB_SOURCE))
index f72540bd14a3be3f05222d5f0bacc31b5f3f6f44..8df4cf3656f2c93249f0576fe6b10529b5ccd335 100644 (file)
        cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
 
        panel@0 {
-               compatible = "ilitek,ili9341";
+               compatible = "canaan,kd233-tft", "ilitek,ili9341";
                reg = <0>;
                dc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
-               spi-max-frequency = <15000000>;
+               spi-max-frequency = <10000000>;
                status = "disabled";
        };
 };
        cs-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
        status = "okay";
 
-       slot@0 {
+       mmc@0 {
                compatible = "mmc-spi-slot";
                reg = <0>;
                voltage-ranges = <3300 3300>;
index ec944d1537dc40ea3e40ad5a1bd72c09a6a6992c..07e2e2649604640156aa61b6c7594b3c23e7a902 100644 (file)
 
        sram: memory@80000000 {
                device_type = "memory";
+               reg = <0x80000000 0x400000>, /* sram0 4 MiB */
+                     <0x80400000 0x200000>, /* sram1 2 MiB */
+                     <0x80600000 0x200000>; /* aisram 2 MiB */
+       };
+
+       sram_controller: memory-controller {
                compatible = "canaan,k210-sram";
-               reg = <0x80000000 0x400000>,
-                     <0x80400000 0x200000>,
-                     <0x80600000 0x200000>;
-               reg-names = "sram0", "sram1", "aisram";
                clocks = <&sysclk K210_CLK_SRAM0>,
                         <&sysclk K210_CLK_SRAM1>,
                         <&sysclk K210_CLK_AI>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "simple-pm-bus";
-                       ranges;
+                       ranges = <0x50200000 0x50200000 0x200000>;
                        clocks = <&sysclk K210_CLK_APB0>;
 
                        gpio1: gpio@50200000 {
                        };
 
                        i2s0: i2s@50250000 {
-                               compatible = "snps,designware-i2s";
+                               compatible = "canaan,k210-i2s", "snps,designware-i2s";
                                reg = <0x50250000 0x200>;
                                interrupts = <5>;
                                clocks = <&sysclk K210_CLK_I2S0>;
                        };
 
                        i2s1: i2s@50260000 {
-                               compatible = "snps,designware-i2s";
+                               compatible = "canaan,k210-i2s", "snps,designware-i2s";
                                reg = <0x50260000 0x200>;
                                interrupts = <6>;
                                clocks = <&sysclk K210_CLK_I2S1>;
                        };
 
                        i2s2: i2s@50270000 {
-                               compatible = "snps,designware-i2s";
+                               compatible = "canaan,k210-i2s", "snps,designware-i2s";
                                reg = <0x50270000 0x200>;
                                interrupts = <7>;
                                clocks = <&sysclk K210_CLK_I2S2>;
 
                        timer0: timer@502d0000 {
                                compatible = "snps,dw-apb-timer";
-                               reg = <0x502D0000 0x100>;
-                               interrupts = <14>, <15>;
+                               reg = <0x502D0000 0x14>;
+                               interrupts = <14>;
                                clocks = <&sysclk K210_CLK_TIMER0>,
                                         <&sysclk K210_CLK_APB0>;
                                clock-names = "timer", "pclk";
                                resets = <&sysrst K210_RST_TIMER0>;
                        };
 
-                       timer1: timer@502e0000 {
+                       timer1: timer@502d0014 {
+                               compatible = "snps,dw-apb-timer";
+                               reg = <0x502D0014 0x14>;
+                               interrupts = <15>;
+                               clocks = <&sysclk K210_CLK_TIMER0>,
+                                        <&sysclk K210_CLK_APB0>;
+                               clock-names = "timer", "pclk";
+                               resets = <&sysrst K210_RST_TIMER0>;
+                       };
+
+                       timer2: timer@502e0000 {
+                               compatible = "snps,dw-apb-timer";
+                               reg = <0x502E0000 0x14>;
+                               interrupts = <16>;
+                               clocks = <&sysclk K210_CLK_TIMER1>,
+                                        <&sysclk K210_CLK_APB0>;
+                               clock-names = "timer", "pclk";
+                               resets = <&sysrst K210_RST_TIMER1>;
+                       };
+
+                       timer3: timer@502e0014 {
                                compatible = "snps,dw-apb-timer";
-                               reg = <0x502E0000 0x100>;
-                               interrupts = <16>, <17>;
+                               reg = <0x502E0014 0x114>;
+                               interrupts = <17>;
                                clocks = <&sysclk K210_CLK_TIMER1>,
                                         <&sysclk K210_CLK_APB0>;
                                clock-names = "timer", "pclk";
                                resets = <&sysrst K210_RST_TIMER1>;
                        };
 
-                       timer2: timer@502f0000 {
+                       timer4: timer@502f0000 {
                                compatible = "snps,dw-apb-timer";
-                               reg = <0x502F0000 0x100>;
-                               interrupts = <18>, <19>;
+                               reg = <0x502F0000 0x14>;
+                               interrupts = <18>;
+                               clocks = <&sysclk K210_CLK_TIMER2>,
+                                        <&sysclk K210_CLK_APB0>;
+                               clock-names = "timer", "pclk";
+                               resets = <&sysrst K210_RST_TIMER2>;
+                       };
+
+                       timer5: timer@502f0014 {
+                               compatible = "snps,dw-apb-timer";
+                               reg = <0x502F0014 0x14>;
+                               interrupts = <19>;
                                clocks = <&sysclk K210_CLK_TIMER2>,
                                         <&sysclk K210_CLK_APB0>;
                                clock-names = "timer", "pclk";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "simple-pm-bus";
-                       ranges;
+                       ranges = <0x50400000 0x50400000 0x40100>;
                        clocks = <&sysclk K210_CLK_APB1>;
 
                        wdt0: watchdog@50400000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "simple-pm-bus";
-                       ranges;
+                       ranges = <0x52000000 0x52000000 0x2000200>;
                        clocks = <&sysclk K210_CLK_APB2>;
 
                        spi0: spi@52000000 {
                                clock-names = "ssi_clk", "pclk";
                                resets = <&sysrst K210_RST_SPI0>;
                                reset-names = "spi";
-                               spi-max-frequency = <25000000>;
                                num-cs = <4>;
                                reg-io-width = <4>;
                        };
                                clock-names = "ssi_clk", "pclk";
                                resets = <&sysrst K210_RST_SPI1>;
                                reset-names = "spi";
-                               spi-max-frequency = <25000000>;
                                num-cs = <4>;
                                reg-io-width = <4>;
                        };
                                clock-names = "ssi_clk", "pclk";
                                resets = <&sysrst K210_RST_SPI3>;
                                reset-names = "spi";
-                               /* Could possibly go up to 200 MHz */
-                               spi-max-frequency = <100000000>;
+
                                num-cs = <4>;
                                reg-io-width = <4>;
                        };
index 8abdbe26a1d098583f99b4e87116b5dbc6acf45b..6d25bf07481a6ed8ecbe74e10316825f630cc559 100644 (file)
        cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
        status = "okay";
 
-       slot@0 {
+       mmc@0 {
                compatible = "mmc-spi-slot";
                reg = <0>;
                voltage-ranges = <3300 3300>;
index 3c6df1ecf76fd7f3534fdc557837ffad5e2ad1f1..f4f4d8d5e8b88cad89664f6c6d4e105f97e44c92 100644 (file)
        cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
        status = "okay";
 
-       slot@0 {
+       mmc@0 {
                compatible = "mmc-spi-slot";
                reg = <0>;
                voltage-ranges = <3300 3300>;
index 03c9843d503e6fc23cd3196c82aae6a96164a543..0d86df47e1ed3987afd424db059ec5a271bf0fdf 100644 (file)
        cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
        status = "okay";
 
-       slot@0 {
+       mmc@0 {
                compatible = "mmc-spi-slot";
                reg = <0>;
                voltage-ranges = <3300 3300>;
index 7164ad06317812d7ee53fc81871345b98e69a77b..5c05c498e2b88bf4f6310b4168e47ef810f33745 100644 (file)
        cs-gpios = <&gpio1_0 2 GPIO_ACTIVE_LOW>;
        status = "okay";
 
-       slot@0 {
+       mmc@0 {
                compatible = "mmc-spi-slot";
                reg = <0>;
                voltage-ranges = <3300 3300>;
index 1f386b07a832d294257132a55362c1e995751d92..07387f9c135ca7e8ddf7d45de10ccdb933a2e4d4 100644 (file)
@@ -4,6 +4,8 @@
 #include "fu740-c000.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pwm/pwm.h>
 
 /* Clock frequency (in Hz) of the PCB crystal for rtcclk */
 #define RTCCLK_FREQ            1000000
                compatible = "gpio-poweroff";
                gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
        };
+
+       led-controller-1 {
+               compatible = "pwm-leds";
+
+               led-d12 {
+                       pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
+                       active-low;
+                       color = <LED_COLOR_ID_GREEN>;
+                       max-brightness = <255>;
+                       label = "d12";
+               };
+       };
+
+       led-controller-2 {
+               compatible = "pwm-leds-multicolor";
+
+               multi-led {
+                       color = <LED_COLOR_ID_RGB>;
+                       max-brightness = <255>;
+                       label = "d2";
+
+                       led-red {
+                               pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>;
+                               active-low;
+                               color = <LED_COLOR_ID_RED>;
+                       };
+
+                       led-green {
+                               pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>;
+                               active-low;
+                               color = <LED_COLOR_ID_GREEN>;
+                       };
+
+                       led-blue {
+                               pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>;
+                               active-low;
+                               color = <LED_COLOR_ID_BLUE>;
+                       };
+               };
+       };
 };
 
 &uart0 {
index c617a61e26e28b38cdbd4300117f252782774aa7..000447482acaa504020b9994c7e2701c8e09eb8d 100644 (file)
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <1>;
-                       riscv,ndev = <127>;
+                       riscv,ndev = <133>;
                };
 
                clkgen: clock-controller@11800000 {
index b37b6fedd53bc50932e87a49a02b59222e93391f..202c83f677b2ede1bc0992fffb91442930ffa74b 100644 (file)
@@ -27,6 +27,23 @@ static bool errata_probe_pbmt(unsigned int stage,
        return false;
 }
 
+static bool errata_probe_cmo(unsigned int stage,
+                            unsigned long arch_id, unsigned long impid)
+{
+#ifdef CONFIG_ERRATA_THEAD_CMO
+       if (arch_id != 0 || impid != 0)
+               return false;
+
+       if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
+               return false;
+
+       riscv_noncoherent_supported();
+       return true;
+#else
+       return false;
+#endif
+}
+
 static u32 thead_errata_probe(unsigned int stage,
                              unsigned long archid, unsigned long impid)
 {
@@ -35,6 +52,9 @@ static u32 thead_errata_probe(unsigned int stage,
        if (errata_probe_pbmt(stage, archid, impid))
                cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
 
+       if (errata_probe_cmo(stage, archid, impid))
+               cpu_req_errata |= (1U << ERRATA_THEAD_CMO);
+
        return cpu_req_errata;
 }
 
index 9b58b104559ee8c535d99a9ce63a93a29c09cfa9..d3036df23ccbba79830dbd37528ea8c937743e8d 100644 (file)
 
 #define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
 
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
+#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
+#endif
+
 /*
  * RISC-V requires the stack pointer to be 16-byte aligned, so ensure that
  * the flat loader aligns it accordingly.
index 23ff7035099261a7c8cc972bb0259aca45437fc7..a60acaecfedab6ad09e578b1f1a98b04a08541c7 100644 (file)
@@ -42,6 +42,16 @@ void flush_icache_mm(struct mm_struct *mm, bool local);
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_RISCV_ISA_ZICBOM
+void riscv_init_cbom_blocksize(void);
+#else
+static inline void riscv_init_cbom_blocksize(void) { }
+#endif
+
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
+void riscv_noncoherent_supported(void);
+#endif
+
 /*
  * Bits in sys_riscv_flush_icache()'s flags argument.
  */
index 134590f1b84359f47da63b838d1300d63d456aca..aa128466c4d4ec7b533dd8403d8c43e97aff0eac 100644 (file)
@@ -38,6 +38,7 @@ struct cpu_operations {
 #endif
 };
 
+extern const struct cpu_operations cpu_ops_spinwait;
 extern const struct cpu_operations *cpu_ops[NR_CPUS];
 void __init cpu_set_ops(int cpu);
 
index 56e4b76d09ff5317b17d08450b242c940908bea4..d6e4665b31954ca5edfa2f078e3af632c81fbc3f 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 
+extern const struct cpu_operations cpu_ops_sbi;
+
 /**
  * struct sbi_hart_boot_data - Hart specific boot used during booting and
  *                            cpu hotplug.
index 17516afc389a9e4869cfd295c9d57cf4d04dbe58..0e571f6483d92842aa8e8a78796813baeb97ca83 100644 (file)
 #define CSR_SIP                        0x144
 #define CSR_SATP               0x180
 
+#define CSR_STIMECMP           0x14D
+#define CSR_STIMECMPH          0x15D
+
 #define CSR_VSSTATUS           0x200
 #define CSR_VSIE               0x204
 #define CSR_VSTVEC             0x205
 #define CSR_VSTVAL             0x243
 #define CSR_VSIP               0x244
 #define CSR_VSATP              0x280
+#define CSR_VSTIMECMP          0x24D
+#define CSR_VSTIMECMPH         0x25D
 
 #define CSR_HSTATUS            0x600
 #define CSR_HEDELEG            0x602
index 398e351e7002e784d2af00c5c544514813dfb2ce..19a771085781a69da552b1daaa31b6b325a17a9a 100644 (file)
 
 #ifdef CONFIG_ERRATA_THEAD
 #define        ERRATA_THEAD_PBMT 0
-#define        ERRATA_THEAD_NUMBER 1
+#define        ERRATA_THEAD_CMO 1
+#define        ERRATA_THEAD_NUMBER 2
 #endif
 
 #define        CPUFEATURE_SVPBMT 0
-#define        CPUFEATURE_NUMBER 1
+#define        CPUFEATURE_ZICBOM 1
+#define        CPUFEATURE_NUMBER 2
 
 #ifdef __ASSEMBLY__
 
@@ -87,6 +89,59 @@ asm volatile(ALTERNATIVE(                                            \
 #define ALT_THEAD_PMA(_val)
 #endif
 
+/*
+ * dcache.ipa rs1 (invalidate, physical address)
+ * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
+ *   0000001    01010      rs1       000      00000  0001011
+ * dache.iva rs1 (invalida, virtual address)
+ *   0000001    00110      rs1       000      00000  0001011
+ *
+ * dcache.cpa rs1 (clean, physical address)
+ * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
+ *   0000001    01001      rs1       000      00000  0001011
+ * dcache.cva rs1 (clean, virtual address)
+ *   0000001    00100      rs1       000      00000  0001011
+ *
+ * dcache.cipa rs1 (clean then invalidate, physical address)
+ * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
+ *   0000001    01011      rs1       000      00000  0001011
+ * dcache.civa rs1 (... virtual address)
+ *   0000001    00111      rs1       000      00000  0001011
+ *
+ * sync.s (make sure all cache operations finished)
+ * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
+ *   0000000    11001     00000      000      00000  0001011
+ */
+#define THEAD_inval_A0 ".long 0x0265000b"
+#define THEAD_clean_A0 ".long 0x0245000b"
+#define THEAD_flush_A0 ".long 0x0275000b"
+#define THEAD_SYNC_S   ".long 0x0190000b"
+
+#define ALT_CMO_OP(_op, _start, _size, _cachesize)                     \
+asm volatile(ALTERNATIVE_2(                                            \
+       __nops(6),                                                      \
+       "mv a0, %1\n\t"                                                 \
+       "j 2f\n\t"                                                      \
+       "3:\n\t"                                                        \
+       "cbo." __stringify(_op) " (a0)\n\t"                             \
+       "add a0, a0, %0\n\t"                                            \
+       "2:\n\t"                                                        \
+       "bltu a0, %2, 3b\n\t"                                           \
+       "nop", 0, CPUFEATURE_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,           \
+       "mv a0, %1\n\t"                                                 \
+       "j 2f\n\t"                                                      \
+       "3:\n\t"                                                        \
+       THEAD_##_op##_A0 "\n\t"                                         \
+       "add a0, a0, %0\n\t"                                            \
+       "2:\n\t"                                                        \
+       "bltu a0, %2, 3b\n\t"                                           \
+       THEAD_SYNC_S, THEAD_VENDOR_ID,                                  \
+                       ERRATA_THEAD_CMO, CONFIG_ERRATA_THEAD_CMO)      \
+       : : "r"(_cachesize),                                            \
+           "r"((unsigned long)(_start) & ~((_cachesize) - 1UL)),       \
+           "r"((unsigned long)(_start) + (_size))                      \
+       : "a0")
+
 #endif /* __ASSEMBLY__ */
 
 #endif
index e48eebdd26315eb457a9f5e759ffa9eb951dd467..6f59ec64175efd2781635c01e34bb26f80d689fb 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _ASM_RISCV_HWCAP_H
 #define _ASM_RISCV_HWCAP_H
 
+#include <asm/errno.h>
 #include <linux/bits.h>
 #include <uapi/asm/hwcap.h>
 
@@ -54,6 +55,9 @@ extern unsigned long elf_hwcap;
 enum riscv_isa_ext_id {
        RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
        RISCV_ISA_EXT_SVPBMT,
+       RISCV_ISA_EXT_ZICBOM,
+       RISCV_ISA_EXT_ZIHINTPAUSE,
+       RISCV_ISA_EXT_SSTC,
        RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
 };
 
@@ -64,6 +68,7 @@ enum riscv_isa_ext_id {
  */
 enum riscv_isa_ext_key {
        RISCV_ISA_EXT_KEY_FPU,          /* For 'F' and 'D' */
+       RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
        RISCV_ISA_EXT_KEY_MAX,
 };
 
@@ -83,6 +88,8 @@ static __always_inline int riscv_isa_ext2key(int num)
                return RISCV_ISA_EXT_KEY_FPU;
        case RISCV_ISA_EXT_d:
                return RISCV_ISA_EXT_KEY_FPU;
+       case RISCV_ISA_EXT_ZIHINTPAUSE:
+               return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
        default:
                return -EINVAL;
        }
index 50138e2eb91b90da96ff0ce12261954ccfc77ca2..0d8fdb8ec63aa2cb1b2f2ec4e00d54100bcaa434 100644 (file)
@@ -28,6 +28,11 @@ struct kvm_vcpu_timer {
        u64 next_cycles;
        /* Underlying hrtimer instance */
        struct hrtimer hrt;
+
+       /* Flag to check if sstc is enabled or not */
+       bool sstc_enabled;
+       /* A function pointer to switch between stimecmp or hrtimer at runtime */
+       int (*timer_next_event)(struct kvm_vcpu *vcpu, u64 ncycles);
 };
 
 int kvm_riscv_vcpu_timer_next_event(struct kvm_vcpu *vcpu, u64 ncycles);
@@ -40,5 +45,7 @@ int kvm_riscv_vcpu_timer_deinit(struct kvm_vcpu *vcpu);
 int kvm_riscv_vcpu_timer_reset(struct kvm_vcpu *vcpu);
 void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu);
 void kvm_riscv_guest_timer_init(struct kvm *kvm);
+void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu);
+bool kvm_riscv_vcpu_timer_pending(struct kvm_vcpu *vcpu);
 
 #endif
index 9e3c2cf1edafe4b74b97348b9c5f77685dcd7934..2a0ef738695ed0847aa02c080489aa2f8f8981a6 100644 (file)
@@ -122,7 +122,21 @@ enum sbi_ext_pmu_fid {
        SBI_EXT_PMU_COUNTER_FW_READ,
 };
 
-#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(55, 0)
+union sbi_pmu_ctr_info {
+       unsigned long value;
+       struct {
+               unsigned long csr:12;
+               unsigned long width:6;
+#if __riscv_xlen == 32
+               unsigned long reserved:13;
+#else
+               unsigned long reserved:45;
+#endif
+               unsigned long type:1;
+       };
+};
+
+#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)
 #define RISCV_PMU_RAW_EVENT_IDX 0x20000
 
 /** General pmu event codes specified in SBI PMU extension */
@@ -189,12 +203,26 @@ enum sbi_pmu_ctr_type {
        SBI_PMU_CTR_TYPE_FW,
 };
 
+/* Helper macros to decode event idx */
+#define SBI_PMU_EVENT_IDX_OFFSET 20
+#define SBI_PMU_EVENT_IDX_MASK 0xFFFFF
+#define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF
+#define SBI_PMU_EVENT_IDX_TYPE_MASK 0xF0000
+#define SBI_PMU_EVENT_RAW_IDX 0x20000
+#define SBI_PMU_FIXED_CTR_MASK 0x07
+
+#define SBI_PMU_EVENT_CACHE_ID_CODE_MASK 0xFFF8
+#define SBI_PMU_EVENT_CACHE_OP_ID_CODE_MASK 0x06
+#define SBI_PMU_EVENT_CACHE_RESULT_ID_CODE_MASK 0x01
+
+#define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF
+
 /* Flags defined for config matching function */
 #define SBI_PMU_CFG_FLAG_SKIP_MATCH    (1 << 0)
 #define SBI_PMU_CFG_FLAG_CLEAR_VALUE   (1 << 1)
 #define SBI_PMU_CFG_FLAG_AUTO_START    (1 << 2)
 #define SBI_PMU_CFG_FLAG_SET_VUINH     (1 << 3)
-#define SBI_PMU_CFG_FLAG_SET_VSNH      (1 << 4)
+#define SBI_PMU_CFG_FLAG_SET_VSINH     (1 << 4)
 #define SBI_PMU_CFG_FLAG_SET_UINH      (1 << 5)
 #define SBI_PMU_CFG_FLAG_SET_SINH      (1 << 6)
 #define SBI_PMU_CFG_FLAG_SET_MINH      (1 << 7)
index 134388cbaaa1d3ba1bdc5c5b7a765327006c1732..1e4f8b4aef79d8eaf7fc29e192d9ee3c87e9e8d3 100644 (file)
@@ -4,15 +4,30 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/jump_label.h>
 #include <asm/barrier.h>
+#include <asm/hwcap.h>
 
 static inline void cpu_relax(void)
 {
+       if (!static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_ZIHINTPAUSE])) {
 #ifdef __riscv_muldiv
-       int dummy;
-       /* In lieu of a halt instruction, induce a long-latency stall. */
-       __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
+               int dummy;
+               /* In lieu of a halt instruction, induce a long-latency stall. */
+               __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
 #endif
+       } else {
+               /*
+                * Reduce instruction retirement.
+                * This assumes the PC changes.
+                */
+#ifdef __riscv_zihintpause
+               __asm__ __volatile__ ("pause");
+#else
+               /* Encoding of the pause instruction */
+               __asm__ __volatile__ (".4byte 0x100000F");
+#endif
+       }
        barrier();
 }
 
index 24b2a6e27698743196eb36fec697e6aad54a30af..7351417afd62e32c69eaa6ec9bc57675815ad322 100644 (file)
@@ -97,6 +97,7 @@ enum KVM_RISCV_ISA_EXT_ID {
        KVM_RISCV_ISA_EXT_I,
        KVM_RISCV_ISA_EXT_M,
        KVM_RISCV_ISA_EXT_SVPBMT,
+       KVM_RISCV_ISA_EXT_SSTC,
        KVM_RISCV_ISA_EXT_MAX,
 };
 
index 022fd18619929764d4c30ab237da9bc332c06092..0be8a2403212d4a2b9a8a30af78437bc5b597b5f 100644 (file)
@@ -93,6 +93,9 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
 static struct riscv_isa_ext_data isa_ext_arr[] = {
        __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
        __RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
+       __RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
+       __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
+       __RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
        __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
 };
 
index 170d07e577215b2c40c23da0332b2a2c28a322a0..8275f237a59df7d16cf12a8ba11630fe718c617d 100644 (file)
@@ -9,15 +9,14 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <asm/cpu_ops.h>
+#include <asm/cpu_ops_sbi.h>
 #include <asm/sbi.h>
 #include <asm/smp.h>
 
 const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
 
 extern const struct cpu_operations cpu_ops_sbi;
-#ifdef CONFIG_RISCV_BOOT_SPINWAIT
-extern const struct cpu_operations cpu_ops_spinwait;
-#else
+#ifndef CONFIG_RISCV_BOOT_SPINWAIT
 const struct cpu_operations cpu_ops_spinwait = {
        .name           = "",
        .cpu_prepare    = NULL,
index 3ade9152a3c7a02f3776ebcbcb71b2d9b64c8579..d98d19226b5f5175aca387cf22558bad9df1f2c5 100644 (file)
@@ -11,6 +11,8 @@
 #include <asm/sbi.h>
 #include <asm/smp.h>
 
+#include "head.h"
+
 const struct cpu_operations cpu_ops_spinwait;
 void *__cpu_spinwait_stack_pointer[NR_CPUS] __section(".data");
 void *__cpu_spinwait_task_pointer[NR_CPUS] __section(".data");
index e233fe154c96c809fca4031fea6afef4b10fcb5c..553d755483ed6d2c86051e5e4decb4a21d030874 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <asm/alternative.h>
+#include <asm/cacheflush.h>
 #include <asm/errata_list.h>
 #include <asm/hwcap.h>
 #include <asm/patch.h>
@@ -200,6 +201,9 @@ void __init riscv_fill_hwcap(void)
                        } else {
                                SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
                                SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
+                               SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
+                               SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
+                               SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC);
                        }
 #undef SET_ISA_EXT_MAP
                }
@@ -261,6 +265,25 @@ static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
        return false;
 }
 
+static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage)
+{
+#ifdef CONFIG_RISCV_ISA_ZICBOM
+       switch (stage) {
+       case RISCV_ALTERNATIVES_EARLY_BOOT:
+               return false;
+       default:
+               if (riscv_isa_extension_available(NULL, ZICBOM)) {
+                       riscv_noncoherent_supported();
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+#endif
+
+       return false;
+}
+
 /*
  * Probe presence of individual extensions.
  *
@@ -275,6 +298,9 @@ static u32 __init_or_module cpufeature_probe(unsigned int stage)
        if (cpufeature_probe_svpbmt(stage))
                cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
 
+       if (cpufeature_probe_zicbom(stage))
+               cpu_req_feature |= (1U << CPUFEATURE_ZICBOM);
+
        return cpu_req_feature;
 }
 
index 7832fb763abacf60e368fd5a6591e65df665793b..b2a1908c0463e411308d946955c3d1cd329039bf 100644 (file)
@@ -44,7 +44,7 @@ SYM_CODE_START(riscv_crash_save_regs)
        REG_S t6,  PT_T6(a0)    /* x31 */
 
        csrr t1, CSR_STATUS
-       csrr t2, CSR_EPC
+       auipc t2, 0x0
        csrr t3, CSR_TVAL
        csrr t4, CSR_CAUSE
 
index df8e24559035c455d0aa49e615c42b9dfdd109c1..ee79e6839b8639128e3adc1ee44bd71059a151f6 100644 (file)
@@ -138,19 +138,37 @@ void machine_shutdown(void)
 #endif
 }
 
+/* Override the weak function in kernel/panic.c */
+void crash_smp_send_stop(void)
+{
+       static int cpus_stopped;
+
+       /*
+        * This function can be called twice in panic path, but obviously
+        * we execute this only once.
+        */
+       if (cpus_stopped)
+               return;
+
+       smp_send_stop();
+       cpus_stopped = 1;
+}
+
 /*
  * machine_crash_shutdown - Prepare to kexec after a kernel crash
  *
  * This function is called by crash_kexec just before machine_kexec
- * below and its goal is similar to machine_shutdown, but in case of
- * a kernel crash. Since we don't handle such cases yet, this function
- * is empty.
+ * and its goal is to shutdown non-crashing cpus and save registers.
  */
 void
 machine_crash_shutdown(struct pt_regs *regs)
 {
+       local_irq_disable();
+
+       /* shutdown non-crashing cpus */
+       crash_smp_send_stop();
+
        crash_save_cpu(regs, smp_processor_id());
-       machine_shutdown();
        pr_info("Starting crashdump kernel...\n");
 }
 
@@ -171,7 +189,7 @@ machine_kexec(struct kimage *image)
        struct kimage_arch *internal = &image->arch;
        unsigned long jump_addr = (unsigned long) image->start;
        unsigned long first_ind_entry = (unsigned long) &image->head;
-       unsigned long this_cpu_id = smp_processor_id();
+       unsigned long this_cpu_id = __smp_processor_id();
        unsigned long this_hart_id = cpuid_to_hartid_map(this_cpu_id);
        unsigned long fdt_addr = internal->fdt_addr;
        void *control_code_buffer = page_address(image->control_code_page);
index 7a057b5f0adc73f1306e7ccc61f9cec28c50b66a..c976a21cd4bd5b20cd5030995335c601202dad01 100644 (file)
@@ -59,8 +59,6 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
        instruction_pointer_set(regs, utask->xol_vaddr);
 
-       regs->status &= ~SR_SPIE;
-
        return 0;
 }
 
@@ -72,8 +70,6 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
        instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size);
 
-       regs->status |= SR_SPIE;
-
        return 0;
 }
 
@@ -111,8 +107,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
         * address.
         */
        instruction_pointer_set(regs, utask->vaddr);
-
-       regs->status &= ~SR_SPIE;
 }
 
 bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
index f0f36a4a0e9b811a17922f32d62b306696419e8c..95ef6e2bf45c02faffaa4228ae50393d9146c6fd 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/crash_dump.h>
 
 #include <asm/alternative.h>
+#include <asm/cacheflush.h>
 #include <asm/cpu_ops.h>
 #include <asm/early_ioremap.h>
 #include <asm/pgtable.h>
@@ -296,6 +297,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        riscv_fill_hwcap();
+       riscv_init_cbom_blocksize();
        apply_boot_alternatives();
 }
 
index 46c4dafe3ba0e365d39f5f2a61850f5b1228b5f6..378f5b151443564020e775edfc13e6e90e557152 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/stringify.h>
 
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #define PRECISION_S 0
 #define PRECISION_D 1
 
-#define STR(x) XSTR(x)
-#define XSTR(x) #x
-
 #define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn)                 \
 static inline type load_##type(const type *addr)                       \
 {                                                                      \
@@ -207,9 +205,9 @@ static inline ulong get_insn(ulong mepc)
        asm ("and %[tmp], %[addr], 2\n"
                "bnez %[tmp], 1f\n"
 #if defined(CONFIG_64BIT)
-               STR(LWU) " %[insn], (%[addr])\n"
+               __stringify(LWU) " %[insn], (%[addr])\n"
 #else
-               STR(LW) " %[insn], (%[addr])\n"
+               __stringify(LW) " %[insn], (%[addr])\n"
 #endif
                "and %[tmp], %[insn], %[rvc_mask]\n"
                "beq %[tmp], %[rvc_mask], 2f\n"
index 5d271b5976139f92ea38131d4196144625baa1a0..d0f08d5b4282952c82a462cb8f4ba9bc27a5f9eb 100644 (file)
@@ -52,6 +52,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
        RISCV_ISA_EXT_i,
        RISCV_ISA_EXT_m,
        RISCV_ISA_EXT_SVPBMT,
+       RISCV_ISA_EXT_SSTC,
 };
 
 static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext)
@@ -85,6 +86,7 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
        case KVM_RISCV_ISA_EXT_C:
        case KVM_RISCV_ISA_EXT_I:
        case KVM_RISCV_ISA_EXT_M:
+       case KVM_RISCV_ISA_EXT_SSTC:
                return false;
        default:
                break;
@@ -203,7 +205,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-       return kvm_riscv_vcpu_has_interrupts(vcpu, 1UL << IRQ_VS_TIMER);
+       return kvm_riscv_vcpu_timer_pending(vcpu);
 }
 
 void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
@@ -785,6 +787,8 @@ static void kvm_riscv_vcpu_update_config(const unsigned long *isa)
        if (__riscv_isa_extension_available(isa, RISCV_ISA_EXT_SVPBMT))
                henvcfg |= ENVCFG_PBMTE;
 
+       if (__riscv_isa_extension_available(isa, RISCV_ISA_EXT_SSTC))
+               henvcfg |= ENVCFG_STCE;
        csr_write(CSR_HENVCFG, henvcfg);
 #ifdef CONFIG_32BIT
        csr_write(CSR_HENVCFGH, henvcfg >> 32);
@@ -828,6 +832,8 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
                                     vcpu->arch.isa);
        kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context);
 
+       kvm_riscv_vcpu_timer_save(vcpu);
+
        csr->vsstatus = csr_read(CSR_VSSTATUS);
        csr->vsie = csr_read(CSR_VSIE);
        csr->vstvec = csr_read(CSR_VSTVEC);
index 595043857049d082aad53d196ca47685b733a8d1..16f50c46ba39430ee95e0a2a0434ea599671765d 100644 (file)
@@ -69,7 +69,18 @@ static int kvm_riscv_vcpu_timer_cancel(struct kvm_vcpu_timer *t)
        return 0;
 }
 
-int kvm_riscv_vcpu_timer_next_event(struct kvm_vcpu *vcpu, u64 ncycles)
+static int kvm_riscv_vcpu_update_vstimecmp(struct kvm_vcpu *vcpu, u64 ncycles)
+{
+#if defined(CONFIG_32BIT)
+               csr_write(CSR_VSTIMECMP, ncycles & 0xFFFFFFFF);
+               csr_write(CSR_VSTIMECMPH, ncycles >> 32);
+#else
+               csr_write(CSR_VSTIMECMP, ncycles);
+#endif
+               return 0;
+}
+
+static int kvm_riscv_vcpu_update_hrtimer(struct kvm_vcpu *vcpu, u64 ncycles)
 {
        struct kvm_vcpu_timer *t = &vcpu->arch.timer;
        struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
@@ -88,6 +99,65 @@ int kvm_riscv_vcpu_timer_next_event(struct kvm_vcpu *vcpu, u64 ncycles)
        return 0;
 }
 
+int kvm_riscv_vcpu_timer_next_event(struct kvm_vcpu *vcpu, u64 ncycles)
+{
+       struct kvm_vcpu_timer *t = &vcpu->arch.timer;
+
+       return t->timer_next_event(vcpu, ncycles);
+}
+
+static enum hrtimer_restart kvm_riscv_vcpu_vstimer_expired(struct hrtimer *h)
+{
+       u64 delta_ns;
+       struct kvm_vcpu_timer *t = container_of(h, struct kvm_vcpu_timer, hrt);
+       struct kvm_vcpu *vcpu = container_of(t, struct kvm_vcpu, arch.timer);
+       struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
+
+       if (kvm_riscv_current_cycles(gt) < t->next_cycles) {
+               delta_ns = kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t);
+               hrtimer_forward_now(&t->hrt, ktime_set(0, delta_ns));
+               return HRTIMER_RESTART;
+       }
+
+       t->next_set = false;
+       kvm_vcpu_kick(vcpu);
+
+       return HRTIMER_NORESTART;
+}
+
+bool kvm_riscv_vcpu_timer_pending(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_timer *t = &vcpu->arch.timer;
+       struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
+
+       if (!kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t) ||
+           kvm_riscv_vcpu_has_interrupts(vcpu, 1UL << IRQ_VS_TIMER))
+               return true;
+       else
+               return false;
+}
+
+static void kvm_riscv_vcpu_timer_blocking(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_timer *t = &vcpu->arch.timer;
+       struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
+       u64 delta_ns;
+
+       if (!t->init_done)
+               return;
+
+       delta_ns = kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t);
+       if (delta_ns) {
+               hrtimer_start(&t->hrt, ktime_set(0, delta_ns), HRTIMER_MODE_REL);
+               t->next_set = true;
+       }
+}
+
+static void kvm_riscv_vcpu_timer_unblocking(struct kvm_vcpu *vcpu)
+{
+       kvm_riscv_vcpu_timer_cancel(&vcpu->arch.timer);
+}
+
 int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
                                 const struct kvm_one_reg *reg)
 {
@@ -180,10 +250,20 @@ int kvm_riscv_vcpu_timer_init(struct kvm_vcpu *vcpu)
                return -EINVAL;
 
        hrtimer_init(&t->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       t->hrt.function = kvm_riscv_vcpu_hrtimer_expired;
        t->init_done = true;
        t->next_set = false;
 
+       /* Enable sstc for every vcpu if available in hardware */
+       if (riscv_isa_extension_available(NULL, SSTC)) {
+               t->sstc_enabled = true;
+               t->hrt.function = kvm_riscv_vcpu_vstimer_expired;
+               t->timer_next_event = kvm_riscv_vcpu_update_vstimecmp;
+       } else {
+               t->sstc_enabled = false;
+               t->hrt.function = kvm_riscv_vcpu_hrtimer_expired;
+               t->timer_next_event = kvm_riscv_vcpu_update_hrtimer;
+       }
+
        return 0;
 }
 
@@ -199,21 +279,73 @@ int kvm_riscv_vcpu_timer_deinit(struct kvm_vcpu *vcpu)
 
 int kvm_riscv_vcpu_timer_reset(struct kvm_vcpu *vcpu)
 {
+       struct kvm_vcpu_timer *t = &vcpu->arch.timer;
+
+       t->next_cycles = -1ULL;
        return kvm_riscv_vcpu_timer_cancel(&vcpu->arch.timer);
 }
 
-void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
+static void kvm_riscv_vcpu_update_timedelta(struct kvm_vcpu *vcpu)
 {
        struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
 
-#ifdef CONFIG_64BIT
-       csr_write(CSR_HTIMEDELTA, gt->time_delta);
-#else
+#if defined(CONFIG_32BIT)
        csr_write(CSR_HTIMEDELTA, (u32)(gt->time_delta));
        csr_write(CSR_HTIMEDELTAH, (u32)(gt->time_delta >> 32));
+#else
+       csr_write(CSR_HTIMEDELTA, gt->time_delta);
 #endif
 }
 
+void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_csr *csr;
+       struct kvm_vcpu_timer *t = &vcpu->arch.timer;
+
+       kvm_riscv_vcpu_update_timedelta(vcpu);
+
+       if (!t->sstc_enabled)
+               return;
+
+       csr = &vcpu->arch.guest_csr;
+#if defined(CONFIG_32BIT)
+       csr_write(CSR_VSTIMECMP, (u32)t->next_cycles);
+       csr_write(CSR_VSTIMECMPH, (u32)(t->next_cycles >> 32));
+#else
+       csr_write(CSR_VSTIMECMP, t->next_cycles);
+#endif
+
+       /* timer should be enabled for the remaining operations */
+       if (unlikely(!t->init_done))
+               return;
+
+       kvm_riscv_vcpu_timer_unblocking(vcpu);
+}
+
+void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_csr *csr;
+       struct kvm_vcpu_timer *t = &vcpu->arch.timer;
+
+       if (!t->sstc_enabled)
+               return;
+
+       csr = &vcpu->arch.guest_csr;
+       t = &vcpu->arch.timer;
+#if defined(CONFIG_32BIT)
+       t->next_cycles = csr_read(CSR_VSTIMECMP);
+       t->next_cycles |= (u64)csr_read(CSR_VSTIMECMPH) << 32;
+#else
+       t->next_cycles = csr_read(CSR_VSTIMECMP);
+#endif
+       /* timer should be enabled for the remaining operations */
+       if (unlikely(!t->init_done))
+               return;
+
+       if (kvm_vcpu_is_blocking(vcpu))
+               kvm_riscv_vcpu_timer_blocking(vcpu);
+}
+
 void kvm_riscv_guest_timer_init(struct kvm *kvm)
 {
        struct kvm_guest_timer *gt = &kvm->arch.timer;
index 8c475f4da3084f2457f372b52ee0094bd3597003..ec486e5369d9bf5b274bcd73b242666d2b216322 100644 (file)
@@ -175,7 +175,7 @@ ENTRY(__asm_copy_from_user)
        /* Exception fixup code */
 10:
        /* Disable access to user memory */
-       csrs CSR_STATUS, t6
+       csrc CSR_STATUS, t6
        mv a0, t5
        ret
 ENDPROC(__asm_copy_to_user)
@@ -227,7 +227,7 @@ ENTRY(__clear_user)
        /* Exception fixup code */
 11:
        /* Disable access to user memory */
-       csrs CSR_STATUS, t6
+       csrc CSR_STATUS, t6
        mv a0, a1
        ret
 ENDPROC(__clear_user)
index ac7a25298a04af665ff0552d99a95e1671013ddd..d76aabf4b94d6a8bf4ef20eab680de4d4be16ff9 100644 (file)
@@ -30,3 +30,4 @@ endif
 endif
 
 obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
+obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
new file mode 100644 (file)
index 0000000..cd22253
--- /dev/null
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RISC-V specific functions to support DMA for non-coherent devices
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ */
+
+#include <linux/dma-direct.h>
+#include <linux/dma-map-ops.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <asm/cacheflush.h>
+
+static unsigned int riscv_cbom_block_size = L1_CACHE_BYTES;
+static bool noncoherent_supported;
+
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+                             enum dma_data_direction dir)
+{
+       void *vaddr = phys_to_virt(paddr);
+
+       switch (dir) {
+       case DMA_TO_DEVICE:
+               ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
+               break;
+       case DMA_FROM_DEVICE:
+               ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
+               break;
+       case DMA_BIDIRECTIONAL:
+               ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
+               break;
+       default:
+               break;
+       }
+}
+
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+                          enum dma_data_direction dir)
+{
+       void *vaddr = phys_to_virt(paddr);
+
+       switch (dir) {
+       case DMA_TO_DEVICE:
+               break;
+       case DMA_FROM_DEVICE:
+       case DMA_BIDIRECTIONAL:
+               ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
+               break;
+       default:
+               break;
+       }
+}
+
+void arch_dma_prep_coherent(struct page *page, size_t size)
+{
+       void *flush_addr = page_address(page);
+
+       ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
+}
+
+void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+               const struct iommu_ops *iommu, bool coherent)
+{
+       WARN_TAINT(!coherent && riscv_cbom_block_size > ARCH_DMA_MINALIGN,
+                  TAINT_CPU_OUT_OF_SPEC,
+                  "%s %s: ARCH_DMA_MINALIGN smaller than riscv,cbom-block-size (%d < %d)",
+                  dev_driver_string(dev), dev_name(dev),
+                  ARCH_DMA_MINALIGN, riscv_cbom_block_size);
+
+       WARN_TAINT(!coherent && !noncoherent_supported, TAINT_CPU_OUT_OF_SPEC,
+                  "%s %s: device non-coherent but no non-coherent operations supported",
+                  dev_driver_string(dev), dev_name(dev));
+
+       dev->dma_coherent = coherent;
+}
+
+#ifdef CONFIG_RISCV_ISA_ZICBOM
+void riscv_init_cbom_blocksize(void)
+{
+       struct device_node *node;
+       int ret;
+       u32 val;
+
+       for_each_of_cpu_node(node) {
+               unsigned long hartid;
+               int cbom_hartid;
+
+               ret = riscv_of_processor_hartid(node, &hartid);
+               if (ret)
+                       continue;
+
+               if (hartid < 0)
+                       continue;
+
+               /* set block-size for cbom extension if available */
+               ret = of_property_read_u32(node, "riscv,cbom-block-size", &val);
+               if (ret)
+                       continue;
+
+               if (!riscv_cbom_block_size) {
+                       riscv_cbom_block_size = val;
+                       cbom_hartid = hartid;
+               } else {
+                       if (riscv_cbom_block_size != val)
+                               pr_warn("cbom-block-size mismatched between harts %d and %lu\n",
+                                       cbom_hartid, hartid);
+               }
+       }
+}
+#endif
+
+void riscv_noncoherent_supported(void)
+{
+       noncoherent_supported = true;
+}
index a88b7dc31a68c007921905f332b36e0ef89fc63e..b56a0a75533fe3993a25fc10b833b2c1b7df523a 100644 (file)
@@ -135,6 +135,10 @@ static void __init print_vm_layout(void)
                (unsigned long)VMEMMAP_END);
        print_ml("vmalloc", (unsigned long)VMALLOC_START,
                (unsigned long)VMALLOC_END);
+#ifdef CONFIG_64BIT
+       print_ml("modules", (unsigned long)MODULES_VADDR,
+               (unsigned long)MODULES_END);
+#endif
        print_ml("lowmem", (unsigned long)PAGE_OFFSET,
                (unsigned long)high_memory);
        if (IS_ENABLED(CONFIG_64BIT)) {
index 38d7d1bda4d7c2671d99087b8b9345d8d647543c..6e4dfb024ad2bf3c7731e9ee1335c04e2d919f15 100644 (file)
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 purgatory.chk
 purgatory.ro
-kexec-purgatory.c
index d4df200f7edf9d97fc842d46246bc974947ec8ef..dd58e1d99397291a21a0f7ebbbca9799e37f0415 100644 (file)
@@ -84,12 +84,6 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
 $(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE
                $(call if_changed,ld)
 
-targets += kexec-purgatory.c
+$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro $(obj)/purgatory.chk
 
-quiet_cmd_bin2c = BIN2C   $@
-      cmd_bin2c = $(objtree)/scripts/bin2c kexec_purgatory < $< > $@
-
-$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro $(obj)/purgatory.chk FORCE
-       $(call if_changed,bin2c)
-
-obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += kexec-purgatory.o
+obj-y += kexec-purgatory.o
diff --git a/arch/riscv/purgatory/kexec-purgatory.S b/arch/riscv/purgatory/kexec-purgatory.S
new file mode 100644 (file)
index 0000000..0e91888
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+       .section .rodata, "a"
+
+       .align  8
+kexec_purgatory:
+       .globl  kexec_purgatory
+       .incbin "arch/riscv/purgatory/purgatory.ro"
+.Lkexec_purgatroy_end:
+
+       .align  8
+kexec_purgatory_size:
+       .globl  kexec_purgatory_size
+       .quad   .Lkexec_purgatroy_end - kexec_purgatory
index e460df7ed799de6b00f3d86e2d0557b8f836e317..969a552da8d2971c7df54cfd6af29871a443aff7 100644 (file)
@@ -7,6 +7,9 @@
  * either be read from the "time" and "timeh" CSRs, and can use the SBI to
  * setup events, or directly accessed using MMIO registers.
  */
+
+#define pr_fmt(fmt) "riscv-timer: " fmt
+
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/cpu.h>
 #include <linux/of_irq.h>
 #include <clocksource/timer-riscv.h>
 #include <asm/smp.h>
+#include <asm/hwcap.h>
 #include <asm/sbi.h>
 #include <asm/timex.h>
 
+static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
+
 static int riscv_clock_next_event(unsigned long delta,
                struct clock_event_device *ce)
 {
+       u64 next_tval = get_cycles64() + delta;
+
        csr_set(CSR_IE, IE_TIE);
-       sbi_set_timer(get_cycles64() + delta);
+       if (static_branch_likely(&riscv_sstc_available)) {
+#if defined(CONFIG_32BIT)
+               csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
+               csr_write(CSR_STIMECMPH, next_tval >> 32);
+#else
+               csr_write(CSR_STIMECMP, next_tval);
+#endif
+       } else
+               sbi_set_timer(next_tval);
+
        return 0;
 }
 
@@ -166,6 +183,12 @@ static int __init riscv_timer_init_dt(struct device_node *n)
        if (error)
                pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
                       error);
+
+       if (riscv_isa_extension_available(NULL, SSTC)) {
+               pr_info("Timer interrupt in S-mode is available via sstc extension\n");
+               static_branch_enable(&riscv_sstc_available);
+       }
+
        return error;
 }
 
index 94f017d808c44c53d014b7cde8f4445aad37bd63..96f0a12e507cd12e8dad8f7703f3e094f7ddb00e 100644 (file)
@@ -1045,26 +1045,29 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
  *
  * It returns true if "dma-coherent" property was found
  * for this device in the DT, or if DMA is coherent by
- * default for OF devices on the current platform.
+ * default for OF devices on the current platform and no
+ * "dma-noncoherent" property was found for this device.
  */
 bool of_dma_is_coherent(struct device_node *np)
 {
        struct device_node *node;
-
-       if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
-               return true;
+       bool is_coherent = IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT);
 
        node = of_node_get(np);
 
        while (node) {
                if (of_property_read_bool(node, "dma-coherent")) {
-                       of_node_put(node);
-                       return true;
+                       is_coherent = true;
+                       break;
+               }
+               if (of_property_read_bool(node, "dma-noncoherent")) {
+                       is_coherent = false;
+                       break;
                }
                node = of_get_next_dma_parent(node);
        }
        of_node_put(node);
-       return false;
+       return is_coherent;
 }
 EXPORT_SYMBOL_GPL(of_dma_is_coherent);
 
index 2c961839903d68c79091b25fb73c7f4281d6ed88..ebca5eab9c9beeac4393c898bb3dbf272bfacd64 100644 (file)
@@ -170,7 +170,6 @@ int riscv_pmu_event_set_period(struct perf_event *event)
                left = (max_period >> 1);
 
        local64_set(&hwc->prev_count, (u64)-left);
-       perf_event_update_userpage(event);
 
        return overflow;
 }
index 79a3de515ece6ba2f3c6218906d5c31f44e9ea82..6f6681bbfd36de515b52bfc58ed6e04a1d34518f 100644 (file)
@@ -41,20 +41,6 @@ static const struct attribute_group *riscv_pmu_attr_groups[] = {
        NULL,
 };
 
-union sbi_pmu_ctr_info {
-       unsigned long value;
-       struct {
-               unsigned long csr:12;
-               unsigned long width:6;
-#if __riscv_xlen == 32
-               unsigned long reserved:13;
-#else
-               unsigned long reserved:45;
-#endif
-               unsigned long type:1;
-       };
-};
-
 /*
  * RISC-V doesn't have hetergenous harts yet. This need to be part of
  * per_cpu in case of harts with different pmu counters
@@ -294,8 +280,13 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event)
                cflags |= SBI_PMU_CFG_FLAG_SET_UINH;
 
        /* retrieve the available counter index */
+#if defined(CONFIG_32BIT)
+       ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask,
+                       cflags, hwc->event_base, hwc->config, hwc->config >> 32);
+#else
        ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask,
                        cflags, hwc->event_base, hwc->config, 0);
+#endif
        if (ret.error) {
                pr_debug("Not able to find a counter for event %lx config %llx\n",
                        hwc->event_base, hwc->config);
@@ -437,8 +428,13 @@ static void pmu_sbi_ctr_start(struct perf_event *event, u64 ival)
        struct hw_perf_event *hwc = &event->hw;
        unsigned long flag = SBI_PMU_START_FLAG_SET_INIT_VALUE;
 
+#if defined(CONFIG_32BIT)
        ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, hwc->idx,
                        1, flag, ival, ival >> 32, 0);
+#else
+       ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, hwc->idx,
+                       1, flag, ival, 0, 0);
+#endif
        if (ret.error && (ret.error != SBI_ERR_ALREADY_STARTED))
                pr_err("Starting counter idx %d failed with error %d\n",
                        hwc->idx, sbi_err_map_linux_errno(ret.error));
@@ -545,8 +541,14 @@ static inline void pmu_sbi_start_overflow_mask(struct riscv_pmu *pmu,
                        hwc = &event->hw;
                        max_period = riscv_pmu_ctr_get_width_mask(event);
                        init_val = local64_read(&hwc->prev_count) & max_period;
+#if defined(CONFIG_32BIT)
+                       sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx, 1,
+                                 flag, init_val, init_val >> 32, 0);
+#else
                        sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx, 1,
                                  flag, init_val, 0, 0);
+#endif
+                       perf_event_update_userpage(event);
                }
                ctr_ovf_mask = ctr_ovf_mask >> 1;
                idx++;
index 51e5c76bcd076dad09c3aa9ac6c8f8daae5f0ad4..ccadfa3afb2b81d4c70c604098225138b36f85e6 100755 (executable)
@@ -42,6 +42,8 @@ if [ -n "${building_out_of_srctree}" ]; then
        done
 fi
 
+rm -f arch/riscv/purgatory/kexec-purgatory.c
+
 rm -f scripts/extract-cert
 
 rm -f arch/x86/purgatory/kexec-purgatory.c
index 0bd0e72d95d49f67eb53b5c8ab5ff649d39c11c7..2fc36efb166dc9a2f692f38aa7642588cd7b54c7 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_NONPORTABLE=y
 CONFIG_ARCH_RV32I=y
 CONFIG_MMU=y
 CONFIG_FPU=y