mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
RISC-V Patches for the 5.20 Merge Window, Part 2
There's still a handful of new features in here, but there are a lot of fixes/cleanups as well: * Support for the Zicbom 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. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAmL21egTHHBhbG1lckBk YWJiZWx0LmNvbQAKCRAuExnzX7sYiSsiD/9cCN/7ndt4v7N65PUya+mVYC9VPppB d/UC74M0mMUHQbtdtHzlCZVHW0pxc6Pc8oDTWLviKxNSHa6LQkLQJ/RZZz4YlH91 V/vh6DCZv9TRfHJS2E6jMUKEAVAiGg+723gE5EqLc5uapIBrvmiluQwBIQcu8dj1 egfdxJH3IVrEZWwROrYtffDgw4sipENuch5v4yhk4vH0bMlatcIM+hMpPZgOfbgX xip4K4B/HTAJRn5vunrlCQzYdg+g9l5iEy73A/A9HfzOFCMTMJFp1zHvIrzLUjKC 79MZza3GJLpwMG4C1j8u+qOL01wVrQcA5gNp+14UuUedl/jHaceZwBkCL4cmFyGP LE94Ed7+6cIJJH/NTcNfOOSD9byOePjfan+qJIlRBxZGbHKt+Ip6Lu2FGeftpXah MlhhN5S1nGTuFpn7XGRsYrB/VLBD/KWsLxvWBZZWsSYwHwnFA9ZTUbcuQfxTJ+Qq mH9wZIZ/z8MaEjKcdooIPHjKl+CFjDpVYWge83/t12LLYC9ryTM4vIlltZ84bs6i 2CMSNjBRSuPa7FQPHW+a6CWAjz2Lv1u9jCSH0iI62ytZR5/zinI39tv6LvwbypbY VfWBnrtLNLlZmNbk13ODV64ayhTpZoZXWGL2TvkJklBqEPqda+9/nopiqb8a8jFZ yEmKFdEqrb1LAg== =caji -----END PGP SIGNATURE----- Merge tag 'riscv-for-linus-5.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux 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 ...
This commit is contained in:
commit
69dac8e431
@ -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>;
|
|
||||||
};
|
|
@ -21,8 +21,10 @@ properties:
|
|||||||
compatible:
|
compatible:
|
||||||
items:
|
items:
|
||||||
- enum:
|
- enum:
|
||||||
|
- adafruit,yx240qv29
|
||||||
# ili9341 240*320 Color on stm32f429-disco board
|
# ili9341 240*320 Color on stm32f429-disco board
|
||||||
- st,sf-tc240t-9370-t
|
- st,sf-tc240t-9370-t
|
||||||
|
- canaan,kd233-tft
|
||||||
- const: ilitek,ili9341
|
- const: ilitek,ili9341
|
||||||
|
|
||||||
reg: true
|
reg: true
|
||||||
@ -47,31 +49,50 @@ properties:
|
|||||||
vddi-led-supply:
|
vddi-led-supply:
|
||||||
description: Voltage supply for the LED driver (1.65 .. 3.3 V)
|
description: Voltage supply for the LED driver (1.65 .. 3.3 V)
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
- dc-gpios
|
- dc-gpios
|
||||||
- port
|
|
||||||
|
if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- st,sf-tc240t-9370-t
|
||||||
|
then:
|
||||||
|
required:
|
||||||
|
- port
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |+
|
- |+
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
spi {
|
spi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
panel: display@0 {
|
panel: display@0 {
|
||||||
compatible = "st,sf-tc240t-9370-t",
|
compatible = "st,sf-tc240t-9370-t",
|
||||||
"ilitek,ili9341";
|
"ilitek,ili9341";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
spi-3wire;
|
spi-3wire;
|
||||||
spi-max-frequency = <10000000>;
|
spi-max-frequency = <10000000>;
|
||||||
dc-gpios = <&gpiod 13 0>;
|
dc-gpios = <&gpiod 13 0>;
|
||||||
port {
|
port {
|
||||||
panel_in: endpoint {
|
panel_in: endpoint {
|
||||||
remote-endpoint = <&display_out>;
|
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>;
|
||||||
|
};
|
||||||
|
};
|
||||||
...
|
...
|
||||||
|
@ -46,6 +46,10 @@ properties:
|
|||||||
maximum: 32
|
maximum: 32
|
||||||
default: 16
|
default: 16
|
||||||
|
|
||||||
|
gpio-line-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 32
|
||||||
|
|
||||||
gpio-controller: true
|
gpio-controller: true
|
||||||
|
|
||||||
required:
|
required:
|
||||||
|
@ -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";
|
||||||
|
};
|
@ -63,6 +63,11 @@ properties:
|
|||||||
- riscv,sv48
|
- riscv,sv48
|
||||||
- riscv,none
|
- riscv,none
|
||||||
|
|
||||||
|
riscv,cbom-block-size:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
description:
|
||||||
|
The blocksize in bytes for the Zicbom cache operations.
|
||||||
|
|
||||||
riscv,isa:
|
riscv,isa:
|
||||||
description:
|
description:
|
||||||
Identifies the specific RISC-V instruction set architecture
|
Identifies the specific RISC-V instruction set architecture
|
||||||
|
@ -46,7 +46,7 @@ properties:
|
|||||||
const: 2
|
const: 2
|
||||||
|
|
||||||
cache-sets:
|
cache-sets:
|
||||||
const: 1024
|
enum: [1024, 2048]
|
||||||
|
|
||||||
cache-size:
|
cache-size:
|
||||||
const: 2097152
|
const: 2097152
|
||||||
@ -84,6 +84,8 @@ then:
|
|||||||
description: |
|
description: |
|
||||||
Must contain entries for DirError, DataError and DataFail signals.
|
Must contain entries for DirError, DataError and DataFail signals.
|
||||||
maxItems: 3
|
maxItems: 3
|
||||||
|
cache-sets:
|
||||||
|
const: 1024
|
||||||
|
|
||||||
else:
|
else:
|
||||||
properties:
|
properties:
|
||||||
@ -91,6 +93,8 @@ else:
|
|||||||
description: |
|
description: |
|
||||||
Must contain entries for DirError, DataError, DataFail, DirFail signals.
|
Must contain entries for DirError, DataError, DataFail, DirFail signals.
|
||||||
minItems: 4
|
minItems: 4
|
||||||
|
cache-sets:
|
||||||
|
const: 2048
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
|
@ -113,6 +113,7 @@ config RISCV
|
|||||||
select MODULES_USE_ELF_RELA if MODULES
|
select MODULES_USE_ELF_RELA if MODULES
|
||||||
select MODULE_SECTIONS if MODULES
|
select MODULE_SECTIONS if MODULES
|
||||||
select OF
|
select OF
|
||||||
|
select OF_DMA_DEFAULT_COHERENT
|
||||||
select OF_EARLY_FLATTREE
|
select OF_EARLY_FLATTREE
|
||||||
select OF_IRQ
|
select OF_IRQ
|
||||||
select PCI_DOMAINS_GENERIC if PCI
|
select PCI_DOMAINS_GENERIC if PCI
|
||||||
@ -218,6 +219,14 @@ config PGTABLE_LEVELS
|
|||||||
config LOCKDEP_SUPPORT
|
config LOCKDEP_SUPPORT
|
||||||
def_bool y
|
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.socs"
|
||||||
source "arch/riscv/Kconfig.erratas"
|
source "arch/riscv/Kconfig.erratas"
|
||||||
|
|
||||||
@ -392,6 +401,28 @@ config RISCV_ISA_SVPBMT
|
|||||||
|
|
||||||
If you don't know what to do here, say Y.
|
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
|
config FPU
|
||||||
bool "FPU support"
|
bool "FPU support"
|
||||||
default y
|
default y
|
||||||
@ -463,7 +494,6 @@ config KEXEC_FILE
|
|||||||
|
|
||||||
config ARCH_HAS_KEXEC_PURGATORY
|
config ARCH_HAS_KEXEC_PURGATORY
|
||||||
def_bool KEXEC_FILE
|
def_bool KEXEC_FILE
|
||||||
select BUILD_BIN2C
|
|
||||||
depends on CRYPTO=y
|
depends on CRYPTO=y
|
||||||
depends on CRYPTO_SHA256=y
|
depends on CRYPTO_SHA256=y
|
||||||
|
|
||||||
|
@ -55,4 +55,15 @@ config ERRATA_THEAD_PBMT
|
|||||||
|
|
||||||
If you don't know what to do here, say "Y".
|
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"
|
endmenu # "CPU errata selection"
|
||||||
|
@ -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)
|
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
|
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_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
|
||||||
KBUILD_AFLAGS += -march=$(riscv-march-y)
|
KBUILD_AFLAGS += -march=$(riscv-march-y)
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
dtb-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += $(addsuffix .dtb, $(CONFIG_SOC_CANAAN_K210_DTB_SOURCE))
|
dtb-$(CONFIG_SOC_CANAAN) += canaan_kd233.dtb
|
||||||
obj-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += $(addsuffix .o, $(dtb-y))
|
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))
|
||||||
|
@ -127,10 +127,10 @@
|
|||||||
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
|
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
|
||||||
|
|
||||||
panel@0 {
|
panel@0 {
|
||||||
compatible = "ilitek,ili9341";
|
compatible = "canaan,kd233-tft", "ilitek,ili9341";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
dc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
|
dc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
|
||||||
spi-max-frequency = <15000000>;
|
spi-max-frequency = <10000000>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -142,7 +142,7 @@
|
|||||||
cs-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
|
cs-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
slot@0 {
|
mmc@0 {
|
||||||
compatible = "mmc-spi-slot";
|
compatible = "mmc-spi-slot";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
voltage-ranges = <3300 3300>;
|
voltage-ranges = <3300 3300>;
|
||||||
|
@ -81,11 +81,13 @@
|
|||||||
|
|
||||||
sram: memory@80000000 {
|
sram: memory@80000000 {
|
||||||
device_type = "memory";
|
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";
|
compatible = "canaan,k210-sram";
|
||||||
reg = <0x80000000 0x400000>,
|
|
||||||
<0x80400000 0x200000>,
|
|
||||||
<0x80600000 0x200000>;
|
|
||||||
reg-names = "sram0", "sram1", "aisram";
|
|
||||||
clocks = <&sysclk K210_CLK_SRAM0>,
|
clocks = <&sysclk K210_CLK_SRAM0>,
|
||||||
<&sysclk K210_CLK_SRAM1>,
|
<&sysclk K210_CLK_SRAM1>,
|
||||||
<&sysclk K210_CLK_AI>;
|
<&sysclk K210_CLK_AI>;
|
||||||
@ -173,7 +175,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
compatible = "simple-pm-bus";
|
compatible = "simple-pm-bus";
|
||||||
ranges;
|
ranges = <0x50200000 0x50200000 0x200000>;
|
||||||
clocks = <&sysclk K210_CLK_APB0>;
|
clocks = <&sysclk K210_CLK_APB0>;
|
||||||
|
|
||||||
gpio1: gpio@50200000 {
|
gpio1: gpio@50200000 {
|
||||||
@ -261,7 +263,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
i2s0: i2s@50250000 {
|
i2s0: i2s@50250000 {
|
||||||
compatible = "snps,designware-i2s";
|
compatible = "canaan,k210-i2s", "snps,designware-i2s";
|
||||||
reg = <0x50250000 0x200>;
|
reg = <0x50250000 0x200>;
|
||||||
interrupts = <5>;
|
interrupts = <5>;
|
||||||
clocks = <&sysclk K210_CLK_I2S0>;
|
clocks = <&sysclk K210_CLK_I2S0>;
|
||||||
@ -270,7 +272,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
i2s1: i2s@50260000 {
|
i2s1: i2s@50260000 {
|
||||||
compatible = "snps,designware-i2s";
|
compatible = "canaan,k210-i2s", "snps,designware-i2s";
|
||||||
reg = <0x50260000 0x200>;
|
reg = <0x50260000 0x200>;
|
||||||
interrupts = <6>;
|
interrupts = <6>;
|
||||||
clocks = <&sysclk K210_CLK_I2S1>;
|
clocks = <&sysclk K210_CLK_I2S1>;
|
||||||
@ -279,7 +281,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
i2s2: i2s@50270000 {
|
i2s2: i2s@50270000 {
|
||||||
compatible = "snps,designware-i2s";
|
compatible = "canaan,k210-i2s", "snps,designware-i2s";
|
||||||
reg = <0x50270000 0x200>;
|
reg = <0x50270000 0x200>;
|
||||||
interrupts = <7>;
|
interrupts = <7>;
|
||||||
clocks = <&sysclk K210_CLK_I2S2>;
|
clocks = <&sysclk K210_CLK_I2S2>;
|
||||||
@ -329,28 +331,58 @@
|
|||||||
|
|
||||||
timer0: timer@502d0000 {
|
timer0: timer@502d0000 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0x502D0000 0x100>;
|
reg = <0x502D0000 0x14>;
|
||||||
interrupts = <14>, <15>;
|
interrupts = <14>;
|
||||||
clocks = <&sysclk K210_CLK_TIMER0>,
|
clocks = <&sysclk K210_CLK_TIMER0>,
|
||||||
<&sysclk K210_CLK_APB0>;
|
<&sysclk K210_CLK_APB0>;
|
||||||
clock-names = "timer", "pclk";
|
clock-names = "timer", "pclk";
|
||||||
resets = <&sysrst K210_RST_TIMER0>;
|
resets = <&sysrst K210_RST_TIMER0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
timer1: timer@502e0000 {
|
timer1: timer@502d0014 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0x502E0000 0x100>;
|
reg = <0x502D0014 0x14>;
|
||||||
interrupts = <16>, <17>;
|
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>,
|
clocks = <&sysclk K210_CLK_TIMER1>,
|
||||||
<&sysclk K210_CLK_APB0>;
|
<&sysclk K210_CLK_APB0>;
|
||||||
clock-names = "timer", "pclk";
|
clock-names = "timer", "pclk";
|
||||||
resets = <&sysrst K210_RST_TIMER1>;
|
resets = <&sysrst K210_RST_TIMER1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
timer2: timer@502f0000 {
|
timer3: timer@502e0014 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0x502F0000 0x100>;
|
reg = <0x502E0014 0x114>;
|
||||||
interrupts = <18>, <19>;
|
interrupts = <17>;
|
||||||
|
clocks = <&sysclk K210_CLK_TIMER1>,
|
||||||
|
<&sysclk K210_CLK_APB0>;
|
||||||
|
clock-names = "timer", "pclk";
|
||||||
|
resets = <&sysrst K210_RST_TIMER1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
timer4: timer@502f0000 {
|
||||||
|
compatible = "snps,dw-apb-timer";
|
||||||
|
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>,
|
clocks = <&sysclk K210_CLK_TIMER2>,
|
||||||
<&sysclk K210_CLK_APB0>;
|
<&sysclk K210_CLK_APB0>;
|
||||||
clock-names = "timer", "pclk";
|
clock-names = "timer", "pclk";
|
||||||
@ -362,7 +394,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
compatible = "simple-pm-bus";
|
compatible = "simple-pm-bus";
|
||||||
ranges;
|
ranges = <0x50400000 0x50400000 0x40100>;
|
||||||
clocks = <&sysclk K210_CLK_APB1>;
|
clocks = <&sysclk K210_CLK_APB1>;
|
||||||
|
|
||||||
wdt0: watchdog@50400000 {
|
wdt0: watchdog@50400000 {
|
||||||
@ -417,7 +449,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
compatible = "simple-pm-bus";
|
compatible = "simple-pm-bus";
|
||||||
ranges;
|
ranges = <0x52000000 0x52000000 0x2000200>;
|
||||||
clocks = <&sysclk K210_CLK_APB2>;
|
clocks = <&sysclk K210_CLK_APB2>;
|
||||||
|
|
||||||
spi0: spi@52000000 {
|
spi0: spi@52000000 {
|
||||||
@ -431,7 +463,6 @@
|
|||||||
clock-names = "ssi_clk", "pclk";
|
clock-names = "ssi_clk", "pclk";
|
||||||
resets = <&sysrst K210_RST_SPI0>;
|
resets = <&sysrst K210_RST_SPI0>;
|
||||||
reset-names = "spi";
|
reset-names = "spi";
|
||||||
spi-max-frequency = <25000000>;
|
|
||||||
num-cs = <4>;
|
num-cs = <4>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
};
|
};
|
||||||
@ -447,7 +478,6 @@
|
|||||||
clock-names = "ssi_clk", "pclk";
|
clock-names = "ssi_clk", "pclk";
|
||||||
resets = <&sysrst K210_RST_SPI1>;
|
resets = <&sysrst K210_RST_SPI1>;
|
||||||
reset-names = "spi";
|
reset-names = "spi";
|
||||||
spi-max-frequency = <25000000>;
|
|
||||||
num-cs = <4>;
|
num-cs = <4>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
};
|
};
|
||||||
@ -463,8 +493,7 @@
|
|||||||
clock-names = "ssi_clk", "pclk";
|
clock-names = "ssi_clk", "pclk";
|
||||||
resets = <&sysrst K210_RST_SPI3>;
|
resets = <&sysrst K210_RST_SPI3>;
|
||||||
reset-names = "spi";
|
reset-names = "spi";
|
||||||
/* Could possibly go up to 200 MHz */
|
|
||||||
spi-max-frequency = <100000000>;
|
|
||||||
num-cs = <4>;
|
num-cs = <4>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
};
|
};
|
||||||
|
@ -189,7 +189,7 @@
|
|||||||
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
slot@0 {
|
mmc@0 {
|
||||||
compatible = "mmc-spi-slot";
|
compatible = "mmc-spi-slot";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
voltage-ranges = <3300 3300>;
|
voltage-ranges = <3300 3300>;
|
||||||
|
@ -191,7 +191,7 @@
|
|||||||
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
slot@0 {
|
mmc@0 {
|
||||||
compatible = "mmc-spi-slot";
|
compatible = "mmc-spi-slot";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
voltage-ranges = <3300 3300>;
|
voltage-ranges = <3300 3300>;
|
||||||
|
@ -199,7 +199,7 @@
|
|||||||
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
slot@0 {
|
mmc@0 {
|
||||||
compatible = "mmc-spi-slot";
|
compatible = "mmc-spi-slot";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
voltage-ranges = <3300 3300>;
|
voltage-ranges = <3300 3300>;
|
||||||
|
@ -164,7 +164,7 @@
|
|||||||
cs-gpios = <&gpio1_0 2 GPIO_ACTIVE_LOW>;
|
cs-gpios = <&gpio1_0 2 GPIO_ACTIVE_LOW>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
slot@0 {
|
mmc@0 {
|
||||||
compatible = "mmc-spi-slot";
|
compatible = "mmc-spi-slot";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
voltage-ranges = <3300 3300>;
|
voltage-ranges = <3300 3300>;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "fu740-c000.dtsi"
|
#include "fu740-c000.dtsi"
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
#include <dt-bindings/interrupt-controller/irq.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 */
|
/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
|
||||||
#define RTCCLK_FREQ 1000000
|
#define RTCCLK_FREQ 1000000
|
||||||
@ -44,6 +46,46 @@
|
|||||||
compatible = "gpio-poweroff";
|
compatible = "gpio-poweroff";
|
||||||
gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
|
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 {
|
&uart0 {
|
||||||
|
@ -130,7 +130,7 @@
|
|||||||
interrupt-controller;
|
interrupt-controller;
|
||||||
#address-cells = <0>;
|
#address-cells = <0>;
|
||||||
#interrupt-cells = <1>;
|
#interrupt-cells = <1>;
|
||||||
riscv,ndev = <127>;
|
riscv,ndev = <133>;
|
||||||
};
|
};
|
||||||
|
|
||||||
clkgen: clock-controller@11800000 {
|
clkgen: clock-controller@11800000 {
|
||||||
|
@ -27,6 +27,23 @@ static bool errata_probe_pbmt(unsigned int stage,
|
|||||||
return false;
|
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,
|
static u32 thead_errata_probe(unsigned int stage,
|
||||||
unsigned long archid, unsigned long impid)
|
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))
|
if (errata_probe_pbmt(stage, archid, impid))
|
||||||
cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
|
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;
|
return cpu_req_errata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
|
#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
|
* RISC-V requires the stack pointer to be 16-byte aligned, so ensure that
|
||||||
* the flat loader aligns it accordingly.
|
* the flat loader aligns it accordingly.
|
||||||
|
@ -42,6 +42,16 @@ void flush_icache_mm(struct mm_struct *mm, bool local);
|
|||||||
|
|
||||||
#endif /* CONFIG_SMP */
|
#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.
|
* Bits in sys_riscv_flush_icache()'s flags argument.
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +38,7 @@ struct cpu_operations {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const struct cpu_operations cpu_ops_spinwait;
|
||||||
extern const struct cpu_operations *cpu_ops[NR_CPUS];
|
extern const struct cpu_operations *cpu_ops[NR_CPUS];
|
||||||
void __init cpu_set_ops(int cpu);
|
void __init cpu_set_ops(int cpu);
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/threads.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
|
* struct sbi_hart_boot_data - Hart specific boot used during booting and
|
||||||
* cpu hotplug.
|
* cpu hotplug.
|
||||||
|
@ -247,6 +247,9 @@
|
|||||||
#define CSR_SIP 0x144
|
#define CSR_SIP 0x144
|
||||||
#define CSR_SATP 0x180
|
#define CSR_SATP 0x180
|
||||||
|
|
||||||
|
#define CSR_STIMECMP 0x14D
|
||||||
|
#define CSR_STIMECMPH 0x15D
|
||||||
|
|
||||||
#define CSR_VSSTATUS 0x200
|
#define CSR_VSSTATUS 0x200
|
||||||
#define CSR_VSIE 0x204
|
#define CSR_VSIE 0x204
|
||||||
#define CSR_VSTVEC 0x205
|
#define CSR_VSTVEC 0x205
|
||||||
@ -256,6 +259,8 @@
|
|||||||
#define CSR_VSTVAL 0x243
|
#define CSR_VSTVAL 0x243
|
||||||
#define CSR_VSIP 0x244
|
#define CSR_VSIP 0x244
|
||||||
#define CSR_VSATP 0x280
|
#define CSR_VSATP 0x280
|
||||||
|
#define CSR_VSTIMECMP 0x24D
|
||||||
|
#define CSR_VSTIMECMPH 0x25D
|
||||||
|
|
||||||
#define CSR_HSTATUS 0x600
|
#define CSR_HSTATUS 0x600
|
||||||
#define CSR_HEDELEG 0x602
|
#define CSR_HEDELEG 0x602
|
||||||
|
@ -16,11 +16,13 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_ERRATA_THEAD
|
#ifdef CONFIG_ERRATA_THEAD
|
||||||
#define ERRATA_THEAD_PBMT 0
|
#define ERRATA_THEAD_PBMT 0
|
||||||
#define ERRATA_THEAD_NUMBER 1
|
#define ERRATA_THEAD_CMO 1
|
||||||
|
#define ERRATA_THEAD_NUMBER 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CPUFEATURE_SVPBMT 0
|
#define CPUFEATURE_SVPBMT 0
|
||||||
#define CPUFEATURE_NUMBER 1
|
#define CPUFEATURE_ZICBOM 1
|
||||||
|
#define CPUFEATURE_NUMBER 2
|
||||||
|
|
||||||
#ifdef __ASSEMBLY__
|
#ifdef __ASSEMBLY__
|
||||||
|
|
||||||
@ -87,6 +89,59 @@ asm volatile(ALTERNATIVE( \
|
|||||||
#define ALT_THEAD_PMA(_val)
|
#define ALT_THEAD_PMA(_val)
|
||||||
#endif
|
#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 /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#ifndef _ASM_RISCV_HWCAP_H
|
#ifndef _ASM_RISCV_HWCAP_H
|
||||||
#define _ASM_RISCV_HWCAP_H
|
#define _ASM_RISCV_HWCAP_H
|
||||||
|
|
||||||
|
#include <asm/errno.h>
|
||||||
#include <linux/bits.h>
|
#include <linux/bits.h>
|
||||||
#include <uapi/asm/hwcap.h>
|
#include <uapi/asm/hwcap.h>
|
||||||
|
|
||||||
@ -54,6 +55,9 @@ extern unsigned long elf_hwcap;
|
|||||||
enum riscv_isa_ext_id {
|
enum riscv_isa_ext_id {
|
||||||
RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
|
RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
|
||||||
RISCV_ISA_EXT_SVPBMT,
|
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,
|
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,6 +68,7 @@ enum riscv_isa_ext_id {
|
|||||||
*/
|
*/
|
||||||
enum riscv_isa_ext_key {
|
enum riscv_isa_ext_key {
|
||||||
RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */
|
RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */
|
||||||
|
RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
|
||||||
RISCV_ISA_EXT_KEY_MAX,
|
RISCV_ISA_EXT_KEY_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,6 +88,8 @@ static __always_inline int riscv_isa_ext2key(int num)
|
|||||||
return RISCV_ISA_EXT_KEY_FPU;
|
return RISCV_ISA_EXT_KEY_FPU;
|
||||||
case RISCV_ISA_EXT_d:
|
case RISCV_ISA_EXT_d:
|
||||||
return RISCV_ISA_EXT_KEY_FPU;
|
return RISCV_ISA_EXT_KEY_FPU;
|
||||||
|
case RISCV_ISA_EXT_ZIHINTPAUSE:
|
||||||
|
return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,11 @@ struct kvm_vcpu_timer {
|
|||||||
u64 next_cycles;
|
u64 next_cycles;
|
||||||
/* Underlying hrtimer instance */
|
/* Underlying hrtimer instance */
|
||||||
struct hrtimer hrt;
|
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);
|
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);
|
int kvm_riscv_vcpu_timer_reset(struct kvm_vcpu *vcpu);
|
||||||
void kvm_riscv_vcpu_timer_restore(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_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
|
#endif
|
||||||
|
@ -122,7 +122,21 @@ enum sbi_ext_pmu_fid {
|
|||||||
SBI_EXT_PMU_COUNTER_FW_READ,
|
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
|
#define RISCV_PMU_RAW_EVENT_IDX 0x20000
|
||||||
|
|
||||||
/** General pmu event codes specified in SBI PMU extension */
|
/** General pmu event codes specified in SBI PMU extension */
|
||||||
@ -189,12 +203,26 @@ enum sbi_pmu_ctr_type {
|
|||||||
SBI_PMU_CTR_TYPE_FW,
|
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 */
|
/* Flags defined for config matching function */
|
||||||
#define SBI_PMU_CFG_FLAG_SKIP_MATCH (1 << 0)
|
#define SBI_PMU_CFG_FLAG_SKIP_MATCH (1 << 0)
|
||||||
#define SBI_PMU_CFG_FLAG_CLEAR_VALUE (1 << 1)
|
#define SBI_PMU_CFG_FLAG_CLEAR_VALUE (1 << 1)
|
||||||
#define SBI_PMU_CFG_FLAG_AUTO_START (1 << 2)
|
#define SBI_PMU_CFG_FLAG_AUTO_START (1 << 2)
|
||||||
#define SBI_PMU_CFG_FLAG_SET_VUINH (1 << 3)
|
#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_UINH (1 << 5)
|
||||||
#define SBI_PMU_CFG_FLAG_SET_SINH (1 << 6)
|
#define SBI_PMU_CFG_FLAG_SET_SINH (1 << 6)
|
||||||
#define SBI_PMU_CFG_FLAG_SET_MINH (1 << 7)
|
#define SBI_PMU_CFG_FLAG_SET_MINH (1 << 7)
|
||||||
|
@ -4,15 +4,30 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#include <linux/jump_label.h>
|
||||||
#include <asm/barrier.h>
|
#include <asm/barrier.h>
|
||||||
|
#include <asm/hwcap.h>
|
||||||
|
|
||||||
static inline void cpu_relax(void)
|
static inline void cpu_relax(void)
|
||||||
{
|
{
|
||||||
|
if (!static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_ZIHINTPAUSE])) {
|
||||||
#ifdef __riscv_muldiv
|
#ifdef __riscv_muldiv
|
||||||
int dummy;
|
int dummy;
|
||||||
/* In lieu of a halt instruction, induce a long-latency stall. */
|
/* In lieu of a halt instruction, induce a long-latency stall. */
|
||||||
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
|
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
|
||||||
#endif
|
#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();
|
barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ enum KVM_RISCV_ISA_EXT_ID {
|
|||||||
KVM_RISCV_ISA_EXT_I,
|
KVM_RISCV_ISA_EXT_I,
|
||||||
KVM_RISCV_ISA_EXT_M,
|
KVM_RISCV_ISA_EXT_M,
|
||||||
KVM_RISCV_ISA_EXT_SVPBMT,
|
KVM_RISCV_ISA_EXT_SVPBMT,
|
||||||
|
KVM_RISCV_ISA_EXT_SSTC,
|
||||||
KVM_RISCV_ISA_EXT_MAX,
|
KVM_RISCV_ISA_EXT_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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[] = {
|
static struct riscv_isa_ext_data isa_ext_arr[] = {
|
||||||
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
|
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
|
||||||
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
|
__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),
|
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,15 +9,14 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <asm/cpu_ops.h>
|
#include <asm/cpu_ops.h>
|
||||||
|
#include <asm/cpu_ops_sbi.h>
|
||||||
#include <asm/sbi.h>
|
#include <asm/sbi.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
|
||||||
const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
|
const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
|
||||||
|
|
||||||
extern const struct cpu_operations cpu_ops_sbi;
|
extern const struct cpu_operations cpu_ops_sbi;
|
||||||
#ifdef CONFIG_RISCV_BOOT_SPINWAIT
|
#ifndef CONFIG_RISCV_BOOT_SPINWAIT
|
||||||
extern const struct cpu_operations cpu_ops_spinwait;
|
|
||||||
#else
|
|
||||||
const struct cpu_operations cpu_ops_spinwait = {
|
const struct cpu_operations cpu_ops_spinwait = {
|
||||||
.name = "",
|
.name = "",
|
||||||
.cpu_prepare = NULL,
|
.cpu_prepare = NULL,
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include <asm/sbi.h>
|
#include <asm/sbi.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
|
||||||
|
#include "head.h"
|
||||||
|
|
||||||
const struct cpu_operations cpu_ops_spinwait;
|
const struct cpu_operations cpu_ops_spinwait;
|
||||||
void *__cpu_spinwait_stack_pointer[NR_CPUS] __section(".data");
|
void *__cpu_spinwait_stack_pointer[NR_CPUS] __section(".data");
|
||||||
void *__cpu_spinwait_task_pointer[NR_CPUS] __section(".data");
|
void *__cpu_spinwait_task_pointer[NR_CPUS] __section(".data");
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <asm/alternative.h>
|
#include <asm/alternative.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/errata_list.h>
|
#include <asm/errata_list.h>
|
||||||
#include <asm/hwcap.h>
|
#include <asm/hwcap.h>
|
||||||
#include <asm/patch.h>
|
#include <asm/patch.h>
|
||||||
@ -200,6 +201,9 @@ void __init riscv_fill_hwcap(void)
|
|||||||
} else {
|
} else {
|
||||||
SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
|
SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
|
||||||
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
|
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
|
#undef SET_ISA_EXT_MAP
|
||||||
}
|
}
|
||||||
@ -261,6 +265,25 @@ static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
|
|||||||
return false;
|
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.
|
* Probe presence of individual extensions.
|
||||||
*
|
*
|
||||||
@ -275,6 +298,9 @@ static u32 __init_or_module cpufeature_probe(unsigned int stage)
|
|||||||
if (cpufeature_probe_svpbmt(stage))
|
if (cpufeature_probe_svpbmt(stage))
|
||||||
cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
|
cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
|
||||||
|
|
||||||
|
if (cpufeature_probe_zicbom(stage))
|
||||||
|
cpu_req_feature |= (1U << CPUFEATURE_ZICBOM);
|
||||||
|
|
||||||
return cpu_req_feature;
|
return cpu_req_feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ SYM_CODE_START(riscv_crash_save_regs)
|
|||||||
REG_S t6, PT_T6(a0) /* x31 */
|
REG_S t6, PT_T6(a0) /* x31 */
|
||||||
|
|
||||||
csrr t1, CSR_STATUS
|
csrr t1, CSR_STATUS
|
||||||
csrr t2, CSR_EPC
|
auipc t2, 0x0
|
||||||
csrr t3, CSR_TVAL
|
csrr t3, CSR_TVAL
|
||||||
csrr t4, CSR_CAUSE
|
csrr t4, CSR_CAUSE
|
||||||
|
|
||||||
|
@ -138,19 +138,37 @@ void machine_shutdown(void)
|
|||||||
#endif
|
#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
|
* machine_crash_shutdown - Prepare to kexec after a kernel crash
|
||||||
*
|
*
|
||||||
* This function is called by crash_kexec just before machine_kexec
|
* This function is called by crash_kexec just before machine_kexec
|
||||||
* below and its goal is similar to machine_shutdown, but in case of
|
* and its goal is to shutdown non-crashing cpus and save registers.
|
||||||
* a kernel crash. Since we don't handle such cases yet, this function
|
|
||||||
* is empty.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
machine_crash_shutdown(struct pt_regs *regs)
|
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());
|
crash_save_cpu(regs, smp_processor_id());
|
||||||
machine_shutdown();
|
|
||||||
pr_info("Starting crashdump kernel...\n");
|
pr_info("Starting crashdump kernel...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +189,7 @@ machine_kexec(struct kimage *image)
|
|||||||
struct kimage_arch *internal = &image->arch;
|
struct kimage_arch *internal = &image->arch;
|
||||||
unsigned long jump_addr = (unsigned long) image->start;
|
unsigned long jump_addr = (unsigned long) image->start;
|
||||||
unsigned long first_ind_entry = (unsigned long) &image->head;
|
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 this_hart_id = cpuid_to_hartid_map(this_cpu_id);
|
||||||
unsigned long fdt_addr = internal->fdt_addr;
|
unsigned long fdt_addr = internal->fdt_addr;
|
||||||
void *control_code_buffer = page_address(image->control_code_page);
|
void *control_code_buffer = page_address(image->control_code_page);
|
||||||
|
@ -59,8 +59,6 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|||||||
|
|
||||||
instruction_pointer_set(regs, utask->xol_vaddr);
|
instruction_pointer_set(regs, utask->xol_vaddr);
|
||||||
|
|
||||||
regs->status &= ~SR_SPIE;
|
|
||||||
|
|
||||||
return 0;
|
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);
|
instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size);
|
||||||
|
|
||||||
regs->status |= SR_SPIE;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,8 +107,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|||||||
* address.
|
* address.
|
||||||
*/
|
*/
|
||||||
instruction_pointer_set(regs, utask->vaddr);
|
instruction_pointer_set(regs, utask->vaddr);
|
||||||
|
|
||||||
regs->status &= ~SR_SPIE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
|
bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <linux/crash_dump.h>
|
#include <linux/crash_dump.h>
|
||||||
|
|
||||||
#include <asm/alternative.h>
|
#include <asm/alternative.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cpu_ops.h>
|
#include <asm/cpu_ops.h>
|
||||||
#include <asm/early_ioremap.h>
|
#include <asm/early_ioremap.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
@ -296,6 +297,7 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
riscv_fill_hwcap();
|
riscv_fill_hwcap();
|
||||||
|
riscv_init_cbom_blocksize();
|
||||||
apply_boot_alternatives();
|
apply_boot_alternatives();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/stringify.h>
|
||||||
|
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
@ -150,9 +151,6 @@
|
|||||||
#define PRECISION_S 0
|
#define PRECISION_S 0
|
||||||
#define PRECISION_D 1
|
#define PRECISION_D 1
|
||||||
|
|
||||||
#define STR(x) XSTR(x)
|
|
||||||
#define XSTR(x) #x
|
|
||||||
|
|
||||||
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \
|
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \
|
||||||
static inline type load_##type(const type *addr) \
|
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"
|
asm ("and %[tmp], %[addr], 2\n"
|
||||||
"bnez %[tmp], 1f\n"
|
"bnez %[tmp], 1f\n"
|
||||||
#if defined(CONFIG_64BIT)
|
#if defined(CONFIG_64BIT)
|
||||||
STR(LWU) " %[insn], (%[addr])\n"
|
__stringify(LWU) " %[insn], (%[addr])\n"
|
||||||
#else
|
#else
|
||||||
STR(LW) " %[insn], (%[addr])\n"
|
__stringify(LW) " %[insn], (%[addr])\n"
|
||||||
#endif
|
#endif
|
||||||
"and %[tmp], %[insn], %[rvc_mask]\n"
|
"and %[tmp], %[insn], %[rvc_mask]\n"
|
||||||
"beq %[tmp], %[rvc_mask], 2f\n"
|
"beq %[tmp], %[rvc_mask], 2f\n"
|
||||||
|
@ -52,6 +52,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
|
|||||||
RISCV_ISA_EXT_i,
|
RISCV_ISA_EXT_i,
|
||||||
RISCV_ISA_EXT_m,
|
RISCV_ISA_EXT_m,
|
||||||
RISCV_ISA_EXT_SVPBMT,
|
RISCV_ISA_EXT_SVPBMT,
|
||||||
|
RISCV_ISA_EXT_SSTC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext)
|
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_C:
|
||||||
case KVM_RISCV_ISA_EXT_I:
|
case KVM_RISCV_ISA_EXT_I:
|
||||||
case KVM_RISCV_ISA_EXT_M:
|
case KVM_RISCV_ISA_EXT_M:
|
||||||
|
case KVM_RISCV_ISA_EXT_SSTC:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -203,7 +205,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
int kvm_cpu_has_pending_timer(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)
|
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))
|
if (__riscv_isa_extension_available(isa, RISCV_ISA_EXT_SVPBMT))
|
||||||
henvcfg |= ENVCFG_PBMTE;
|
henvcfg |= ENVCFG_PBMTE;
|
||||||
|
|
||||||
|
if (__riscv_isa_extension_available(isa, RISCV_ISA_EXT_SSTC))
|
||||||
|
henvcfg |= ENVCFG_STCE;
|
||||||
csr_write(CSR_HENVCFG, henvcfg);
|
csr_write(CSR_HENVCFG, henvcfg);
|
||||||
#ifdef CONFIG_32BIT
|
#ifdef CONFIG_32BIT
|
||||||
csr_write(CSR_HENVCFGH, henvcfg >> 32);
|
csr_write(CSR_HENVCFGH, henvcfg >> 32);
|
||||||
@ -828,6 +832,8 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
|||||||
vcpu->arch.isa);
|
vcpu->arch.isa);
|
||||||
kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context);
|
kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context);
|
||||||
|
|
||||||
|
kvm_riscv_vcpu_timer_save(vcpu);
|
||||||
|
|
||||||
csr->vsstatus = csr_read(CSR_VSSTATUS);
|
csr->vsstatus = csr_read(CSR_VSSTATUS);
|
||||||
csr->vsie = csr_read(CSR_VSIE);
|
csr->vsie = csr_read(CSR_VSIE);
|
||||||
csr->vstvec = csr_read(CSR_VSTVEC);
|
csr->vstvec = csr_read(CSR_VSTVEC);
|
||||||
|
@ -69,7 +69,18 @@ static int kvm_riscv_vcpu_timer_cancel(struct kvm_vcpu_timer *t)
|
|||||||
return 0;
|
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_vcpu_timer *t = &vcpu->arch.timer;
|
||||||
struct kvm_guest_timer *gt = &vcpu->kvm->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;
|
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,
|
int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
|
||||||
const struct kvm_one_reg *reg)
|
const struct kvm_one_reg *reg)
|
||||||
{
|
{
|
||||||
@ -180,10 +250,20 @@ int kvm_riscv_vcpu_timer_init(struct kvm_vcpu *vcpu)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
hrtimer_init(&t->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
hrtimer_init(&t->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||||
t->hrt.function = kvm_riscv_vcpu_hrtimer_expired;
|
|
||||||
t->init_done = true;
|
t->init_done = true;
|
||||||
t->next_set = false;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,19 +279,71 @@ int kvm_riscv_vcpu_timer_deinit(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
int kvm_riscv_vcpu_timer_reset(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);
|
return kvm_riscv_vcpu_timer_cancel(&vcpu->arch.timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kvm_riscv_vcpu_update_timedelta(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
|
||||||
|
|
||||||
|
#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)
|
void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
|
struct kvm_vcpu_csr *csr;
|
||||||
|
struct kvm_vcpu_timer *t = &vcpu->arch.timer;
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
kvm_riscv_vcpu_update_timedelta(vcpu);
|
||||||
csr_write(CSR_HTIMEDELTA, gt->time_delta);
|
|
||||||
|
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
|
#else
|
||||||
csr_write(CSR_HTIMEDELTA, (u32)(gt->time_delta));
|
csr_write(CSR_VSTIMECMP, t->next_cycles);
|
||||||
csr_write(CSR_HTIMEDELTAH, (u32)(gt->time_delta >> 32));
|
|
||||||
#endif
|
#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)
|
void kvm_riscv_guest_timer_init(struct kvm *kvm)
|
||||||
|
@ -175,7 +175,7 @@ ENTRY(__asm_copy_from_user)
|
|||||||
/* Exception fixup code */
|
/* Exception fixup code */
|
||||||
10:
|
10:
|
||||||
/* Disable access to user memory */
|
/* Disable access to user memory */
|
||||||
csrs CSR_STATUS, t6
|
csrc CSR_STATUS, t6
|
||||||
mv a0, t5
|
mv a0, t5
|
||||||
ret
|
ret
|
||||||
ENDPROC(__asm_copy_to_user)
|
ENDPROC(__asm_copy_to_user)
|
||||||
@ -227,7 +227,7 @@ ENTRY(__clear_user)
|
|||||||
/* Exception fixup code */
|
/* Exception fixup code */
|
||||||
11:
|
11:
|
||||||
/* Disable access to user memory */
|
/* Disable access to user memory */
|
||||||
csrs CSR_STATUS, t6
|
csrc CSR_STATUS, t6
|
||||||
mv a0, a1
|
mv a0, a1
|
||||||
ret
|
ret
|
||||||
ENDPROC(__clear_user)
|
ENDPROC(__clear_user)
|
||||||
|
@ -30,3 +30,4 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
|
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
|
||||||
|
obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
|
||||||
|
116
arch/riscv/mm/dma-noncoherent.c
Normal file
116
arch/riscv/mm/dma-noncoherent.c
Normal file
@ -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;
|
||||||
|
}
|
@ -135,6 +135,10 @@ static void __init print_vm_layout(void)
|
|||||||
(unsigned long)VMEMMAP_END);
|
(unsigned long)VMEMMAP_END);
|
||||||
print_ml("vmalloc", (unsigned long)VMALLOC_START,
|
print_ml("vmalloc", (unsigned long)VMALLOC_START,
|
||||||
(unsigned long)VMALLOC_END);
|
(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,
|
print_ml("lowmem", (unsigned long)PAGE_OFFSET,
|
||||||
(unsigned long)high_memory);
|
(unsigned long)high_memory);
|
||||||
if (IS_ENABLED(CONFIG_64BIT)) {
|
if (IS_ENABLED(CONFIG_64BIT)) {
|
||||||
|
1
arch/riscv/purgatory/.gitignore
vendored
1
arch/riscv/purgatory/.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
purgatory.chk
|
purgatory.chk
|
||||||
purgatory.ro
|
purgatory.ro
|
||||||
kexec-purgatory.c
|
|
||||||
|
@ -84,12 +84,6 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
|
|||||||
$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE
|
$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE
|
||||||
$(call if_changed,ld)
|
$(call if_changed,ld)
|
||||||
|
|
||||||
targets += kexec-purgatory.c
|
$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro $(obj)/purgatory.chk
|
||||||
|
|
||||||
quiet_cmd_bin2c = BIN2C $@
|
obj-y += kexec-purgatory.o
|
||||||
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
|
|
||||||
|
14
arch/riscv/purgatory/kexec-purgatory.S
Normal file
14
arch/riscv/purgatory/kexec-purgatory.S
Normal file
@ -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
|
@ -7,6 +7,9 @@
|
|||||||
* either be read from the "time" and "timeh" CSRs, and can use the SBI to
|
* either be read from the "time" and "timeh" CSRs, and can use the SBI to
|
||||||
* setup events, or directly accessed using MMIO registers.
|
* setup events, or directly accessed using MMIO registers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "riscv-timer: " fmt
|
||||||
|
|
||||||
#include <linux/clocksource.h>
|
#include <linux/clocksource.h>
|
||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
@ -20,14 +23,28 @@
|
|||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <clocksource/timer-riscv.h>
|
#include <clocksource/timer-riscv.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
#include <asm/hwcap.h>
|
||||||
#include <asm/sbi.h>
|
#include <asm/sbi.h>
|
||||||
#include <asm/timex.h>
|
#include <asm/timex.h>
|
||||||
|
|
||||||
|
static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
|
||||||
|
|
||||||
static int riscv_clock_next_event(unsigned long delta,
|
static int riscv_clock_next_event(unsigned long delta,
|
||||||
struct clock_event_device *ce)
|
struct clock_event_device *ce)
|
||||||
{
|
{
|
||||||
|
u64 next_tval = get_cycles64() + delta;
|
||||||
|
|
||||||
csr_set(CSR_IE, IE_TIE);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +183,12 @@ static int __init riscv_timer_init_dt(struct device_node *n)
|
|||||||
if (error)
|
if (error)
|
||||||
pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
|
pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
|
||||||
error);
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
* It returns true if "dma-coherent" property was found
|
||||||
* for this device in the DT, or if DMA is coherent by
|
* 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)
|
bool of_dma_is_coherent(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
bool is_coherent = IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT);
|
||||||
if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
node = of_node_get(np);
|
node = of_node_get(np);
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
if (of_property_read_bool(node, "dma-coherent")) {
|
if (of_property_read_bool(node, "dma-coherent")) {
|
||||||
of_node_put(node);
|
is_coherent = true;
|
||||||
return true;
|
break;
|
||||||
|
}
|
||||||
|
if (of_property_read_bool(node, "dma-noncoherent")) {
|
||||||
|
is_coherent = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
node = of_get_next_dma_parent(node);
|
node = of_get_next_dma_parent(node);
|
||||||
}
|
}
|
||||||
of_node_put(node);
|
of_node_put(node);
|
||||||
return false;
|
return is_coherent;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_dma_is_coherent);
|
EXPORT_SYMBOL_GPL(of_dma_is_coherent);
|
||||||
|
|
||||||
|
@ -170,7 +170,6 @@ int riscv_pmu_event_set_period(struct perf_event *event)
|
|||||||
left = (max_period >> 1);
|
left = (max_period >> 1);
|
||||||
|
|
||||||
local64_set(&hwc->prev_count, (u64)-left);
|
local64_set(&hwc->prev_count, (u64)-left);
|
||||||
perf_event_update_userpage(event);
|
|
||||||
|
|
||||||
return overflow;
|
return overflow;
|
||||||
}
|
}
|
||||||
|
@ -41,20 +41,6 @@ static const struct attribute_group *riscv_pmu_attr_groups[] = {
|
|||||||
NULL,
|
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
|
* RISC-V doesn't have hetergenous harts yet. This need to be part of
|
||||||
* per_cpu in case of harts with different pmu counters
|
* 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;
|
cflags |= SBI_PMU_CFG_FLAG_SET_UINH;
|
||||||
|
|
||||||
/* retrieve the available counter index */
|
/* 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,
|
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask,
|
||||||
cflags, hwc->event_base, hwc->config, 0);
|
cflags, hwc->event_base, hwc->config, 0);
|
||||||
|
#endif
|
||||||
if (ret.error) {
|
if (ret.error) {
|
||||||
pr_debug("Not able to find a counter for event %lx config %llx\n",
|
pr_debug("Not able to find a counter for event %lx config %llx\n",
|
||||||
hwc->event_base, hwc->config);
|
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;
|
struct hw_perf_event *hwc = &event->hw;
|
||||||
unsigned long flag = SBI_PMU_START_FLAG_SET_INIT_VALUE;
|
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,
|
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, hwc->idx,
|
||||||
1, flag, ival, ival >> 32, 0);
|
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))
|
if (ret.error && (ret.error != SBI_ERR_ALREADY_STARTED))
|
||||||
pr_err("Starting counter idx %d failed with error %d\n",
|
pr_err("Starting counter idx %d failed with error %d\n",
|
||||||
hwc->idx, sbi_err_map_linux_errno(ret.error));
|
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;
|
hwc = &event->hw;
|
||||||
max_period = riscv_pmu_ctr_get_width_mask(event);
|
max_period = riscv_pmu_ctr_get_width_mask(event);
|
||||||
init_val = local64_read(&hwc->prev_count) & max_period;
|
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,
|
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx, 1,
|
||||||
flag, init_val, 0, 0);
|
flag, init_val, 0, 0);
|
||||||
|
#endif
|
||||||
|
perf_event_update_userpage(event);
|
||||||
}
|
}
|
||||||
ctr_ovf_mask = ctr_ovf_mask >> 1;
|
ctr_ovf_mask = ctr_ovf_mask >> 1;
|
||||||
idx++;
|
idx++;
|
||||||
|
@ -42,6 +42,8 @@ if [ -n "${building_out_of_srctree}" ]; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
rm -f arch/riscv/purgatory/kexec-purgatory.c
|
||||||
|
|
||||||
rm -f scripts/extract-cert
|
rm -f scripts/extract-cert
|
||||||
|
|
||||||
rm -f arch/x86/purgatory/kexec-purgatory.c
|
rm -f arch/x86/purgatory/kexec-purgatory.c
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
CONFIG_NONPORTABLE=y
|
||||||
CONFIG_ARCH_RV32I=y
|
CONFIG_ARCH_RV32I=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
CONFIG_FPU=y
|
CONFIG_FPU=y
|
||||||
|
Loading…
Reference in New Issue
Block a user