summaryrefslogtreecommitdiff
path: root/arch/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv')
-rw-r--r--arch/riscv/Kconfig53
-rw-r--r--arch/riscv/Kconfig.errata23
-rw-r--r--arch/riscv/Kconfig.socs6
-rw-r--r--arch/riscv/Kconfig.vendor13
-rw-r--r--arch/riscv/Makefile9
-rw-r--r--arch/riscv/boot/dts/Makefile1
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi48
-rw-r--r--arch/riscv/boot/dts/eswin/Makefile2
-rw-r--r--arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts29
-rw-r--r--arch/riscv/boot/dts/eswin/eic7700.dtsi345
-rw-r--r--arch/riscv/boot/dts/microchip/Makefile2
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts2
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-disco-kit-fabric.dtsi58
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-disco-kit.dts190
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit-common.dtsi249
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi25
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit-prod.dts23
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts244
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi64
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042.dtsi22
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2044.dtsi2
-rw-r--r--arch/riscv/boot/dts/spacemit/Makefile1
-rw-r--r--arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts52
-rw-r--r--arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts52
-rw-r--r--arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts40
-rw-r--r--arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi48
-rw-r--r--arch/riscv/boot/dts/spacemit/k1.dtsi53
-rw-r--r--arch/riscv/boot/dts/starfive/Makefile2
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-common.dtsi4
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-emmc.dts12
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-lite.dts25
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-milkv-marscm.dtsi159
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110.dtsi24
-rw-r--r--arch/riscv/boot/dts/thead/th1520.dtsi21
-rw-r--r--arch/riscv/configs/defconfig6
-rw-r--r--arch/riscv/errata/Makefile1
-rw-r--r--arch/riscv/errata/mips/Makefile5
-rw-r--r--arch/riscv/errata/mips/errata.c67
-rw-r--r--arch/riscv/include/asm/alternative-macros.h12
-rw-r--r--arch/riscv/include/asm/alternative.h5
-rw-r--r--arch/riscv/include/asm/asm-extable.h6
-rw-r--r--arch/riscv/include/asm/asm.h10
-rw-r--r--arch/riscv/include/asm/assembler.h2
-rw-r--r--arch/riscv/include/asm/barrier.h4
-rw-r--r--arch/riscv/include/asm/bitops.h6
-rw-r--r--arch/riscv/include/asm/cache.h4
-rw-r--r--arch/riscv/include/asm/cacheflush.h4
-rw-r--r--arch/riscv/include/asm/cfi.h4
-rw-r--r--arch/riscv/include/asm/cmpxchg.h9
-rw-r--r--arch/riscv/include/asm/cpu_ops_sbi.h2
-rw-r--r--arch/riscv/include/asm/csr.h4
-rw-r--r--arch/riscv/include/asm/current.h4
-rw-r--r--arch/riscv/include/asm/errata_list.h38
-rw-r--r--arch/riscv/include/asm/errata_list_vendors.h29
-rw-r--r--arch/riscv/include/asm/ftrace.h6
-rw-r--r--arch/riscv/include/asm/gpr-num.h6
-rw-r--r--arch/riscv/include/asm/hugetlb.h2
-rw-r--r--arch/riscv/include/asm/hwprobe.h3
-rw-r--r--arch/riscv/include/asm/image.h4
-rw-r--r--arch/riscv/include/asm/insn-def.h8
-rw-r--r--arch/riscv/include/asm/insn.h216
-rw-r--r--arch/riscv/include/asm/io.h4
-rw-r--r--arch/riscv/include/asm/jump_label.h4
-rw-r--r--arch/riscv/include/asm/kasan.h2
-rw-r--r--arch/riscv/include/asm/kgdb.h4
-rw-r--r--arch/riscv/include/asm/mmu.h4
-rw-r--r--arch/riscv/include/asm/page.h4
-rw-r--r--arch/riscv/include/asm/pgtable.h22
-rw-r--r--arch/riscv/include/asm/processor.h4
-rw-r--r--arch/riscv/include/asm/ptrace.h4
-rw-r--r--arch/riscv/include/asm/scs.h4
-rw-r--r--arch/riscv/include/asm/set_memory.h4
-rw-r--r--arch/riscv/include/asm/swab.h87
-rw-r--r--arch/riscv/include/asm/thread_info.h35
-rw-r--r--arch/riscv/include/asm/vdso.h4
-rw-r--r--arch/riscv/include/asm/vdso/getrandom.h4
-rw-r--r--arch/riscv/include/asm/vdso/gettimeofday.h4
-rw-r--r--arch/riscv/include/asm/vdso/processor.h7
-rw-r--r--arch/riscv/include/asm/vdso/vsyscall.h4
-rw-r--r--arch/riscv/include/asm/vendor_extensions/mips.h37
-rw-r--r--arch/riscv/include/asm/vendor_extensions/mips_hwprobe.h22
-rw-r--r--arch/riscv/include/asm/vendorid_list.h1
-rw-r--r--arch/riscv/include/uapi/asm/hwprobe.h1
-rw-r--r--arch/riscv/include/uapi/asm/kvm.h2
-rw-r--r--arch/riscv/include/uapi/asm/ptrace.h4
-rw-r--r--arch/riscv/include/uapi/asm/sigcontext.h4
-rw-r--r--arch/riscv/include/uapi/asm/vendor/mips.h3
-rw-r--r--arch/riscv/kernel/Makefile2
-rw-r--r--arch/riscv/kernel/acpi.c3
-rw-r--r--arch/riscv/kernel/alternative.c5
-rw-r--r--arch/riscv/kernel/asm-offsets.c1
-rw-r--r--arch/riscv/kernel/cpufeature.c6
-rw-r--r--arch/riscv/kernel/entry.S1
-rw-r--r--arch/riscv/kernel/machine_kexec_file.c2
-rw-r--r--arch/riscv/kernel/pi/Makefile2
-rw-r--r--arch/riscv/kernel/pi/cmdline_early.c4
-rw-r--r--arch/riscv/kernel/pi/fdt_early.c40
-rw-r--r--arch/riscv/kernel/pi/pi.h1
-rw-r--r--arch/riscv/kernel/probes/simulate-insn.c94
-rw-r--r--arch/riscv/kernel/process.c2
-rw-r--r--arch/riscv/kernel/sbi.c4
-rw-r--r--arch/riscv/kernel/setup.c1
-rw-r--r--arch/riscv/kernel/sys_hwprobe.c18
-rw-r--r--arch/riscv/kernel/sys_riscv.c2
-rw-r--r--arch/riscv/kernel/tests/Kconfig.debug12
-rw-r--r--arch/riscv/kernel/tests/Makefile1
-rw-r--r--arch/riscv/kernel/tests/kprobes/Makefile1
-rw-r--r--arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S229
-rw-r--r--arch/riscv/kernel/tests/kprobes/test-kprobes.c56
-rw-r--r--arch/riscv/kernel/tests/kprobes/test-kprobes.h24
-rw-r--r--arch/riscv/kernel/traps_misaligned.c144
-rw-r--r--arch/riscv/kernel/vector.c2
-rw-r--r--arch/riscv/kernel/vendor_extensions.c10
-rw-r--r--arch/riscv/kernel/vendor_extensions/Makefile2
-rw-r--r--arch/riscv/kernel/vendor_extensions/mips.c22
-rw-r--r--arch/riscv/kernel/vendor_extensions/mips_hwprobe.c23
-rw-r--r--arch/riscv/kvm/vcpu_insn.c128
-rw-r--r--arch/riscv/mm/cacheflush.c4
-rw-r--r--arch/riscv/mm/init.c16
-rw-r--r--arch/riscv/mm/kasan_init.c1
-rw-r--r--arch/riscv/net/bpf_jit.h70
-rw-r--r--arch/riscv/net/bpf_jit_comp64.c573
-rw-r--r--arch/riscv/purgatory/Makefile2
124 files changed, 2940 insertions, 1219 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 51dcd8eaa243..0c6038dc5dfd 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -16,6 +16,7 @@ config RISCV
select ACPI_MCFG if (ACPI && PCI)
select ACPI_PPTT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+ select ACPI_RIMT if ACPI
select ACPI_SPCR_TABLE if ACPI
select ARCH_DMA_DEFAULT_COHERENT
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
@@ -28,6 +29,7 @@ config RISCV
select ARCH_HAS_DEBUG_VIRTUAL if MMU
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX
+ select ARCH_HAS_ELF_CORE_EFLAGS
select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
@@ -52,7 +54,8 @@ config RISCV
select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN
- select ARCH_HAS_VDSO_ARCH_DATA if GENERIC_VDSO_DATA_STORE
+ select ARCH_HAS_VDSO_ARCH_DATA if HAVE_GENERIC_VDSO
+ select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_KEEP_MEMBLOCK if ACPI
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
@@ -60,23 +63,23 @@ config RISCV
select ARCH_STACKWALK
select ARCH_SUPPORTS_ATOMIC_RMW
# clang >= 17: https://github.com/llvm/llvm-project/commit/62fa708ceb027713b386c7e0efda994f8bdc27e2
- select ARCH_SUPPORTS_CFI_CLANG if CLANG_VERSION >= 170000
+ select ARCH_SUPPORTS_CFI if (!CC_IS_CLANG || CLANG_VERSION >= 170000)
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE
select ARCH_SUPPORTS_HUGETLBFS if MMU
- # LLD >= 14: https://github.com/llvm/llvm-project/issues/50505
- select ARCH_SUPPORTS_LTO_CLANG if LLD_VERSION >= 140000 && CMODEL_MEDANY
- select ARCH_SUPPORTS_LTO_CLANG_THIN if LLD_VERSION >= 140000
+ select ARCH_SUPPORTS_LTO_CLANG if CMODEL_MEDANY
+ select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS if 64BIT && MMU
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU
select ARCH_SUPPORTS_PER_VMA_LOCK if MMU
select ARCH_SUPPORTS_RT
select ARCH_SUPPORTS_SHADOW_CALL_STACK if HAVE_SHADOW_CALL_STACK
+ select ARCH_SUPPORTS_SCHED_MC if SMP
select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_SYM_ANNOTATIONS
- select ARCH_USES_CFI_TRAPS if CFI_CLANG
+ select ARCH_USES_CFI_TRAPS if CFI
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if MMU
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
select ARCH_WANT_FRAME_POINTERS
@@ -107,7 +110,7 @@ config RISCV
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY
- select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
+ select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO && 64BIT
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IOREMAP if MMU
select GENERIC_IRQ_IPI if SMP
@@ -120,9 +123,7 @@ config RISCV
select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_TIME_VSYSCALL if MMU && 64BIT
- select GENERIC_VDSO_DATA_STORE if MMU
- select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
+ select GENERIC_TIME_VSYSCALL if GENERIC_GETTIMEOFDAY
select HARDIRQS_SW_RESEND
select HAS_IOPORT if MMU
select HAVE_ALIGNED_STRUCT_PAGE
@@ -154,18 +155,19 @@ config RISCV
select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE)
select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
- select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI_CLANG)
+ select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI)
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_GRAPH_FUNC
select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS
select HAVE_FUNCTION_GRAPH_FREGS
select HAVE_FUNCTION_TRACER if !XIP_KERNEL && HAVE_DYNAMIC_FTRACE
select HAVE_EBPF_JIT if MMU
+ select HAVE_GENERIC_TIF_BITS
select HAVE_GUP_FAST if MMU
select HAVE_FUNCTION_ARG_ACCESS_API
select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_GCC_PLUGINS
- select HAVE_GENERIC_VDSO if MMU && 64BIT
+ select HAVE_GENERIC_VDSO if MMU
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_KERNEL_BZIP2 if !XIP_KERNEL && !EFI_ZBOOT
select HAVE_KERNEL_GZIP if !XIP_KERNEL && !EFI_ZBOOT
@@ -221,7 +223,7 @@ config RISCV
select THREAD_INFO_IN_TASK
select TRACE_IRQFLAGS_SUPPORT
select UACCESS_MEMCPY if !MMU
- select VDSO_GETRANDOM if HAVE_GENERIC_VDSO
+ select VDSO_GETRANDOM if HAVE_GENERIC_VDSO && 64BIT
select USER_STACKTRACE_SUPPORT
select ZONE_DMA32 if 64BIT
@@ -247,15 +249,9 @@ config HAVE_SHADOW_CALL_STACK
# https://github.com/riscv-non-isa/riscv-elf-psabi-doc/commit/a484e843e6eeb51f0cb7b8819e50da6d2444d769
depends on $(ld-option,--no-relax-gp)
-config RISCV_USE_LINKER_RELAXATION
- def_bool y
- # https://github.com/llvm/llvm-project/commit/6611d58f5bbcbec77262d392e2923e1d680f6985
- depends on !LD_IS_LLD || LLD_VERSION >= 150000
-
# https://github.com/llvm/llvm-project/commit/bbc0f99f3bc96f1db16f649fc21dd18e5b0918f6
config ARCH_HAS_BROKEN_DWARF5
def_bool y
- depends on RISCV_USE_LINKER_RELAXATION
# https://github.com/llvm/llvm-project/commit/1df5ea29b43690b6622db2cad7b745607ca4de6a
depends on AS_IS_LLVM && AS_VERSION < 180000
# https://github.com/llvm/llvm-project/commit/7ffabb61a5569444b5ac9322e22e5471cc5e4a77
@@ -453,14 +449,6 @@ config SMP
If you don't know what to do here, say N.
-config SCHED_MC
- bool "Multi-core scheduler support"
- depends on SMP
- help
- Multi-core scheduler support improves the CPU scheduler's decision
- making when dealing with multi-core CPU chips at a cost of slightly
- increased overhead in some places. If unsure say N here.
-
config NR_CPUS
int "Maximum number of CPUs (2-512)"
depends on SMP
@@ -627,7 +615,7 @@ config TOOLCHAIN_HAS_V
default y
depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64imv)
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32imv)
- depends on LLD_VERSION >= 140000 || LD_VERSION >= 23800
+ depends on LD_IS_LLD || LD_VERSION >= 23800
depends on AS_HAS_OPTION_ARCH
config RISCV_ISA_V
@@ -714,7 +702,6 @@ config TOOLCHAIN_HAS_ZACAS
config RISCV_ISA_ZACAS
bool "Zacas extension support for atomic CAS"
- depends on TOOLCHAIN_HAS_ZACAS
depends on RISCV_ALTERNATIVE
default y
help
@@ -728,7 +715,7 @@ config TOOLCHAIN_HAS_ZBB
default y
depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zbb)
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zbb)
- depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
+ depends on LD_IS_LLD || LD_VERSION >= 23900
depends on AS_HAS_OPTION_ARCH
# This symbol indicates that the toolchain supports all v1.0 vector crypto
@@ -743,7 +730,7 @@ config TOOLCHAIN_HAS_ZBA
default y
depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zba)
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zba)
- depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
+ depends on LD_IS_LLD || LD_VERSION >= 23900
depends on AS_HAS_OPTION_ARCH
config RISCV_ISA_ZBA
@@ -778,7 +765,7 @@ config TOOLCHAIN_HAS_ZBC
default y
depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zbc)
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zbc)
- depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
+ depends on LD_IS_LLD || LD_VERSION >= 23900
depends on AS_HAS_OPTION_ARCH
config RISCV_ISA_ZBC
@@ -801,7 +788,7 @@ config TOOLCHAIN_HAS_ZBKB
default y
depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zbkb)
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zbkb)
- depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
+ depends on LD_IS_LLD || LD_VERSION >= 23900
depends on AS_HAS_OPTION_ARCH
config RISCV_ISA_ZBKB
diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index e318119d570d..aca9b0cfcfec 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -21,6 +21,29 @@ config ERRATA_ANDES_CMO
If you don't know what to do here, say "Y".
+config ERRATA_MIPS
+ bool "MIPS errata"
+ depends on RISCV_ALTERNATIVE
+ help
+ All MIPS errata Kconfig depend on this Kconfig. Disabling
+ this Kconfig will disable all MIPS errata. Please say "Y"
+ here if your platform uses MIPS CPU cores.
+
+ Otherwise, please say "N" here to avoid unnecessary overhead.
+
+config ERRATA_MIPS_P8700_PAUSE_OPCODE
+ bool "Fix the PAUSE Opcode for MIPS P8700"
+ depends on ERRATA_MIPS && 64BIT
+ default n
+ help
+ The RISCV MIPS P8700 uses a different opcode for PAUSE.
+ It is a 'hint' encoding of the SLLI instruction,
+ with rd=0, rs1=0 and imm=5. It will behave as a NOP
+ instruction if no additional behavior beyond that of
+ SLLI is implemented.
+
+ If you are not using the P8700 processor, say n.
+
config ERRATA_SIFIVE
bool "SiFive errata"
depends on RISCV_ALTERNATIVE
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 61ceae0aa27a..848e7149e443 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -7,6 +7,12 @@ config ARCH_ANDES
help
This enables support for Andes SoC platform hardware.
+config ARCH_ESWIN
+ bool "ESWIN SoCs"
+ help
+ This enables support for ESWIN SoC platform hardware,
+ including the ESWIN EIC7700 SoC.
+
config ARCH_MICROCHIP_POLARFIRE
def_bool ARCH_MICROCHIP
diff --git a/arch/riscv/Kconfig.vendor b/arch/riscv/Kconfig.vendor
index e14f26368963..3c1f92e406c3 100644
--- a/arch/riscv/Kconfig.vendor
+++ b/arch/riscv/Kconfig.vendor
@@ -16,6 +16,19 @@ config RISCV_ISA_VENDOR_EXT_ANDES
If you don't know what to do here, say Y.
endmenu
+menu "MIPS"
+config RISCV_ISA_VENDOR_EXT_MIPS
+ bool "MIPS vendor extension support"
+ select RISCV_ISA_VENDOR_EXT
+ default y
+ help
+ Say N here to disable detection of and support for all MIPS vendor
+ extensions. Without this option enabled, MIPS vendor extensions will
+ not be detected at boot and their presence not reported to userspace.
+
+ If you don't know what to do here, say Y.
+endmenu
+
menu "SiFive"
config RISCV_ISA_VENDOR_EXT_SIFIVE
bool "SiFive vendor extension support"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index df57654a615e..ecf2fcce2d92 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -46,17 +46,10 @@ else
KBUILD_LDFLAGS += -melf32lriscv
endif
-ifndef CONFIG_RISCV_USE_LINKER_RELAXATION
- KBUILD_CFLAGS += -mno-relax
- KBUILD_AFLAGS += -mno-relax
-ifndef CONFIG_AS_IS_LLVM
- KBUILD_CFLAGS += -Wa,-mno-relax
- KBUILD_AFLAGS += -Wa,-mno-relax
-endif
# LLVM has an issue with target-features and LTO: https://github.com/llvm/llvm-project/issues/59350
# Ensure it is aware of linker relaxation with LTO, otherwise relocations may
# be incorrect: https://github.com/llvm/llvm-project/issues/65090
-else ifeq ($(CONFIG_LTO_CLANG),y)
+ifeq ($(CONFIG_LTO_CLANG),y)
KBUILD_LDFLAGS += -mllvm -mattr=+c -mllvm -mattr=+relax
endif
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index 3b99e91efa25..3763d199c70a 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -2,6 +2,7 @@
subdir-y += allwinner
subdir-y += andes
subdir-y += canaan
+subdir-y += eswin
subdir-y += microchip
subdir-y += renesas
subdir-y += sifive
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
index bc5c84f22762..5f2e5cc3e3d5 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
@@ -17,7 +17,7 @@
#cooling-cells = <2>;
};
- i2c-gpio-0 {
+ i2c-0 {
compatible = "i2c-gpio";
sda-gpios = <&pio 3 14 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; /* PD14/GPIO44 */
scl-gpios = <&pio 3 15 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; /* PD15/GPIO45 */
diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
index e4175adb028d..63e252b44973 100644
--- a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
@@ -79,6 +79,36 @@
};
/omit-if-no-ref/
+ i2c2_pd_pins: i2c2-pd-pins {
+ pins = "PD20", "PD21";
+ function = "i2c2";
+ };
+
+ /omit-if-no-ref/
+ i2c3_pg_pins: i2c3-pg-pins {
+ pins = "PG10", "PG11";
+ function = "i2c3";
+ };
+
+ /omit-if-no-ref/
+ i2s1_pins: i2s1-pins {
+ pins = "PG12", "PG13";
+ function = "i2s1";
+ };
+
+ /omit-if-no-ref/
+ i2s1_din0_pin: i2s1-din0-pin {
+ pins = "PG14";
+ function = "i2s1_din";
+ };
+
+ /omit-if-no-ref/
+ i2s1_dout0_pin: i2s1-dout0-pin {
+ pins = "PG15";
+ function = "i2s1_dout";
+ };
+
+ /omit-if-no-ref/
lcd_rgb666_pins: lcd-rgb666-pins {
pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
"PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
@@ -127,6 +157,24 @@
};
/omit-if-no-ref/
+ spi1_pins: spi1-pins {
+ pins = "PD10", "PD11", "PD12", "PD13";
+ function = "spi1";
+ };
+
+ /omit-if-no-ref/
+ spi1_hold_pin: spi1-hold-pin {
+ pins = "PD14";
+ function = "spi1";
+ };
+
+ /omit-if-no-ref/
+ spi1_wp_pin: spi1-wp-pin {
+ pins = "PD15";
+ function = "spi1";
+ };
+
+ /omit-if-no-ref/
uart1_pg6_pins: uart1-pg6-pins {
pins = "PG6", "PG7";
function = "uart1";
diff --git a/arch/riscv/boot/dts/eswin/Makefile b/arch/riscv/boot/dts/eswin/Makefile
new file mode 100644
index 000000000000..224101ae471e
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_ESWIN) += eic7700-hifive-premier-p550.dtb
diff --git a/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts b/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
new file mode 100644
index 000000000000..131ed1fc6b2e
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024, Beijing ESWIN Computing Technology Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "eic7700.dtsi"
+
+/ {
+ compatible = "sifive,hifive-premier-p550", "eswin,eic7700";
+ model = "SiFive HiFive Premier P550";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/eswin/eic7700.dtsi b/arch/riscv/boot/dts/eswin/eic7700.dtsi
new file mode 100644
index 000000000000..c3ed93008bca
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700.dtsi
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024 Beijing ESWIN Computing Technology Co., Ltd.
+ */
+
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <1000000>;
+
+ cpu0: cpu@0 {
+ compatible = "sifive,p550", "riscv";
+ device_type = "cpu";
+ d-cache-block-size = <64>;
+ d-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv48";
+ next-level-cache = <&l2_cache_0>;
+ reg = <0x0>;
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h", "sscofpmf",
+ "zba", "zbb", "zicsr", "zifencei";
+ tlb-split;
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ cpu1: cpu@1 {
+ compatible = "sifive,p550", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv48";
+ next-level-cache = <&l2_cache_1>;
+ reg = <0x1>;
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h", "sscofpmf",
+ "zba", "zbb", "zicsr", "zifencei";
+ tlb-split;
+
+ cpu1_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ cpu2: cpu@2 {
+ compatible = "sifive,p550", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv48";
+ next-level-cache = <&l2_cache_2>;
+ reg = <0x2>;
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h", "sscofpmf",
+ "zba", "zbb", "zicsr", "zifencei";
+ tlb-split;
+
+ cpu2_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ cpu3: cpu@3 {
+ compatible = "sifive,p550", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv48";
+ next-level-cache = <&l2_cache_3>;
+ reg = <0x3>;
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h", "sscofpmf",
+ "zba", "zbb", "zicsr", "zifencei";
+ tlb-split;
+
+ cpu3_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ l2_cache_0: l2-cache0 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-sets = <512>;
+ cache-size = <262144>;
+ cache-unified;
+ next-level-cache = <&ccache>;
+ };
+
+ l2_cache_1: l2-cache1 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-sets = <512>;
+ cache-size = <262144>;
+ cache-unified;
+ next-level-cache = <&ccache>;
+ };
+
+ l2_cache_2: l2-cache2 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-sets = <512>;
+ cache-size = <262144>;
+ cache-unified;
+ next-level-cache = <&ccache>;
+ };
+
+ l2_cache_3: l2-cache3 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-sets = <512>;
+ cache-size = <262144>;
+ cache-unified;
+ next-level-cache = <&ccache>;
+ };
+ };
+
+ pmu {
+ compatible = "riscv,pmu";
+ riscv,event-to-mhpmcounters =
+ <0x00001 0x00001 0x00000001>,
+ <0x00002 0x00002 0x00000004>,
+ <0x00004 0x00006 0x00000078>,
+ <0x10009 0x10009 0x00000078>,
+ <0x10019 0x10019 0x00000078>,
+ <0x10021 0x10021 0x00000078>;
+ riscv,event-to-mhpmevent =
+ <0x00004 0x00000000 0x00000202>,
+ <0x00005 0x00000000 0x00004000>,
+ <0x00006 0x00000000 0x00002001>,
+ <0x10009 0x00000000 0x00000102>,
+ <0x10019 0x00000000 0x00001002>,
+ <0x10021 0x00000000 0x00000802>;
+ riscv,raw-event-to-mhpmcounters =
+ <0x00000000 0x00000000 0xffffffff 0xfc0000ff 0x00000078>,
+ <0x00000000 0x00000001 0xffffffff 0xfffe07ff 0x00000078>,
+ <0x00000000 0x00000002 0xffffffff 0xfffe00ff 0x00000078>,
+ <0x00000000 0x00000003 0xfffffffc 0x000000ff 0x00000078>,
+ <0x00000000 0x00000004 0xffffffc0 0x000000ff 0x00000078>,
+ <0x00000000 0x00000005 0xffffffff 0xfffffdff 0x00000078>,
+ <0x00000000 0x00000006 0xfffffe00 0x110204ff 0x00000078>,
+ <0x00000000 0x00000007 0xffffffff 0xf00000ff 0x00000078>,
+ <0x00000000 0x00000008 0xfffffe04 0x000000ff 0x00000078>,
+ <0x00000000 0x00000009 0xffffffff 0xffffc0ff 0x00000078>,
+ <0x00000000 0x0000000a 0xffffffff 0xf00000ff 0x00000078>,
+ <0x00000000 0x0000000b 0xffffffff 0xfffffcff 0x00000078>,
+ <0x00000000 0x0000000c 0xfffffff0 0x000000ff 0x00000078>,
+ <0x00000000 0x0000000d 0xffffffff 0x800000ff 0x00000078>,
+ <0x00000000 0x0000000e 0xffffffff 0xf80000ff 0x00000078>,
+ <0x00000000 0x0000000f 0xfffffffc 0x000000ff 0x00000078>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges;
+ interrupt-parent = <&plic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-noncoherent;
+
+ clint: timer@2000000 {
+ compatible = "eswin,eic7700-clint", "sifive,clint0";
+ reg = <0x0 0x02000000 0x0 0x10000>;
+ interrupts-extended =
+ <&cpu0_intc 3>, <&cpu0_intc 7>,
+ <&cpu1_intc 3>, <&cpu1_intc 7>,
+ <&cpu2_intc 3>, <&cpu2_intc 7>,
+ <&cpu3_intc 3>, <&cpu3_intc 7>;
+ };
+
+ ccache: cache-controller@2010000 {
+ compatible = "eswin,eic7700-l3-cache", "sifive,ccache0", "cache";
+ reg = <0x0 0x2010000 0x0 0x4000>;
+ interrupts = <1>, <3>, <4>, <2>;
+ cache-block-size = <64>;
+ cache-level = <3>;
+ cache-sets = <4096>;
+ cache-size = <4194304>;
+ cache-unified;
+ };
+
+ plic: interrupt-controller@c000000 {
+ compatible = "eswin,eic7700-plic", "sifive,plic-1.0.0";
+ reg = <0x0 0xc000000 0x0 0x4000000>;
+ interrupt-controller;
+ interrupts-extended =
+ <&cpu0_intc 11>, <&cpu0_intc 9>,
+ <&cpu1_intc 11>, <&cpu1_intc 9>,
+ <&cpu2_intc 11>, <&cpu2_intc 9>,
+ <&cpu3_intc 11>, <&cpu3_intc 9>;
+ riscv,ndev = <520>;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+
+ uart0: serial@50900000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x0 0x50900000 0x0 0x10000>;
+ interrupts = <100>;
+ clock-frequency = <200000000>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart1: serial@50910000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x0 0x50910000 0x0 0x10000>;
+ interrupts = <101>;
+ clock-frequency = <200000000>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart2: serial@50920000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x0 0x50920000 0x0 0x10000>;
+ interrupts = <102>;
+ clock-frequency = <200000000>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart3: serial@50930000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x0 0x50930000 0x0 0x10000>;
+ interrupts = <103>;
+ clock-frequency = <200000000>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart4: serial@50940000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x0 0x50940000 0x0 0x10000>;
+ interrupts = <104>;
+ clock-frequency = <200000000>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ gpio@51600000 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x0 0x51600000 0x0 0x80>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpioA: gpio-port@0 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <0>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts =
+ <303>, <304>, <305>, <306>, <307>, <308>, <309>,
+ <310>, <311>, <312>, <313>, <314>, <315>, <316>,
+ <317>, <318>, <319>, <320>, <321>, <322>, <323>,
+ <324>, <325>, <326>, <327>, <328>, <329>, <330>,
+ <331>, <332>, <333>, <334>;
+ gpio-controller;
+ ngpios = <32>;
+ #gpio-cells = <2>;
+ };
+
+ gpioB: gpio-port@1 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <1>;
+ gpio-controller;
+ ngpios = <32>;
+ #gpio-cells = <2>;
+ };
+
+ gpioC: gpio-port@2 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <2>;
+ gpio-controller;
+ ngpios = <32>;
+ #gpio-cells = <2>;
+ };
+
+ gpioD: gpio-port@3 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <3>;
+ gpio-controller;
+ ngpios = <16>;
+ #gpio-cells = <2>;
+ };
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/microchip/Makefile b/arch/riscv/boot/dts/microchip/Makefile
index f51aeeb9fd3b..345ed7a48cc1 100644
--- a/arch/riscv/boot/dts/microchip/Makefile
+++ b/arch/riscv/boot/dts/microchip/Makefile
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-beaglev-fire.dtb
+dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-disco-kit.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-icicle-kit.dtb
+dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-icicle-kit-prod.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-m100pfsevp.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-polarberry.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-sev-kit.dtb
diff --git a/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts b/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts
index 47cf693beb68..55e30f3636df 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts
@@ -88,7 +88,7 @@
<53>, <53>, <53>, <53>,
<53>, <53>, <53>, <53>,
<53>, <53>, <53>, <53>;
- ngpios=<32>;
+ ngpios = <32>;
gpio-line-names = "P8_PIN3_USER_LED_0", "P8_PIN4_USER_LED_1", "P8_PIN5_USER_LED_2",
"P8_PIN6_USER_LED_3", "P8_PIN7_USER_LED_4", "P8_PIN8_USER_LED_5",
"P8_PIN9_USER_LED_6", "P8_PIN10_USER_LED_7", "P8_PIN11_USER_LED_8",
diff --git a/arch/riscv/boot/dts/microchip/mpfs-disco-kit-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-disco-kit-fabric.dtsi
new file mode 100644
index 000000000000..ae8be7d6f392
--- /dev/null
+++ b/arch/riscv/boot/dts/microchip/mpfs-disco-kit-fabric.dtsi
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2020-2025 Microchip Technology Inc */
+
+/ {
+ core_pwm0: pwm@40000000 {
+ compatible = "microchip,corepwm-rtl-v4";
+ reg = <0x0 0x40000000 0x0 0xF0>;
+ microchip,sync-update-mask = /bits/ 32 <0>;
+ #pwm-cells = <3>;
+ clocks = <&ccc_sw CLK_CCC_PLL0_OUT3>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@40000200 {
+ compatible = "microchip,corei2c-rtl-v7";
+ reg = <0x0 0x40000200 0x0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&ccc_sw CLK_CCC_PLL0_OUT3>;
+ interrupt-parent = <&plic>;
+ interrupts = <122>;
+ clock-frequency = <100000>;
+ status = "disabled";
+ };
+
+ ihc: mailbox {
+ compatible = "microchip,sbi-ipc";
+ interrupt-parent = <&plic>;
+ interrupts = <180>, <179>, <178>, <177>;
+ interrupt-names = "hart-1", "hart-2", "hart-3", "hart-4";
+ #mbox-cells = <1>;
+ status = "disabled";
+ };
+
+ mailbox@50000000 {
+ compatible = "microchip,miv-ihc-rtl-v2";
+ reg = <0x0 0x50000000 0x0 0x1c000>;
+ interrupt-parent = <&plic>;
+ interrupts = <180>, <179>, <178>, <177>;
+ interrupt-names = "hart-1", "hart-2", "hart-3", "hart-4";
+ #mbox-cells = <1>;
+ microchip,ihc-chan-disabled-mask = /bits/ 16 <0>;
+ status = "disabled";
+ };
+
+ refclk_ccc: clock-cccref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+};
+
+&ccc_sw {
+ clocks = <&refclk_ccc>, <&refclk_ccc>, <&refclk_ccc>, <&refclk_ccc>,
+ <&refclk_ccc>, <&refclk_ccc>;
+ clock-names = "pll0_ref0", "pll0_ref1", "pll1_ref0", "pll1_ref1",
+ "dll0_ref", "dll1_ref";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-disco-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-disco-kit.dts
new file mode 100644
index 000000000000..c068b9bb5bfd
--- /dev/null
+++ b/arch/riscv/boot/dts/microchip/mpfs-disco-kit.dts
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2020-2025 Microchip Technology Inc */
+
+/dts-v1/;
+
+#include "mpfs.dtsi"
+#include "mpfs-disco-kit-fabric.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "Microchip PolarFire-SoC Discovery Kit";
+ compatible = "microchip,mpfs-disco-kit-reference-rtl-v2507",
+ "microchip,mpfs-disco-kit",
+ "microchip,mpfs";
+
+ aliases {
+ ethernet0 = &mac0;
+ serial4 = &mmuart4;
+ };
+
+ chosen {
+ stdout-path = "serial4:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-1 {
+ gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led1";
+ };
+
+ led-2 {
+ gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led2";
+ };
+
+ led-3 {
+ gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led3";
+ };
+
+ led-4 {
+ gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led4";
+ };
+
+ led-5 {
+ gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led5";
+ };
+
+ led-6 {
+ gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led6";
+ };
+
+ led-7 {
+ gpios = <&gpio2 23 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led7";
+ };
+
+ led-8 {
+ gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led8";
+ };
+ };
+
+ ddrc_cache_lo: memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hss_payload: region@bfc00000 {
+ reg = <0x0 0xbfc00000 0x0 0x400000>;
+ no-map;
+ };
+ };
+};
+
+&core_pwm0 {
+ status = "okay";
+};
+
+&gpio1 {
+ interrupts = <27>, <28>, <29>, <30>,
+ <31>, <32>, <33>, <47>,
+ <35>, <36>, <37>, <38>,
+ <39>, <40>, <41>, <42>,
+ <43>, <44>, <45>, <46>,
+ <47>, <48>, <49>, <50>;
+ status = "okay";
+};
+
+&gpio2 {
+ interrupts = <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&ihc {
+ status = "okay";
+};
+
+&mac0 {
+ phy-mode = "sgmii";
+ phy-handle = <&phy0>;
+ status = "okay";
+
+ phy0: ethernet-phy@b {
+ reg = <0xb>;
+ };
+};
+
+&mbox {
+ status = "okay";
+};
+
+&mmc {
+ bus-width = <4>;
+ disable-wp;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ no-1-8-v;
+ status = "okay";
+};
+
+&mmuart1 {
+ status = "okay";
+};
+
+&mmuart4 {
+ status = "okay";
+};
+
+&refclk {
+ clock-frequency = <125000000>;
+};
+
+&refclk_ccc {
+ clock-frequency = <50000000>;
+};
+
+&rtc {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&syscontroller {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-common.dtsi b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-common.dtsi
new file mode 100644
index 000000000000..e01a216e6c3a
--- /dev/null
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-common.dtsi
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2025 Microchip Technology Inc */
+
+/dts-v1/;
+
+#include "mpfs.dtsi"
+#include "mpfs-icicle-kit-fabric.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ ethernet0 = &mac1;
+ serial0 = &mmuart0;
+ serial1 = &mmuart1;
+ serial2 = &mmuart2;
+ serial3 = &mmuart3;
+ serial4 = &mmuart4;
+ };
+
+ chosen {
+ stdout-path = "serial1:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-1 {
+ gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led1";
+ };
+
+ led-2 {
+ gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led2";
+ };
+
+ led-3 {
+ gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led3";
+ };
+
+ led-4 {
+ gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led4";
+ };
+ };
+
+ ddrc_cache_lo: memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x40000000>;
+ };
+
+ ddrc_cache_hi: memory@1040000000 {
+ device_type = "memory";
+ reg = <0x10 0x40000000 0x0 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hss_payload: region@bfc00000 {
+ reg = <0x0 0xbfc00000 0x0 0x400000>;
+ no-map;
+ };
+ };
+};
+
+&core_pwm0 {
+ status = "okay";
+};
+
+&gpio2 {
+ interrupts = <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ power-monitor@10 {
+ compatible = "microchip,pac1934";
+ reg = <0x10>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDREG";
+ };
+
+ channel@2 {
+ reg = <0x2>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDA25";
+ };
+
+ channel@3 {
+ reg = <0x3>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDD25";
+ };
+
+ channel@4 {
+ reg = <0x4>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDA_REG";
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&ihc {
+ status = "okay";
+};
+
+&mac0 {
+ phy-mode = "sgmii";
+ phy-handle = <&phy0>;
+ status = "okay";
+};
+
+&mac1 {
+ phy-mode = "sgmii";
+ phy-handle = <&phy1>;
+ status = "okay";
+
+ phy1: ethernet-phy@9 {
+ reg = <9>;
+ };
+
+ phy0: ethernet-phy@8 {
+ reg = <8>;
+ };
+};
+
+&mbox {
+ status = "okay";
+};
+
+&mmc {
+ bus-width = <4>;
+ disable-wp;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
+
+&mmuart1 {
+ status = "okay";
+};
+
+&mmuart2 {
+ status = "okay";
+};
+
+&mmuart3 {
+ status = "okay";
+};
+
+&mmuart4 {
+ status = "okay";
+};
+
+&pcie {
+ status = "okay";
+};
+
+&qspi {
+ status = "okay";
+};
+
+&refclk {
+ clock-frequency = <125000000>;
+};
+
+&refclk_ccc {
+ clock-frequency = <50000000>;
+};
+
+&rtc {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&syscontroller {
+ status = "okay";
+};
+
+&syscontroller_qspi {
+ /*
+ * The flash *is* there, but Icicle kits that have engineering sample
+ * silicon (write?) access to this flash to non-functional. The system
+ * controller itself can actually access it, but the MSS cannot write
+ * an image there. Instantiating a coreQSPI in the fabric & connecting
+ * it to the flash instead should work though. Pre-production or later
+ * silicon does not have this issue.
+ */
+ status = "disabled";
+
+ sys_ctrl_flash: flash@0 { // MT25QL01GBBB8ESF-0SIT
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <20000000>;
+ spi-rx-bus-width = <1>;
+ reg = <0>;
+ };
+};
+
+&usb {
+ status = "okay";
+ dr_mode = "host";
+};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi
index a6dda55a2d1d..71f724325578 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi
@@ -2,9 +2,6 @@
/* Copyright (c) 2020-2021 Microchip Technology Inc */
/ {
- compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit",
- "microchip,mpfs";
-
core_pwm0: pwm@40000000 {
compatible = "microchip,corepwm-rtl-v4";
reg = <0x0 0x40000000 0x0 0xF0>;
@@ -26,6 +23,26 @@
status = "disabled";
};
+ ihc: mailbox {
+ compatible = "microchip,sbi-ipc";
+ interrupt-parent = <&plic>;
+ interrupts = <180>, <179>, <178>, <177>;
+ interrupt-names = "hart-1", "hart-2", "hart-3", "hart-4";
+ #mbox-cells = <1>;
+ status = "disabled";
+ };
+
+ mailbox@50000000 {
+ compatible = "microchip,miv-ihc-rtl-v2";
+ reg = <0x0 0x50000000 0x0 0x1c000>;
+ interrupt-parent = <&plic>;
+ interrupts = <180>, <179>, <178>, <177>;
+ interrupt-names = "hart-1", "hart-2", "hart-3", "hart-4";
+ #mbox-cells = <1>;
+ microchip,ihc-chan-disabled-mask = /bits/ 16 <0>;
+ status = "disabled";
+ };
+
pcie: pcie@3000000000 {
compatible = "microchip,pcie-host-1.0";
#address-cells = <0x3>;
@@ -57,7 +74,7 @@
};
};
- refclk_ccc: cccrefclk {
+ refclk_ccc: clock-cccref {
compatible = "fixed-clock";
#clock-cells = <0>;
};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-prod.dts b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-prod.dts
new file mode 100644
index 000000000000..8afedece89d1
--- /dev/null
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-prod.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2025 Microchip Technology Inc */
+
+/dts-v1/;
+
+#include "mpfs-icicle-kit-common.dtsi"
+
+/ {
+ model = "Microchip PolarFire-SoC Icicle Kit (Production Silicon)";
+ compatible = "microchip,mpfs-icicle-prod-reference-rtl-v2507",
+ "microchip,mpfs-icicle-kit-prod",
+ "microchip,mpfs-icicle-kit",
+ "microchip,mpfs-prod",
+ "microchip,mpfs";
+};
+
+&syscontroller {
+ microchip,bitstream-flash = <&sys_ctrl_flash>;
+};
+
+&syscontroller_qspi {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
index f80df225f72b..556aa9638282 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
@@ -3,249 +3,11 @@
/dts-v1/;
-#include "mpfs.dtsi"
-#include "mpfs-icicle-kit-fabric.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/leds/common.h>
+#include "mpfs-icicle-kit-common.dtsi"
/ {
model = "Microchip PolarFire-SoC Icicle Kit";
- compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit",
+ compatible = "microchip,mpfs-icicle-es-reference-rtl-v2507",
+ "microchip,mpfs-icicle-kit",
"microchip,mpfs";
-
- aliases {
- ethernet0 = &mac1;
- serial0 = &mmuart0;
- serial1 = &mmuart1;
- serial2 = &mmuart2;
- serial3 = &mmuart3;
- serial4 = &mmuart4;
- };
-
- chosen {
- stdout-path = "serial1:115200n8";
- };
-
- leds {
- compatible = "gpio-leds";
-
- led-1 {
- gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_RED>;
- label = "led1";
- };
-
- led-2 {
- gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_RED>;
- label = "led2";
- };
-
- led-3 {
- gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_AMBER>;
- label = "led3";
- };
-
- led-4 {
- gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_AMBER>;
- label = "led4";
- };
- };
-
- ddrc_cache_lo: memory@80000000 {
- device_type = "memory";
- reg = <0x0 0x80000000 0x0 0x40000000>;
- status = "okay";
- };
-
- ddrc_cache_hi: memory@1040000000 {
- device_type = "memory";
- reg = <0x10 0x40000000 0x0 0x40000000>;
- status = "okay";
- };
-
- reserved-memory {
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- hss_payload: region@BFC00000 {
- reg = <0x0 0xBFC00000 0x0 0x400000>;
- no-map;
- };
- };
-};
-
-&core_pwm0 {
- status = "okay";
-};
-
-&gpio2 {
- interrupts = <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>,
- <53>, <53>, <53>, <53>;
- status = "okay";
-};
-
-&i2c0 {
- status = "okay";
-};
-
-&i2c1 {
- status = "okay";
-
- power-monitor@10 {
- compatible = "microchip,pac1934";
- reg = <0x10>;
-
- #address-cells = <1>;
- #size-cells = <0>;
-
- channel@1 {
- reg = <0x1>;
- shunt-resistor-micro-ohms = <10000>;
- label = "VDDREG";
- };
-
- channel@2 {
- reg = <0x2>;
- shunt-resistor-micro-ohms = <10000>;
- label = "VDDA25";
- };
-
- channel@3 {
- reg = <0x3>;
- shunt-resistor-micro-ohms = <10000>;
- label = "VDD25";
- };
-
- channel@4 {
- reg = <0x4>;
- shunt-resistor-micro-ohms = <10000>;
- label = "VDDA_REG";
- };
- };
-};
-
-&i2c2 {
- status = "okay";
-};
-
-&mac0 {
- phy-mode = "sgmii";
- phy-handle = <&phy0>;
- status = "okay";
-};
-
-&mac1 {
- phy-mode = "sgmii";
- phy-handle = <&phy1>;
- status = "okay";
-
- phy1: ethernet-phy@9 {
- reg = <9>;
- };
-
- phy0: ethernet-phy@8 {
- reg = <8>;
- };
-};
-
-&mbox {
- status = "okay";
-};
-
-&mmc {
- bus-width = <4>;
- disable-wp;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- mmc-ddr-1_8v;
- mmc-hs200-1_8v;
- sd-uhs-sdr12;
- sd-uhs-sdr25;
- sd-uhs-sdr50;
- sd-uhs-sdr104;
- status = "okay";
-};
-
-&mmuart1 {
- status = "okay";
-};
-
-&mmuart2 {
- status = "okay";
-};
-
-&mmuart3 {
- status = "okay";
-};
-
-&mmuart4 {
- status = "okay";
-};
-
-&pcie {
- status = "okay";
-};
-
-&qspi {
- status = "okay";
-};
-
-&refclk {
- clock-frequency = <125000000>;
-};
-
-&refclk_ccc {
- clock-frequency = <50000000>;
-};
-
-&rtc {
- status = "okay";
-};
-
-&spi0 {
- status = "okay";
-};
-
-&spi1 {
- status = "okay";
-};
-
-&syscontroller {
- status = "okay";
-};
-
-&syscontroller_qspi {
- /*
- * The flash *is* there, but Icicle kits that have engineering sample
- * silicon (write?) access to this flash to non-functional. The system
- * controller itself can actually access it, but the MSS cannot write
- * an image there. Instantiating a coreQSPI in the fabric & connecting
- * it to the flash instead should work though. Pre-production or later
- * silicon does not have this issue.
- */
- status = "disabled";
-
- sys_ctrl_flash: flash@0 { // MT25QL01GBBB8ESF-0SIT
- compatible = "jedec,spi-nor";
- #address-cells = <1>;
- #size-cells = <1>;
- spi-max-frequency = <20000000>;
- spi-rx-bus-width = <1>;
- reg = <0>;
- };
-};
-
-&usb {
- status = "okay";
- dr_mode = "host";
};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
index 77ded5304272..94a4b71acad3 100644
--- a/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
+++ b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
@@ -272,6 +272,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache0>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu0_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -299,6 +300,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache0>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu1_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -326,6 +328,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache0>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu2_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -353,6 +356,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache0>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu3_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -380,6 +384,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache1>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu4_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -407,6 +412,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache1>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu5_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -434,6 +440,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache1>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu6_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -461,6 +468,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache1>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu7_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -488,6 +496,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache4>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu8_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -515,6 +524,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache4>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu9_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -542,6 +552,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache4>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu10_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -569,6 +580,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache4>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu11_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -596,6 +608,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache5>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu12_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -623,6 +636,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache5>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu13_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -650,6 +664,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache5>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu14_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -677,6 +692,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache5>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu15_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -704,6 +720,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache2>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu16_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -731,6 +748,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache2>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu17_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -758,6 +776,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache2>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu18_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -785,6 +804,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache2>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu19_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -812,6 +832,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache3>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu20_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -839,6 +860,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache3>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu21_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -866,6 +888,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache3>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu22_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -893,6 +916,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache3>;
mmu-type = "riscv,sv39";
+ numa-node-id = <0>;
cpu23_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -920,6 +944,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache6>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu24_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -947,6 +972,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache6>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu25_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -974,6 +1000,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache6>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu26_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1001,6 +1028,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache6>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu27_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1028,6 +1056,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache7>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu28_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1055,6 +1084,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache7>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu29_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1082,6 +1112,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache7>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu30_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1109,6 +1140,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache7>;
mmu-type = "riscv,sv39";
+ numa-node-id = <1>;
cpu31_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1136,6 +1168,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache8>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu32_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1163,6 +1196,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache8>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu33_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1190,6 +1224,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache8>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu34_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1217,6 +1252,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache8>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu35_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1244,6 +1280,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache9>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu36_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1271,6 +1308,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache9>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu37_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1298,6 +1336,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache9>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu38_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1325,6 +1364,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache9>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu39_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1352,6 +1392,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache12>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu40_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1379,6 +1420,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache12>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu41_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1406,6 +1448,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache12>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu42_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1433,6 +1476,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache12>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu43_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1460,6 +1504,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache13>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu44_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1487,6 +1532,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache13>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu45_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1514,6 +1560,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache13>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu46_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1541,6 +1588,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache13>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu47_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1568,6 +1616,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache10>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu48_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1595,6 +1644,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache10>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu49_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1622,6 +1672,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache10>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu50_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1649,6 +1700,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache10>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu51_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1676,6 +1728,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache11>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu52_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1703,6 +1756,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache11>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu53_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1730,6 +1784,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache11>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu54_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1757,6 +1812,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache11>;
mmu-type = "riscv,sv39";
+ numa-node-id = <2>;
cpu55_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1784,6 +1840,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache14>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu56_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1811,6 +1868,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache14>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu57_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1838,6 +1896,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache14>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu58_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1865,6 +1924,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache14>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu59_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1892,6 +1952,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache15>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu60_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1919,6 +1980,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache15>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu61_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1946,6 +2008,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache15>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu62_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
@@ -1973,6 +2036,7 @@
d-cache-sets = <512>;
next-level-cache = <&l2_cache15>;
mmu-type = "riscv,sv39";
+ numa-node-id = <3>;
cpu63_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
index b3e4d3c18fdc..c5e49709b308 100644
--- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi
+++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
@@ -19,6 +19,26 @@
#size-cells = <2>;
dma-noncoherent;
+ distance-map {
+ compatible = "numa-distance-map-v1";
+ distance-matrix = <0 0 10>,
+ <0 1 15>,
+ <0 2 25>,
+ <0 3 30>,
+ <1 0 15>,
+ <1 1 10>,
+ <1 2 30>,
+ <1 3 25>,
+ <2 0 25>,
+ <2 1 30>,
+ <2 2 10>,
+ <2 3 15>,
+ <3 0 30>,
+ <3 1 25>,
+ <3 2 15>,
+ <3 3 10>;
+ };
+
aliases {
serial0 = &uart0;
};
@@ -190,7 +210,7 @@
reg-names = "clr", "doorbell";
msi-controller;
#msi-cells = <0>;
- msi-ranges = <&intc 64 IRQ_TYPE_LEVEL_HIGH 32>;
+ msi-ranges = <&intc 64 IRQ_TYPE_EDGE_RISING 32>;
};
rpgate: clock-controller@7030010368 {
diff --git a/arch/riscv/boot/dts/sophgo/sg2044.dtsi b/arch/riscv/boot/dts/sophgo/sg2044.dtsi
index 6ec955744b0c..320c4d1d08e6 100644
--- a/arch/riscv/boot/dts/sophgo/sg2044.dtsi
+++ b/arch/riscv/boot/dts/sophgo/sg2044.dtsi
@@ -214,7 +214,7 @@
reg-names = "clr", "doorbell";
#msi-cells = <0>;
msi-controller;
- msi-ranges = <&intc 352 IRQ_TYPE_LEVEL_HIGH 512>;
+ msi-ranges = <&intc 352 IRQ_TYPE_EDGE_RISING 512>;
status = "disabled";
};
diff --git a/arch/riscv/boot/dts/spacemit/Makefile b/arch/riscv/boot/dts/spacemit/Makefile
index 92e13ce1c16d..152832644870 100644
--- a/arch/riscv/boot/dts/spacemit/Makefile
+++ b/arch/riscv/boot/dts/spacemit/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_SPACEMIT) += k1-bananapi-f3.dtb
dtb-$(CONFIG_ARCH_SPACEMIT) += k1-milkv-jupiter.dtb
+dtb-$(CONFIG_ARCH_SPACEMIT) += k1-orangepi-rv2.dtb
diff --git a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
index fe22c747c501..2aaaff77831e 100644
--- a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
@@ -11,6 +11,8 @@
compatible = "bananapi,bpi-f3", "spacemit,k1";
aliases {
+ ethernet0 = &eth0;
+ ethernet1 = &eth1;
serial0 = &uart0;
};
@@ -40,6 +42,56 @@
status = "okay";
};
+&eth0 {
+ phy-handle = <&rgmii0>;
+ phy-mode = "rgmii-id";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_cfg>;
+ rx-internal-delay-ps = <0>;
+ tx-internal-delay-ps = <0>;
+ status = "okay";
+
+ mdio-bus {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ reset-gpios = <&gpio K1_GPIO(110) GPIO_ACTIVE_LOW>;
+ reset-delay-us = <10000>;
+ reset-post-delay-us = <100000>;
+
+ rgmii0: phy@1 {
+ reg = <0x1>;
+ };
+ };
+};
+
+&eth1 {
+ phy-handle = <&rgmii1>;
+ phy-mode = "rgmii-id";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1_cfg>;
+ rx-internal-delay-ps = <0>;
+ tx-internal-delay-ps = <250>;
+ status = "okay";
+
+ mdio-bus {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ reset-gpios = <&gpio K1_GPIO(115) GPIO_ACTIVE_LOW>;
+ reset-delay-us = <10000>;
+ reset-post-delay-us = <100000>;
+
+ rgmii1: phy@1 {
+ reg = <0x1>;
+ };
+ };
+};
+
+&pdma {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
diff --git a/arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts b/arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts
index 448319214104..28afd39b28da 100644
--- a/arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts
@@ -12,6 +12,8 @@
compatible = "milkv,jupiter", "spacemit,k1";
aliases {
+ ethernet0 = &eth0;
+ ethernet1 = &eth1;
serial0 = &uart0;
};
@@ -20,6 +22,56 @@
};
};
+&eth0 {
+ phy-handle = <&rgmii0>;
+ phy-mode = "rgmii-id";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_cfg>;
+ rx-internal-delay-ps = <0>;
+ tx-internal-delay-ps = <0>;
+ status = "okay";
+
+ mdio-bus {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ reset-gpios = <&gpio K1_GPIO(110) GPIO_ACTIVE_LOW>;
+ reset-delay-us = <10000>;
+ reset-post-delay-us = <100000>;
+
+ rgmii0: phy@1 {
+ reg = <0x1>;
+ };
+ };
+};
+
+&eth1 {
+ phy-handle = <&rgmii1>;
+ phy-mode = "rgmii-id";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1_cfg>;
+ rx-internal-delay-ps = <0>;
+ tx-internal-delay-ps = <250>;
+ status = "okay";
+
+ mdio-bus {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ reset-gpios = <&gpio K1_GPIO(115) GPIO_ACTIVE_LOW>;
+ reset-delay-us = <10000>;
+ reset-post-delay-us = <100000>;
+
+ rgmii1: phy@1 {
+ reg = <0x1>;
+ };
+ };
+};
+
+&pdma {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
new file mode 100644
index 000000000000..337240ebb7b7
--- /dev/null
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Yangyu Chen <cyy@cyyself.name>
+ * Copyright (C) 2025 Hendrik Hamerlinck <hendrik.hamerlinck@hammernet.be>
+ */
+
+/dts-v1/;
+
+#include "k1.dtsi"
+#include "k1-pinctrl.dtsi"
+
+/ {
+ model = "OrangePi RV2";
+ compatible = "xunlong,orangepi-rv2", "spacemit,k1";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1 {
+ label = "sys-led";
+ gpios = <&gpio K1_GPIO(96) GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_2_cfg>;
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
index 381055737422..aff19c86d5ff 100644
--- a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
@@ -11,6 +11,54 @@
#define K1_GPIO(x) (x / 32) (x % 32)
&pinctrl {
+ gmac0_cfg: gmac0-cfg {
+ gmac0-pins {
+ pinmux = <K1_PADCONF(0, 1)>, /* gmac0_rxdv */
+ <K1_PADCONF(1, 1)>, /* gmac0_rx_d0 */
+ <K1_PADCONF(2, 1)>, /* gmac0_rx_d1 */
+ <K1_PADCONF(3, 1)>, /* gmac0_rx_clk */
+ <K1_PADCONF(4, 1)>, /* gmac0_rx_d2 */
+ <K1_PADCONF(5, 1)>, /* gmac0_rx_d3 */
+ <K1_PADCONF(6, 1)>, /* gmac0_tx_d0 */
+ <K1_PADCONF(7, 1)>, /* gmac0_tx_d1 */
+ <K1_PADCONF(8, 1)>, /* gmac0_tx */
+ <K1_PADCONF(9, 1)>, /* gmac0_tx_d2 */
+ <K1_PADCONF(10, 1)>, /* gmac0_tx_d3 */
+ <K1_PADCONF(11, 1)>, /* gmac0_tx_en */
+ <K1_PADCONF(12, 1)>, /* gmac0_mdc */
+ <K1_PADCONF(13, 1)>, /* gmac0_mdio */
+ <K1_PADCONF(14, 1)>, /* gmac0_int_n */
+ <K1_PADCONF(45, 1)>; /* gmac0_clk_ref */
+
+ bias-pull-up = <0>;
+ drive-strength = <21>;
+ };
+ };
+
+ gmac1_cfg: gmac1-cfg {
+ gmac1-pins {
+ pinmux = <K1_PADCONF(29, 1)>, /* gmac1_rxdv */
+ <K1_PADCONF(30, 1)>, /* gmac1_rx_d0 */
+ <K1_PADCONF(31, 1)>, /* gmac1_rx_d1 */
+ <K1_PADCONF(32, 1)>, /* gmac1_rx_clk */
+ <K1_PADCONF(33, 1)>, /* gmac1_rx_d2 */
+ <K1_PADCONF(34, 1)>, /* gmac1_rx_d3 */
+ <K1_PADCONF(35, 1)>, /* gmac1_tx_d0 */
+ <K1_PADCONF(36, 1)>, /* gmac1_tx_d1 */
+ <K1_PADCONF(37, 1)>, /* gmac1_tx */
+ <K1_PADCONF(38, 1)>, /* gmac1_tx_d2 */
+ <K1_PADCONF(39, 1)>, /* gmac1_tx_d3 */
+ <K1_PADCONF(40, 1)>, /* gmac1_tx_en */
+ <K1_PADCONF(41, 1)>, /* gmac1_mdc */
+ <K1_PADCONF(42, 1)>, /* gmac1_mdio */
+ <K1_PADCONF(43, 1)>, /* gmac1_int_n */
+ <K1_PADCONF(46, 1)>; /* gmac1_clk_ref */
+
+ bias-pull-up = <0>;
+ drive-strength = <21>;
+ };
+ };
+
uart0_2_cfg: uart0-2-cfg {
uart0-2-pins {
pinmux = <K1_PADCONF(68, 2)>,
diff --git a/arch/riscv/boot/dts/spacemit/k1.dtsi b/arch/riscv/boot/dts/spacemit/k1.dtsi
index abde8bb07c95..6cdcd80a7c83 100644
--- a/arch/riscv/boot/dts/spacemit/k1.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1.dtsi
@@ -660,6 +660,17 @@
dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
<0x1 0x00000000 0x1 0x80000000 0x3 0x00000000>;
+ pdma: dma-controller@d4000000 {
+ compatible = "spacemit,k1-pdma";
+ reg = <0x0 0xd4000000 0x0 0x4000>;
+ clocks = <&syscon_apmu CLK_DMA>;
+ resets = <&syscon_apmu RESET_DMA>;
+ interrupts = <72>;
+ dma-channels = <16>;
+ #dma-cells= <1>;
+ status = "disabled";
+ };
+
uart0: serial@d4017000 {
compatible = "spacemit,k1-uart",
"intel,xscale-uart";
@@ -667,6 +678,7 @@
clocks = <&syscon_apbc CLK_UART0>,
<&syscon_apbc CLK_UART0_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART0>;
interrupts = <42>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -680,6 +692,7 @@
clocks = <&syscon_apbc CLK_UART2>,
<&syscon_apbc CLK_UART2_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART2>;
interrupts = <44>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -693,6 +706,7 @@
clocks = <&syscon_apbc CLK_UART3>,
<&syscon_apbc CLK_UART3_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART3>;
interrupts = <45>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -706,6 +720,7 @@
clocks = <&syscon_apbc CLK_UART4>,
<&syscon_apbc CLK_UART4_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART4>;
interrupts = <46>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -719,6 +734,7 @@
clocks = <&syscon_apbc CLK_UART5>,
<&syscon_apbc CLK_UART5_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART5>;
interrupts = <47>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -732,6 +748,7 @@
clocks = <&syscon_apbc CLK_UART6>,
<&syscon_apbc CLK_UART6_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART6>;
interrupts = <48>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -745,6 +762,7 @@
clocks = <&syscon_apbc CLK_UART7>,
<&syscon_apbc CLK_UART7_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART7>;
interrupts = <49>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -758,6 +776,7 @@
clocks = <&syscon_apbc CLK_UART8>,
<&syscon_apbc CLK_UART8_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART8>;
interrupts = <50>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -771,22 +790,14 @@
clocks = <&syscon_apbc CLK_UART9>,
<&syscon_apbc CLK_UART9_BUS>;
clock-names = "core", "bus";
+ resets = <&syscon_apbc RESET_UART9>;
interrupts = <51>;
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
};
- sec_uart1: serial@f0612000 {
- compatible = "spacemit,k1-uart",
- "intel,xscale-uart";
- reg = <0x0 0xf0612000 0x0 0x100>;
- interrupts = <43>;
- clock-frequency = <14857000>;
- reg-shift = <2>;
- reg-io-width = <4>;
- status = "reserved"; /* for TEE usage */
- };
+ /* sec_uart1: 0xf0612000, not available from Linux */
};
multimedia-bus {
@@ -805,6 +816,28 @@
#size-cells = <2>;
dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
<0x0 0x80000000 0x1 0x00000000 0x0 0x80000000>;
+
+ eth0: ethernet@cac80000 {
+ compatible = "spacemit,k1-emac";
+ reg = <0x0 0xcac80000 0x0 0x420>;
+ clocks = <&syscon_apmu CLK_EMAC0_BUS>;
+ interrupts = <131>;
+ mac-address = [ 00 00 00 00 00 00 ];
+ resets = <&syscon_apmu RESET_EMAC0>;
+ spacemit,apmu = <&syscon_apmu 0x3e4>;
+ status = "disabled";
+ };
+
+ eth1: ethernet@cac81000 {
+ compatible = "spacemit,k1-emac";
+ reg = <0x0 0xcac81000 0x0 0x420>;
+ clocks = <&syscon_apmu CLK_EMAC1_BUS>;
+ interrupts = <133>;
+ mac-address = [ 00 00 00 00 00 00 ];
+ resets = <&syscon_apmu RESET_EMAC1>;
+ spacemit,apmu = <&syscon_apmu 0x3ec>;
+ status = "disabled";
+ };
};
pcie-bus {
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
index b3bb12f78e7d..62b659f89ba7 100644
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -10,6 +10,8 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-deepcomputing-fml13v01.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-milkv-mars.dtb
+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-milkv-marscm-emmc.dtb
+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-milkv-marscm-lite.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-pine64-star64.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index 2eaf01775ef5..5dc15e48b74b 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -285,7 +285,6 @@
mmc-ddr-1_8v;
mmc-hs200-1_8v;
cap-mmc-hw-reset;
- post-power-on-delay-ms = <200>;
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <&vcc_3v3>;
@@ -299,12 +298,9 @@
assigned-clock-rates = <50000000>;
bus-width = <4>;
bootph-pre-ram;
- no-sdio;
- no-mmc;
cd-gpios = <&sysgpio 41 GPIO_ACTIVE_LOW>;
disable-wp;
cap-sd-highspeed;
- post-power-on-delay-ms = <200>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
status = "okay";
diff --git a/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-emmc.dts b/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-emmc.dts
new file mode 100644
index 000000000000..e568537af2c4
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-emmc.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2025 E Shattow <e@freeshell.de>
+ */
+
+/dts-v1/;
+#include "jh7110-milkv-marscm.dtsi"
+
+/ {
+ model = "Milk-V Mars CM";
+ compatible = "milkv,marscm-emmc", "starfive,jh7110";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-lite.dts b/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-lite.dts
new file mode 100644
index 000000000000..6c40d0ec4011
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm-lite.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2025 E Shattow <e@freeshell.de>
+ */
+
+/dts-v1/;
+#include "jh7110-milkv-marscm.dtsi"
+
+/ {
+ model = "Milk-V Mars CM Lite";
+ compatible = "milkv,marscm-lite", "starfive,jh7110";
+};
+
+&mmc0 {
+ bus-width = <4>;
+ cd-gpios = <&sysgpio 41 GPIO_ACTIVE_LOW>;
+};
+
+&mmc0_pins {
+ pwren-pins {
+ pinmux = <GPIOMUX(22, GPOUT_HIGH,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ };
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm.dtsi b/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm.dtsi
new file mode 100644
index 000000000000..25b70af564ee
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-milkv-marscm.dtsi
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2025 E Shattow <e@freeshell.de>
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "jh7110-common.dtsi"
+
+/ {
+ aliases {
+ i2c1 = &i2c1;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ serial3 = &uart3;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&sysgpio 33 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&gmac0 {
+ assigned-clocks = <&aoncrg JH7110_AONCLK_GMAC0_TX>;
+ assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>;
+ starfive,tx-use-rgmii-clk;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "disabled";
+};
+
+&i2c6 {
+ status = "disabled";
+};
+
+&mmc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ status = "okay";
+
+ ap6256: wifi@1 {
+ compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&sysgpio>;
+ interrupts = <34 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wake";
+ pinctrl-0 = <&wifi_host_wake_irq>;
+ pinctrl-names = "default";
+ };
+};
+
+&pcie0 {
+ status = "okay";
+};
+
+&phy0 {
+ rx-internal-delay-ps = <1500>;
+ tx-internal-delay-ps = <1500>;
+ motorcomm,rx-clk-drv-microamp = <3970>;
+ motorcomm,rx-data-drv-microamp = <2910>;
+ motorcomm,tx-clk-10-inverted;
+ motorcomm,tx-clk-100-inverted;
+ motorcomm,tx-clk-1000-inverted;
+ motorcomm,tx-clk-adj-enabled;
+};
+
+&pwm {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&sysgpio {
+ uart1_pins: uart1-0 {
+ tx-pins {
+ pinmux = <GPIOMUX(16, GPOUT_SYS_UART1_TX,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ drive-strength = <12>;
+ input-disable;
+ input-schmitt-disable;
+ };
+
+ rx-pins {
+ pinmux = <GPIOMUX(17, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_UART1_RX)>;
+ bias-pull-up;
+ input-enable;
+ input-schmitt-enable;
+ };
+
+ cts-pins {
+ pinmux = <GPIOMUX(3, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_UART1_CTS)>;
+ bias-disable;
+ input-enable;
+ input-schmitt-enable;
+ };
+
+ rts-pins {
+ pinmux = <GPIOMUX(2, GPOUT_SYS_UART1_RTS,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ input-disable;
+ input-schmitt-disable;
+ };
+ };
+
+ usb0_pins: usb0-0 {
+ vbus-pins {
+ pinmux = <GPIOMUX(25, GPOUT_SYS_USB_DRIVE_VBUS,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ wifi_host_wake_irq: wifi-host-wake-irq-0 {
+ wake-pins {
+ pinmux = <GPIOMUX(34, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ input-enable;
+ };
+ };
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "host";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb0_pins>;
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 0ba74ef04679..6e56e9d20bb0 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -35,6 +35,7 @@
cpu0_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
+ bootph-pre-ram;
interrupt-controller;
#interrupt-cells = <1>;
};
@@ -68,6 +69,7 @@
cpu1_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
+ bootph-pre-ram;
interrupt-controller;
#interrupt-cells = <1>;
};
@@ -101,6 +103,7 @@
cpu2_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
+ bootph-pre-ram;
interrupt-controller;
#interrupt-cells = <1>;
};
@@ -134,6 +137,7 @@
cpu3_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
+ bootph-pre-ram;
interrupt-controller;
#interrupt-cells = <1>;
};
@@ -167,6 +171,7 @@
cpu4_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
+ bootph-pre-ram;
interrupt-controller;
#interrupt-cells = <1>;
};
@@ -273,12 +278,14 @@
gmac1_rgmii_rxin: gmac1-rgmii-rxin-clock {
compatible = "fixed-clock";
+ bootph-pre-ram;
clock-output-names = "gmac1_rgmii_rxin";
#clock-cells = <0>;
};
gmac1_rmii_refin: gmac1-rmii-refin-clock {
compatible = "fixed-clock";
+ bootph-pre-ram;
clock-output-names = "gmac1_rmii_refin";
#clock-cells = <0>;
};
@@ -321,6 +328,7 @@
osc: oscillator {
compatible = "fixed-clock";
+ bootph-pre-ram;
clock-output-names = "osc";
#clock-cells = <0>;
};
@@ -354,6 +362,7 @@
clint: timer@2000000 {
compatible = "starfive,jh7110-clint", "sifive,clint0";
reg = <0x0 0x2000000 0x0 0x10000>;
+ bootph-pre-ram;
interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
<&cpu1_intc 3>, <&cpu1_intc 7>,
<&cpu2_intc 3>, <&cpu2_intc 7>,
@@ -880,6 +889,7 @@
syscrg: clock-controller@13020000 {
compatible = "starfive,jh7110-syscrg";
reg = <0x0 0x13020000 0x0 0x10000>;
+ bootph-pre-ram;
clocks = <&osc>, <&gmac1_rmii_refin>,
<&gmac1_rgmii_rxin>,
<&i2stx_bclk_ext>, <&i2stx_lrck_ext>,
@@ -904,6 +914,7 @@
pllclk: clock-controller {
compatible = "starfive,jh7110-pll";
+ bootph-pre-ram;
clocks = <&osc>;
#clock-cells = <1>;
};
@@ -931,6 +942,19 @@
<&syscrg JH7110_SYSRST_WDT_CORE>;
};
+ memory-controller@15700000 {
+ compatible = "starfive,jh7110-dmc";
+ reg = <0x0 0x15700000 0x0 0x10000>,
+ <0x0 0x13000000 0x0 0x10000>;
+ bootph-pre-ram;
+ clocks = <&syscrg JH7110_PLLCLK_PLL1_OUT>;
+ clock-names = "pll";
+ resets = <&syscrg JH7110_SYSRST_DDR_AXI>,
+ <&syscrg JH7110_SYSRST_DDR_OSC>,
+ <&syscrg JH7110_SYSRST_DDR_APB>;
+ reset-names = "axi", "osc", "apb";
+ };
+
crypto: crypto@16000000 {
compatible = "starfive,jh7110-crypto";
reg = <0x0 0x16000000 0x0 0x4000>;
diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi
index 03f1d7319049..e680d1a7c821 100644
--- a/arch/riscv/boot/dts/thead/th1520.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520.dtsi
@@ -225,6 +225,13 @@
#clock-cells = <0>;
};
+ gpu_mem_clk: mem-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <0>;
+ clock-output-names = "gpu_mem_clk";
+ #clock-cells = <0>;
+ };
+
stmmac_axi_config: stmmac-axi-config {
snps,wr_osr_lmt = <15>;
snps,rd_osr_lmt = <15>;
@@ -502,6 +509,20 @@
#clock-cells = <1>;
};
+ gpu: gpu@ffef400000 {
+ compatible = "thead,th1520-gpu", "img,img-bxm-4-64",
+ "img,img-rogue";
+ reg = <0xff 0xef400000 0x0 0x100000>;
+ interrupt-parent = <&plic>;
+ interrupts = <102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vo CLK_GPU_CORE>,
+ <&gpu_mem_clk>,
+ <&clk_vo CLK_GPU_CFG_ACLK>;
+ clock-names = "core", "mem", "sys";
+ power-domains = <&aon TH1520_GPU_PD>;
+ resets = <&rst TH1520_RESET_ID_GPU>;
+ };
+
rst: reset-controller@ffef528000 {
compatible = "thead,th1520-reset";
reg = <0xff 0xef528000 0x0 0x4f>;
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 7b5eed17611a..b9ef2da15fb2 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -135,6 +135,7 @@ CONFIG_MACB=y
CONFIG_E1000E=y
CONFIG_R8169=y
CONFIG_STMMAC_ETH=m
+CONFIG_DWMAC_THEAD=m
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
CONFIG_MOTORCOMM_PHY=y
@@ -152,7 +153,6 @@ CONFIG_HW_RANDOM_JH7110=m
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_DESIGNWARE_CORE=y
-CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_MV64XXX=m
CONFIG_SPI=y
CONFIG_SPI_CADENCE_QUADSPI=m
@@ -160,11 +160,11 @@ CONFIG_SPI_PL022=m
CONFIG_SPI_SIFIVE=y
CONFIG_SPI_SUN6I=y
# CONFIG_PTP_1588_CLOCK is not set
+CONFIG_PINCTRL_TH1520=y
CONFIG_PINCTRL_SOPHGO_CV1800B=y
CONFIG_PINCTRL_SOPHGO_CV1812H=y
CONFIG_PINCTRL_SOPHGO_SG2000=y
CONFIG_PINCTRL_SOPHGO_SG2002=y
-CONFIG_PINCTRL_TH1520=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_SIFIVE=y
CONFIG_GPIO_SPACEMIT_K1=y
@@ -241,7 +241,7 @@ CONFIG_RTC_DRV_SUN6I=y
CONFIG_DMADEVICES=y
CONFIG_DMA_SUN6I=m
CONFIG_DW_AXI_DMAC=y
-CONFIG_DWMAC_THEAD=m
+CONFIG_MMP_PDMA=m
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_INPUT=y
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
index bc6c77ba837d..02a7a3335b1d 100644
--- a/arch/riscv/errata/Makefile
+++ b/arch/riscv/errata/Makefile
@@ -13,5 +13,6 @@ endif
endif
obj-$(CONFIG_ERRATA_ANDES) += andes/
+obj-$(CONFIG_ERRATA_MIPS) += mips/
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
obj-$(CONFIG_ERRATA_THEAD) += thead/
diff --git a/arch/riscv/errata/mips/Makefile b/arch/riscv/errata/mips/Makefile
new file mode 100644
index 000000000000..6278c389b801
--- /dev/null
+++ b/arch/riscv/errata/mips/Makefile
@@ -0,0 +1,5 @@
+ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
+CFLAGS_errata.o := -mcmodel=medany
+endif
+
+obj-y += errata.o
diff --git a/arch/riscv/errata/mips/errata.c b/arch/riscv/errata/mips/errata.c
new file mode 100644
index 000000000000..e984a8152208
--- /dev/null
+++ b/arch/riscv/errata/mips/errata.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 MIPS.
+ */
+
+#include <linux/memory.h>
+#include <linux/module.h>
+#include <asm/text-patching.h>
+#include <asm/alternative.h>
+#include <asm/errata_list.h>
+#include <asm/vendorid_list.h>
+#include <asm/vendor_extensions.h>
+#include <asm/vendor_extensions/mips.h>
+
+static inline bool errata_probe_pause(void)
+{
+ if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE))
+ return false;
+
+ if (!riscv_isa_vendor_extension_available(MIPS_VENDOR_ID, XMIPSEXECTL))
+ return false;
+
+ return true;
+}
+
+static u32 mips_errata_probe(void)
+{
+ u32 cpu_req_errata = 0;
+
+ if (errata_probe_pause())
+ cpu_req_errata |= BIT(ERRATA_MIPS_P8700_PAUSE_OPCODE);
+
+ return cpu_req_errata;
+}
+
+void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+ unsigned long archid, unsigned long impid,
+ unsigned int stage)
+{
+ struct alt_entry *alt;
+ u32 cpu_req_errata = mips_errata_probe();
+ u32 tmp;
+
+ BUILD_BUG_ON(ERRATA_MIPS_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
+
+ if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
+ return;
+
+ for (alt = begin; alt < end; alt++) {
+ if (alt->vendor_id != MIPS_VENDOR_ID)
+ continue;
+
+ if (alt->patch_id >= ERRATA_MIPS_NUMBER) {
+ WARN(1, "MIPS errata id:%d not in kernel errata list\n",
+ alt->patch_id);
+ continue;
+ }
+
+ tmp = (1U << alt->patch_id);
+ if (cpu_req_errata && tmp) {
+ mutex_lock(&text_mutex);
+ patch_text_nosync(ALT_OLD_PTR(alt), ALT_ALT_PTR(alt),
+ alt->alt_len);
+ mutex_unlock(&text_mutex);
+ }
+ }
+}
diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h
index 231d777d936c..9619bd5c8eba 100644
--- a/arch/riscv/include/asm/alternative-macros.h
+++ b/arch/riscv/include/asm/alternative-macros.h
@@ -4,7 +4,7 @@
#ifdef CONFIG_RISCV_ALTERNATIVE
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
.macro ALT_ENTRY oldptr newptr vendor_id patch_id new_len
.4byte \oldptr - .
@@ -53,7 +53,7 @@
#define __ALTERNATIVE_CFG(...) ALTERNATIVE_CFG __VA_ARGS__
#define __ALTERNATIVE_CFG_2(...) ALTERNATIVE_CFG_2 __VA_ARGS__
-#else /* !__ASSEMBLY__ */
+#else /* !__ASSEMBLER__ */
#include <asm/asm.h>
#include <linux/stringify.h>
@@ -98,7 +98,7 @@
__ALTERNATIVE_CFG(old_c, new_c_1, vendor_id_1, patch_id_1, enable_1) \
ALT_NEW_CONTENT(vendor_id_2, patch_id_2, enable_2, new_c_2)
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, patch_id, CONFIG_k) \
__ALTERNATIVE_CFG(old_c, new_c, vendor_id, patch_id, IS_ENABLED(CONFIG_k))
@@ -109,7 +109,7 @@
new_c_2, vendor_id_2, patch_id_2, IS_ENABLED(CONFIG_k_2))
#else /* CONFIG_RISCV_ALTERNATIVE */
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
.macro ALTERNATIVE_CFG old_c
\old_c
@@ -118,12 +118,12 @@
#define __ALTERNATIVE_CFG(old_c, ...) ALTERNATIVE_CFG old_c
#define __ALTERNATIVE_CFG_2(old_c, ...) ALTERNATIVE_CFG old_c
-#else /* !__ASSEMBLY__ */
+#else /* !__ASSEMBLER__ */
#define __ALTERNATIVE_CFG(old_c, ...) old_c "\n"
#define __ALTERNATIVE_CFG_2(old_c, ...) old_c "\n"
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#define _ALTERNATIVE_CFG(old_c, ...) __ALTERNATIVE_CFG(old_c)
#define _ALTERNATIVE_CFG_2(old_c, ...) __ALTERNATIVE_CFG_2(old_c)
diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
index 3c2b59b25017..8407d1d535b8 100644
--- a/arch/riscv/include/asm/alternative.h
+++ b/arch/riscv/include/asm/alternative.h
@@ -8,7 +8,7 @@
#include <asm/alternative-macros.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#ifdef CONFIG_RISCV_ALTERNATIVE
@@ -48,6 +48,9 @@ struct alt_entry {
void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage);
+void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+ unsigned long archid, unsigned long impid,
+ unsigned int stage);
void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage);
diff --git a/arch/riscv/include/asm/asm-extable.h b/arch/riscv/include/asm/asm-extable.h
index 0c8bfd54fc4e..37d425d7a762 100644
--- a/arch/riscv/include/asm/asm-extable.h
+++ b/arch/riscv/include/asm/asm-extable.h
@@ -10,7 +10,7 @@
#ifdef CONFIG_MMU
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
.pushsection __ex_table, "a"; \
@@ -25,7 +25,7 @@
__ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0)
.endm
-#else /* __ASSEMBLY__ */
+#else /* __ASSEMBLER__ */
#include <linux/bits.h>
#include <linux/stringify.h>
@@ -77,7 +77,7 @@
EX_DATA_REG(ADDR, addr) \
")")
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#else /* CONFIG_MMU */
#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err)
diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h
index 2a16e88e13de..8bd2a11382a3 100644
--- a/arch/riscv/include/asm/asm.h
+++ b/arch/riscv/include/asm/asm.h
@@ -6,7 +6,7 @@
#ifndef _ASM_RISCV_ASM_H
#define _ASM_RISCV_ASM_H
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define __ASM_STR(x) x
#else
#define __ASM_STR(x) #x
@@ -30,7 +30,7 @@
#define SRLI __REG_SEL(srliw, srli)
#if __SIZEOF_POINTER__ == 8
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define RISCV_PTR .dword
#define RISCV_SZPTR 8
#define RISCV_LGPTR 3
@@ -40,7 +40,7 @@
#define RISCV_LGPTR "3"
#endif
#elif __SIZEOF_POINTER__ == 4
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define RISCV_PTR .word
#define RISCV_SZPTR 4
#define RISCV_LGPTR 2
@@ -69,7 +69,7 @@
#error "Unexpected __SIZEOF_SHORT__"
#endif
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#include <asm/asm-offsets.h>
/* Common assembly source macros */
@@ -194,6 +194,6 @@
#define ASM_NOKPROBE(name)
#endif
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_ASM_H */
diff --git a/arch/riscv/include/asm/assembler.h b/arch/riscv/include/asm/assembler.h
index 44b1457d3e95..16931712beab 100644
--- a/arch/riscv/include/asm/assembler.h
+++ b/arch/riscv/include/asm/assembler.h
@@ -5,7 +5,7 @@
* Author: Jee Heng Sia <jeeheng.sia@starfivetech.com>
*/
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#error "Only include this from assembly code"
#endif
diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h
index b8c5726d86ac..700ba3f922cb 100644
--- a/arch/riscv/include/asm/barrier.h
+++ b/arch/riscv/include/asm/barrier.h
@@ -10,7 +10,7 @@
#ifndef _ASM_RISCV_BARRIER_H
#define _ASM_RISCV_BARRIER_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/cmpxchg.h>
#include <asm/fence.h>
@@ -82,6 +82,6 @@ do { \
#include <asm-generic/barrier.h>
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_BARRIER_H */
diff --git a/arch/riscv/include/asm/bitops.h b/arch/riscv/include/asm/bitops.h
index d59310f74c2b..77880677b06e 100644
--- a/arch/riscv/include/asm/bitops.h
+++ b/arch/riscv/include/asm/bitops.h
@@ -45,7 +45,7 @@
#error "Unexpected BITS_PER_LONG"
#endif
-static __always_inline unsigned long variable__ffs(unsigned long word)
+static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
{
asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
RISCV_ISA_EXT_ZBB, 1)
@@ -74,7 +74,7 @@ legacy:
(unsigned long)__builtin_ctzl(word) : \
variable__ffs(word))
-static __always_inline unsigned long variable__fls(unsigned long word)
+static __always_inline __attribute_const__ unsigned long variable__fls(unsigned long word)
{
asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
RISCV_ISA_EXT_ZBB, 1)
@@ -103,7 +103,7 @@ legacy:
(unsigned long)(BITS_PER_LONG - 1 - __builtin_clzl(word)) : \
variable__fls(word))
-static __always_inline int variable_ffs(int x)
+static __always_inline __attribute_const__ int variable_ffs(int x)
{
asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
RISCV_ISA_EXT_ZBB, 1)
diff --git a/arch/riscv/include/asm/cache.h b/arch/riscv/include/asm/cache.h
index 570e9d8acad1..eb42b739d132 100644
--- a/arch/riscv/include/asm/cache.h
+++ b/arch/riscv/include/asm/cache.h
@@ -24,7 +24,7 @@
#define ARCH_SLAB_MINALIGN 16
#endif
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
extern int dma_cache_alignment;
#ifdef CONFIG_RISCV_DMA_NONCOHERENT
@@ -35,6 +35,6 @@ static inline int dma_get_cache_alignment(void)
}
#endif
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_CACHE_H */
diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
index 6086b38d5427..0092513c3376 100644
--- a/arch/riscv/include/asm/cacheflush.h
+++ b/arch/riscv/include/asm/cacheflush.h
@@ -23,8 +23,8 @@ static inline void local_flush_icache_range(unsigned long start,
static inline void flush_dcache_folio(struct folio *folio)
{
- if (test_bit(PG_dcache_clean, &folio->flags))
- clear_bit(PG_dcache_clean, &folio->flags);
+ if (test_bit(PG_dcache_clean, &folio->flags.f))
+ clear_bit(PG_dcache_clean, &folio->flags.f);
}
#define flush_dcache_folio flush_dcache_folio
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
diff --git a/arch/riscv/include/asm/cfi.h b/arch/riscv/include/asm/cfi.h
index 4508aaa7a2fd..710aa8192edd 100644
--- a/arch/riscv/include/asm/cfi.h
+++ b/arch/riscv/include/asm/cfi.h
@@ -11,7 +11,7 @@
struct pt_regs;
-#ifdef CONFIG_CFI_CLANG
+#ifdef CONFIG_CFI
enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
#define __bpfcall
#else
@@ -19,6 +19,6 @@ static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
{
return BUG_TRAP_TYPE_NONE;
}
-#endif /* CONFIG_CFI_CLANG */
+#endif /* CONFIG_CFI */
#endif /* _ASM_RISCV_CFI_H */
diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
index 0b749e710216..122e1485d39a 100644
--- a/arch/riscv/include/asm/cmpxchg.h
+++ b/arch/riscv/include/asm/cmpxchg.h
@@ -14,6 +14,7 @@
#include <asm/insn-def.h>
#include <asm/cpufeature-macros.h>
#include <asm/processor.h>
+#include <asm/errata_list.h>
#define __arch_xchg_masked(sc_sfx, swap_sfx, prepend, sc_append, \
swap_append, r, p, n) \
@@ -133,6 +134,7 @@
({ \
if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) && \
IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) && \
+ IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZACAS) && \
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA) && \
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)) { \
r = o; \
@@ -180,6 +182,7 @@
r, p, co, o, n) \
({ \
if (IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) && \
+ IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZACAS) && \
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)) { \
r = o; \
\
@@ -315,7 +318,7 @@
arch_cmpxchg_release((ptr), (o), (n)); \
})
-#if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS)
+#if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
#define system_has_cmpxchg128() riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
@@ -351,7 +354,7 @@ union __u128_halves {
#define arch_cmpxchg128_local(ptr, o, n) \
__arch_cmpxchg128((ptr), (o), (n), "")
-#endif /* CONFIG_64BIT && CONFIG_RISCV_ISA_ZACAS */
+#endif /* CONFIG_64BIT && CONFIG_RISCV_ISA_ZACAS && CONFIG_TOOLCHAIN_HAS_ZACAS */
#ifdef CONFIG_RISCV_ISA_ZAWRS
/*
@@ -438,7 +441,7 @@ static __always_inline void __cmpwait(volatile void *ptr,
return;
no_zawrs:
- asm volatile(RISCV_PAUSE : : : "memory");
+ ALT_RISCV_PAUSE();
}
#define __cmpwait_relaxed(ptr, val) \
diff --git a/arch/riscv/include/asm/cpu_ops_sbi.h b/arch/riscv/include/asm/cpu_ops_sbi.h
index d6e4665b3195..776fa55fbaa4 100644
--- a/arch/riscv/include/asm/cpu_ops_sbi.h
+++ b/arch/riscv/include/asm/cpu_ops_sbi.h
@@ -5,7 +5,7 @@
#ifndef __ASM_CPU_OPS_SBI_H
#define __ASM_CPU_OPS_SBI_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/threads.h>
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 6fed42e37705..4a37a98398ad 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -513,7 +513,7 @@
#define IE_TIE (_AC(0x1, UL) << RV_IRQ_TIMER)
#define IE_EIE (_AC(0x1, UL) << RV_IRQ_EXT)
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#define csr_swap(csr, val) \
({ \
@@ -575,6 +575,6 @@
: "memory"); \
})
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_CSR_H */
diff --git a/arch/riscv/include/asm/current.h b/arch/riscv/include/asm/current.h
index 21774d868c65..ba5aa72aff63 100644
--- a/arch/riscv/include/asm/current.h
+++ b/arch/riscv/include/asm/current.h
@@ -13,7 +13,7 @@
#include <linux/bug.h>
#include <linux/compiler.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct task_struct;
@@ -35,6 +35,6 @@ static __always_inline struct task_struct *get_current(void)
register unsigned long current_stack_pointer __asm__("sp");
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_CURRENT_H */
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index 6e426ed7919a..6694b5ccdcf8 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -5,31 +5,14 @@
#ifndef ASM_ERRATA_LIST_H
#define ASM_ERRATA_LIST_H
-#include <asm/alternative.h>
#include <asm/csr.h>
#include <asm/insn-def.h>
#include <asm/hwcap.h>
#include <asm/vendorid_list.h>
+#include <asm/errata_list_vendors.h>
+#include <asm/vendor_extensions/mips.h>
-#ifdef CONFIG_ERRATA_ANDES
-#define ERRATA_ANDES_NO_IOCP 0
-#define ERRATA_ANDES_NUMBER 1
-#endif
-
-#ifdef CONFIG_ERRATA_SIFIVE
-#define ERRATA_SIFIVE_CIP_453 0
-#define ERRATA_SIFIVE_CIP_1200 1
-#define ERRATA_SIFIVE_NUMBER 2
-#endif
-
-#ifdef CONFIG_ERRATA_THEAD
-#define ERRATA_THEAD_MAE 0
-#define ERRATA_THEAD_PMU 1
-#define ERRATA_THEAD_GHOSTWRITE 2
-#define ERRATA_THEAD_NUMBER 3
-#endif
-
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define ALT_INSN_FAULT(x) \
ALTERNATIVE(__stringify(RISCV_PTR do_trap_insn_fault), \
@@ -42,7 +25,7 @@ ALTERNATIVE(__stringify(RISCV_PTR do_page_fault), \
__stringify(RISCV_PTR sifive_cip_453_page_fault_trp), \
SIFIVE_VENDOR_ID, ERRATA_SIFIVE_CIP_453, \
CONFIG_ERRATA_SIFIVE_CIP_453)
-#else /* !__ASSEMBLY__ */
+#else /* !__ASSEMBLER__ */
#define ALT_SFENCE_VMA_ASID(asid) \
asm(ALTERNATIVE("sfence.vma x0, %0", "sfence.vma", SIFIVE_VENDOR_ID, \
@@ -59,6 +42,17 @@ asm(ALTERNATIVE("sfence.vma %0, %1", "sfence.vma", SIFIVE_VENDOR_ID, \
ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \
: : "r" (addr), "r" (asid) : "memory")
+#define ALT_RISCV_PAUSE() \
+asm(ALTERNATIVE( \
+ RISCV_PAUSE, /* Original RISC‑V pause insn */ \
+ MIPS_PAUSE, /* Replacement for MIPS P8700 */ \
+ MIPS_VENDOR_ID, /* Vendor ID to match */ \
+ ERRATA_MIPS_P8700_PAUSE_OPCODE, /* patch_id */ \
+ CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE) \
+ : /* no outputs */ \
+ : /* no inputs */ \
+ : "memory")
+
/*
* _val is marked as "will be overwritten", so need to set it to 0
* in the default case.
@@ -123,6 +117,6 @@ asm volatile(ALTERNATIVE( \
#define THEAD_C9XX_RV_IRQ_PMU 17
#define THEAD_C9XX_CSR_SCOUNTEROF 0x5c5
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif
diff --git a/arch/riscv/include/asm/errata_list_vendors.h b/arch/riscv/include/asm/errata_list_vendors.h
new file mode 100644
index 000000000000..ec7eba373437
--- /dev/null
+++ b/arch/riscv/include/asm/errata_list_vendors.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef ASM_ERRATA_LIST_VENDORS_H
+#define ASM_ERRATA_LIST_VENDORS_H
+
+#ifdef CONFIG_ERRATA_ANDES
+#define ERRATA_ANDES_NO_IOCP 0
+#define ERRATA_ANDES_NUMBER 1
+#endif
+
+#ifdef CONFIG_ERRATA_SIFIVE
+#define ERRATA_SIFIVE_CIP_453 0
+#define ERRATA_SIFIVE_CIP_1200 1
+#define ERRATA_SIFIVE_NUMBER 2
+#endif
+
+#ifdef CONFIG_ERRATA_THEAD
+#define ERRATA_THEAD_MAE 0
+#define ERRATA_THEAD_PMU 1
+#define ERRATA_THEAD_GHOSTWRITE 2
+#define ERRATA_THEAD_NUMBER 3
+#endif
+
+#ifdef CONFIG_ERRATA_MIPS
+#define ERRATA_MIPS_P8700_PAUSE_OPCODE 0
+#define ERRATA_MIPS_NUMBER 1
+#endif
+
+#endif /* ASM_ERRATA_LIST_VENDORS_H */
diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
index 22ebea3c2b26..e5026cd8f022 100644
--- a/arch/riscv/include/asm/ftrace.h
+++ b/arch/riscv/include/asm/ftrace.h
@@ -13,7 +13,7 @@
#endif
#define ARCH_SUPPORTS_FTRACE_OPS 1
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
extern void *return_address(unsigned int level);
@@ -112,7 +112,7 @@ do { \
#define MCOUNT_JALR_SIZE 4
#define MCOUNT_NOP4_SIZE 4
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct dyn_ftrace;
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
#define ftrace_init_nop ftrace_init_nop
@@ -235,7 +235,7 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsi
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* CONFIG_DYNAMIC_FTRACE */
diff --git a/arch/riscv/include/asm/gpr-num.h b/arch/riscv/include/asm/gpr-num.h
index efeb5edf8a3a..b499cf832734 100644
--- a/arch/riscv/include/asm/gpr-num.h
+++ b/arch/riscv/include/asm/gpr-num.h
@@ -2,7 +2,7 @@
#ifndef __ASM_GPR_NUM_H
#define __ASM_GPR_NUM_H
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
.irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
.equ .L__gpr_num_x\num, \num
@@ -41,7 +41,7 @@
.equ .L__gpr_num_t5, 30
.equ .L__gpr_num_t6, 31
-#else /* __ASSEMBLY__ */
+#else /* __ASSEMBLER__ */
#define __DEFINE_ASM_GPR_NUMS \
" .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31\n" \
@@ -80,6 +80,6 @@
" .equ .L__gpr_num_t5, 30\n" \
" .equ .L__gpr_num_t6, 31\n"
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_GPR_NUM_H */
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 446126497768..0872d43fc0c0 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -7,7 +7,7 @@
static inline void arch_clear_hugetlb_flags(struct folio *folio)
{
- clear_bit(PG_dcache_clean, &folio->flags);
+ clear_bit(PG_dcache_clean, &folio->flags.f);
}
#define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 7fe0a379474a..948d2b34e94e 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,7 @@
#include <uapi/asm/hwprobe.h>
-#define RISCV_HWPROBE_MAX_KEY 13
+#define RISCV_HWPROBE_MAX_KEY 14
static inline bool riscv_hwprobe_key_is_valid(__s64 key)
{
@@ -22,6 +22,7 @@ static inline bool hwprobe_key_is_bitmask(__s64 key)
case RISCV_HWPROBE_KEY_IMA_EXT_0:
case RISCV_HWPROBE_KEY_CPUPERF_0:
case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
+ case RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0:
case RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0:
return true;
}
diff --git a/arch/riscv/include/asm/image.h b/arch/riscv/include/asm/image.h
index 8927a6ea1127..899254966e85 100644
--- a/arch/riscv/include/asm/image.h
+++ b/arch/riscv/include/asm/image.h
@@ -29,7 +29,7 @@
#define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \
RISCV_HEADER_VERSION_MINOR)
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#define riscv_image_flag_field(flags, field)\
(((flags) >> field##_SHIFT) & field##_MASK)
/**
@@ -63,5 +63,5 @@ struct riscv_image_header {
u32 magic2;
u32 res3;
};
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_IMAGE_H */
diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h
index d5adbaec1d01..c9cfcea52cbb 100644
--- a/arch/riscv/include/asm/insn-def.h
+++ b/arch/riscv/include/asm/insn-def.h
@@ -25,7 +25,7 @@
#define INSN_S_SIMM5_SHIFT 7
#define INSN_S_OPCODE_SHIFT 0
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#ifdef CONFIG_AS_HAS_INSN
@@ -77,7 +77,7 @@
#define __INSN_I(...) insn_i __VA_ARGS__
#define __INSN_S(...) insn_s __VA_ARGS__
-#else /* ! __ASSEMBLY__ */
+#else /* ! __ASSEMBLER__ */
#ifdef CONFIG_AS_HAS_INSN
@@ -153,7 +153,7 @@
#endif
-#endif /* ! __ASSEMBLY__ */
+#endif /* ! __ASSEMBLER__ */
#define INSN_R(opcode, func3, func7, rd, rs1, rs2) \
__INSN_R(RV_##opcode, RV_##func3, RV_##func7, \
@@ -263,7 +263,7 @@
#define RISCV_INSN_NOP4 _AC(0x00000013, U)
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#define nop() __asm__ __volatile__ ("nop")
#define __nops(n) ".rept " #n "\nnop\n.endr\n"
#define nops(n) __asm__ __volatile__ (__nops(n))
diff --git a/arch/riscv/include/asm/insn.h b/arch/riscv/include/asm/insn.h
index 09fde95a5e8f..c3005573e8c9 100644
--- a/arch/riscv/include/asm/insn.h
+++ b/arch/riscv/include/asm/insn.h
@@ -64,6 +64,7 @@
#define RVG_RS2_OPOFF 20
#define RVG_RD_OPOFF 7
#define RVG_RS1_MASK GENMASK(4, 0)
+#define RVG_RS2_MASK GENMASK(4, 0)
#define RVG_RD_MASK GENMASK(4, 0)
/* The bit field of immediate value in RVC J instruction */
@@ -286,45 +287,216 @@ static __always_inline bool riscv_insn_is_c_jalr(u32 code)
(code & RVC_INSN_J_RS1_MASK) != 0;
}
-#define RV_IMM_SIGN(x) (-(((x) >> 31) & 1))
-#define RVC_IMM_SIGN(x) (-(((x) >> 12) & 1))
-#define RV_X(X, s, mask) (((X) >> (s)) & (mask))
-#define RVC_X(X, s, mask) RV_X(X, s, mask)
+#define INSN_MATCH_LB 0x3
+#define INSN_MASK_LB 0x707f
+#define INSN_MATCH_LH 0x1003
+#define INSN_MASK_LH 0x707f
+#define INSN_MATCH_LW 0x2003
+#define INSN_MASK_LW 0x707f
+#define INSN_MATCH_LD 0x3003
+#define INSN_MASK_LD 0x707f
+#define INSN_MATCH_LBU 0x4003
+#define INSN_MASK_LBU 0x707f
+#define INSN_MATCH_LHU 0x5003
+#define INSN_MASK_LHU 0x707f
+#define INSN_MATCH_LWU 0x6003
+#define INSN_MASK_LWU 0x707f
+#define INSN_MATCH_SB 0x23
+#define INSN_MASK_SB 0x707f
+#define INSN_MATCH_SH 0x1023
+#define INSN_MASK_SH 0x707f
+#define INSN_MATCH_SW 0x2023
+#define INSN_MASK_SW 0x707f
+#define INSN_MATCH_SD 0x3023
+#define INSN_MASK_SD 0x707f
+
+#define INSN_MATCH_C_LD 0x6000
+#define INSN_MASK_C_LD 0xe003
+#define INSN_MATCH_C_SD 0xe000
+#define INSN_MASK_C_SD 0xe003
+#define INSN_MATCH_C_LW 0x4000
+#define INSN_MASK_C_LW 0xe003
+#define INSN_MATCH_C_SW 0xc000
+#define INSN_MASK_C_SW 0xe003
+#define INSN_MATCH_C_LDSP 0x6002
+#define INSN_MASK_C_LDSP 0xe003
+#define INSN_MATCH_C_SDSP 0xe002
+#define INSN_MASK_C_SDSP 0xe003
+#define INSN_MATCH_C_LWSP 0x4002
+#define INSN_MASK_C_LWSP 0xe003
+#define INSN_MATCH_C_SWSP 0xc002
+#define INSN_MASK_C_SWSP 0xe003
+
+#define INSN_OPCODE_MASK 0x007c
+#define INSN_OPCODE_SHIFT 2
+#define INSN_OPCODE_SYSTEM 28
+
+#define INSN_MASK_WFI 0xffffffff
+#define INSN_MATCH_WFI 0x10500073
+
+#define INSN_MASK_WRS 0xffffffff
+#define INSN_MATCH_WRS 0x00d00073
+
+#define INSN_MATCH_CSRRW 0x1073
+#define INSN_MASK_CSRRW 0x707f
+#define INSN_MATCH_CSRRS 0x2073
+#define INSN_MASK_CSRRS 0x707f
+#define INSN_MATCH_CSRRC 0x3073
+#define INSN_MASK_CSRRC 0x707f
+#define INSN_MATCH_CSRRWI 0x5073
+#define INSN_MASK_CSRRWI 0x707f
+#define INSN_MATCH_CSRRSI 0x6073
+#define INSN_MASK_CSRRSI 0x707f
+#define INSN_MATCH_CSRRCI 0x7073
+#define INSN_MASK_CSRRCI 0x707f
+
+#define INSN_MATCH_FLW 0x2007
+#define INSN_MASK_FLW 0x707f
+#define INSN_MATCH_FLD 0x3007
+#define INSN_MASK_FLD 0x707f
+#define INSN_MATCH_FLQ 0x4007
+#define INSN_MASK_FLQ 0x707f
+#define INSN_MATCH_FSW 0x2027
+#define INSN_MASK_FSW 0x707f
+#define INSN_MATCH_FSD 0x3027
+#define INSN_MASK_FSD 0x707f
+#define INSN_MATCH_FSQ 0x4027
+#define INSN_MASK_FSQ 0x707f
+
+#define INSN_MATCH_C_FLD 0x2000
+#define INSN_MASK_C_FLD 0xe003
+#define INSN_MATCH_C_FLW 0x6000
+#define INSN_MASK_C_FLW 0xe003
+#define INSN_MATCH_C_FSD 0xa000
+#define INSN_MASK_C_FSD 0xe003
+#define INSN_MATCH_C_FSW 0xe000
+#define INSN_MASK_C_FSW 0xe003
+#define INSN_MATCH_C_FLDSP 0x2002
+#define INSN_MASK_C_FLDSP 0xe003
+#define INSN_MATCH_C_FSDSP 0xa002
+#define INSN_MASK_C_FSDSP 0xe003
+#define INSN_MATCH_C_FLWSP 0x6002
+#define INSN_MASK_C_FLWSP 0xe003
+#define INSN_MATCH_C_FSWSP 0xe002
+#define INSN_MASK_C_FSWSP 0xe003
+
+#define INSN_MATCH_C_LHU 0x8400
+#define INSN_MASK_C_LHU 0xfc43
+#define INSN_MATCH_C_LH 0x8440
+#define INSN_MASK_C_LH 0xfc43
+#define INSN_MATCH_C_SH 0x8c00
+#define INSN_MASK_C_SH 0xfc43
+
+#define INSN_16BIT_MASK 0x3
+#define INSN_IS_16BIT(insn) (((insn) & INSN_16BIT_MASK) != INSN_16BIT_MASK)
+#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4)
+
+#define SHIFT_RIGHT(x, y) \
+ ((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
+
+#define REG_MASK \
+ ((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
+
+#define REG_OFFSET(insn, pos) \
+ (SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
+
+#define REG_PTR(insn, pos, regs) \
+ ((ulong *)((ulong)(regs) + REG_OFFSET(insn, pos)))
+
+#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
+#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
+#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
+#define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
+#define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
+#define GET_SP(regs) (*REG_PTR(2, 0, regs))
+#define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
+#define IMM_I(insn) ((s32)(insn) >> 20)
+#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
+ (s32)(((insn) >> 7) & 0x1f))
+
+#define SH_RD 7
+#define SH_RS1 15
+#define SH_RS2 20
+#define SH_RS2C 2
+#define MASK_RX 0x1f
+
+#if defined(CONFIG_64BIT)
+#define LOG_REGBYTES 3
+#else
+#define LOG_REGBYTES 2
+#endif
+
+#define MASK_FUNCT3 0x7000
+
+#define GET_FUNCT3(insn) (((insn) >> 12) & 7)
+
+#define RV_IMM_SIGN(x) (-(((x) >> 31) & 1))
+#define RVC_IMM_SIGN(x) (-(((x) >> 12) & 1))
+#define RV_X_MASK(X, s, mask) (((X) >> (s)) & (mask))
+#define RV_X(X, s, n) RV_X_MASK(X, s, ((1 << (n)) - 1))
+#define RVC_LW_IMM(x) ((RV_X(x, 6, 1) << 2) | \
+ (RV_X(x, 10, 3) << 3) | \
+ (RV_X(x, 5, 1) << 6))
+#define RVC_LD_IMM(x) ((RV_X(x, 10, 3) << 3) | \
+ (RV_X(x, 5, 2) << 6))
+#define RVC_LWSP_IMM(x) ((RV_X(x, 4, 3) << 2) | \
+ (RV_X(x, 12, 1) << 5) | \
+ (RV_X(x, 2, 2) << 6))
+#define RVC_LDSP_IMM(x) ((RV_X(x, 5, 2) << 3) | \
+ (RV_X(x, 12, 1) << 5) | \
+ (RV_X(x, 2, 3) << 6))
+#define RVC_SWSP_IMM(x) ((RV_X(x, 9, 4) << 2) | \
+ (RV_X(x, 7, 2) << 6))
+#define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | \
+ (RV_X(x, 7, 3) << 6))
+#define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3))
+#define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3))
+#define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5)
+#define RVC_X(X, s, mask) RV_X_MASK(X, s, mask)
+
+#define RV_EXTRACT_FUNCT3(x) \
+ ({typeof(x) x_ = (x); \
+ (RV_X_MASK(x_, RV_INSN_FUNCT3_OPOFF, \
+ RV_INSN_FUNCT3_MASK >> RV_INSN_FUNCT3_OPOFF)); })
#define RV_EXTRACT_RS1_REG(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RVG_RS1_OPOFF, RVG_RS1_MASK)); })
+ (RV_X_MASK(x_, RVG_RS1_OPOFF, RVG_RS1_MASK)); })
+
+#define RV_EXTRACT_RS2_REG(x) \
+ ({typeof(x) x_ = (x); \
+ (RV_X_MASK(x_, RVG_RS2_OPOFF, RVG_RS2_MASK)); })
#define RV_EXTRACT_RD_REG(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RVG_RD_OPOFF, RVG_RD_MASK)); })
+ (RV_X_MASK(x_, RVG_RD_OPOFF, RVG_RD_MASK)); })
#define RV_EXTRACT_UTYPE_IMM(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RV_U_IMM_31_12_OPOFF, RV_U_IMM_31_12_MASK)); })
+ (RV_X_MASK(x_, RV_U_IMM_31_12_OPOFF, RV_U_IMM_31_12_MASK)); })
#define RV_EXTRACT_JTYPE_IMM(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RV_J_IMM_10_1_OPOFF, RV_J_IMM_10_1_MASK) << RV_J_IMM_10_1_OFF) | \
- (RV_X(x_, RV_J_IMM_11_OPOFF, RV_J_IMM_11_MASK) << RV_J_IMM_11_OFF) | \
- (RV_X(x_, RV_J_IMM_19_12_OPOFF, RV_J_IMM_19_12_MASK) << RV_J_IMM_19_12_OFF) | \
+ (RV_X_MASK(x_, RV_J_IMM_10_1_OPOFF, RV_J_IMM_10_1_MASK) << RV_J_IMM_10_1_OFF) | \
+ (RV_X_MASK(x_, RV_J_IMM_11_OPOFF, RV_J_IMM_11_MASK) << RV_J_IMM_11_OFF) | \
+ (RV_X_MASK(x_, RV_J_IMM_19_12_OPOFF, RV_J_IMM_19_12_MASK) << RV_J_IMM_19_12_OFF) | \
(RV_IMM_SIGN(x_) << RV_J_IMM_SIGN_OFF); })
#define RV_EXTRACT_ITYPE_IMM(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RV_I_IMM_11_0_OPOFF, RV_I_IMM_11_0_MASK)) | \
+ (RV_X_MASK(x_, RV_I_IMM_11_0_OPOFF, RV_I_IMM_11_0_MASK)) | \
(RV_IMM_SIGN(x_) << RV_I_IMM_SIGN_OFF); })
#define RV_EXTRACT_BTYPE_IMM(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RV_B_IMM_4_1_OPOFF, RV_B_IMM_4_1_MASK) << RV_B_IMM_4_1_OFF) | \
- (RV_X(x_, RV_B_IMM_10_5_OPOFF, RV_B_IMM_10_5_MASK) << RV_B_IMM_10_5_OFF) | \
- (RV_X(x_, RV_B_IMM_11_OPOFF, RV_B_IMM_11_MASK) << RV_B_IMM_11_OFF) | \
+ (RV_X_MASK(x_, RV_B_IMM_4_1_OPOFF, RV_B_IMM_4_1_MASK) << RV_B_IMM_4_1_OFF) | \
+ (RV_X_MASK(x_, RV_B_IMM_10_5_OPOFF, RV_B_IMM_10_5_MASK) << RV_B_IMM_10_5_OFF) | \
+ (RV_X_MASK(x_, RV_B_IMM_11_OPOFF, RV_B_IMM_11_MASK) << RV_B_IMM_11_OFF) | \
(RV_IMM_SIGN(x_) << RV_B_IMM_SIGN_OFF); })
#define RVC_EXTRACT_C2_RS1_REG(x) \
({typeof(x) x_ = (x); \
- (RV_X(x_, RVC_C2_RS1_OPOFF, RVC_C2_RS1_MASK)); })
+ (RV_X_MASK(x_, RVC_C2_RS1_OPOFF, RVC_C2_RS1_MASK)); })
#define RVC_EXTRACT_JTYPE_IMM(x) \
({typeof(x) x_ = (x); \
@@ -346,13 +518,13 @@ static __always_inline bool riscv_insn_is_c_jalr(u32 code)
(RVC_IMM_SIGN(x_) << RVC_B_IMM_SIGN_OFF); })
#define RVG_EXTRACT_SYSTEM_CSR(x) \
- ({typeof(x) x_ = (x); RV_X(x_, RVG_SYSTEM_CSR_OFF, RVG_SYSTEM_CSR_MASK); })
+ ({typeof(x) x_ = (x); RV_X_MASK(x_, RVG_SYSTEM_CSR_OFF, RVG_SYSTEM_CSR_MASK); })
#define RVFDQ_EXTRACT_FL_FS_WIDTH(x) \
- ({typeof(x) x_ = (x); RV_X(x_, RVFDQ_FL_FS_WIDTH_OFF, \
+ ({typeof(x) x_ = (x); RV_X_MASK(x_, RVFDQ_FL_FS_WIDTH_OFF, \
RVFDQ_FL_FS_WIDTH_MASK); })
-#define RVV_EXRACT_VL_VS_WIDTH(x) RVFDQ_EXTRACT_FL_FS_WIDTH(x)
+#define RVV_EXTRACT_VL_VS_WIDTH(x) RVFDQ_EXTRACT_FL_FS_WIDTH(x)
/*
* Get the immediate from a J-type instruction.
@@ -375,10 +547,10 @@ static inline void riscv_insn_insert_jtype_imm(u32 *insn, s32 imm)
{
/* drop the old IMMs, all jal IMM bits sit at 31:12 */
*insn &= ~GENMASK(31, 12);
- *insn |= (RV_X(imm, RV_J_IMM_10_1_OFF, RV_J_IMM_10_1_MASK) << RV_J_IMM_10_1_OPOFF) |
- (RV_X(imm, RV_J_IMM_11_OFF, RV_J_IMM_11_MASK) << RV_J_IMM_11_OPOFF) |
- (RV_X(imm, RV_J_IMM_19_12_OFF, RV_J_IMM_19_12_MASK) << RV_J_IMM_19_12_OPOFF) |
- (RV_X(imm, RV_J_IMM_SIGN_OFF, 1) << RV_J_IMM_SIGN_OPOFF);
+ *insn |= (RV_X_MASK(imm, RV_J_IMM_10_1_OFF, RV_J_IMM_10_1_MASK) << RV_J_IMM_10_1_OPOFF) |
+ (RV_X_MASK(imm, RV_J_IMM_11_OFF, RV_J_IMM_11_MASK) << RV_J_IMM_11_OPOFF) |
+ (RV_X_MASK(imm, RV_J_IMM_19_12_OFF, RV_J_IMM_19_12_MASK) << RV_J_IMM_19_12_OPOFF) |
+ (RV_X_MASK(imm, RV_J_IMM_SIGN_OFF, 1) << RV_J_IMM_SIGN_OPOFF);
}
/*
diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
index a0e51840b9db..09bb5f57a9d3 100644
--- a/arch/riscv/include/asm/io.h
+++ b/arch/riscv/include/asm/io.h
@@ -28,6 +28,10 @@
#ifdef CONFIG_MMU
#define IO_SPACE_LIMIT (PCI_IO_SIZE - 1)
#define PCI_IOBASE ((void __iomem *)PCI_IO_START)
+
+#define ioremap_wc(addr, size) \
+ ioremap_prot((addr), (size), __pgprot(_PAGE_KERNEL_NC))
+
#endif /* CONFIG_MMU */
/*
diff --git a/arch/riscv/include/asm/jump_label.h b/arch/riscv/include/asm/jump_label.h
index 87a71cc6d146..3ab5f2e3212b 100644
--- a/arch/riscv/include/asm/jump_label.h
+++ b/arch/riscv/include/asm/jump_label.h
@@ -7,7 +7,7 @@
#ifndef __ASM_JUMP_LABEL_H
#define __ASM_JUMP_LABEL_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/types.h>
#include <asm/asm.h>
@@ -66,5 +66,5 @@ label:
return true;
}
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_JUMP_LABEL_H */
diff --git a/arch/riscv/include/asm/kasan.h b/arch/riscv/include/asm/kasan.h
index e6a0071bdb56..60af6691f903 100644
--- a/arch/riscv/include/asm/kasan.h
+++ b/arch/riscv/include/asm/kasan.h
@@ -4,7 +4,7 @@
#ifndef __ASM_KASAN_H
#define __ASM_KASAN_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
/*
* The following comment was copied from arm64:
diff --git a/arch/riscv/include/asm/kgdb.h b/arch/riscv/include/asm/kgdb.h
index cc11c4544cff..7559d728c5ff 100644
--- a/arch/riscv/include/asm/kgdb.h
+++ b/arch/riscv/include/asm/kgdb.h
@@ -17,12 +17,12 @@
#define BREAK_INSTR_SIZE 4
#endif
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
void arch_kgdb_breakpoint(void);
extern unsigned long kgdb_compiled_break;
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#define DBG_REG_ZERO "zero"
#define DBG_REG_RA "ra"
diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h
index 1cc90465d75b..cf8e6eac77d5 100644
--- a/arch/riscv/include/asm/mmu.h
+++ b/arch/riscv/include/asm/mmu.h
@@ -7,7 +7,7 @@
#ifndef _ASM_RISCV_MMU_H
#define _ASM_RISCV_MMU_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
typedef struct {
#ifndef CONFIG_MMU
@@ -40,6 +40,6 @@ typedef struct {
void __meminit create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, phys_addr_t sz,
pgprot_t prot);
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_MMU_H */
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index 572a141ddecd..ffe213ad65a4 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -41,7 +41,7 @@
#define PAGE_OFFSET ((unsigned long)phys_ram_base)
#endif /* CONFIG_MMU */
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#ifdef CONFIG_RISCV_ISA_ZICBOZ
void clear_page(void *page);
@@ -199,7 +199,7 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
return __va(pfn << PAGE_SHIFT);
}
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#define virt_addr_valid(vaddr) ({ \
unsigned long _addr = (unsigned long)vaddr; \
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 91697fbf1f90..29e994a9afb6 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -111,7 +111,7 @@
#endif
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/page.h>
#include <asm/tlbflush.h>
@@ -203,6 +203,7 @@ extern struct pt_alloc_ops pt_ops __meminitdata;
#define PAGE_TABLE __pgprot(_PAGE_TABLE)
+#define _PAGE_KERNEL_NC ((_PAGE_KERNEL & ~_PAGE_MTMASK) | _PAGE_NOCACHE)
#define _PAGE_IOREMAP ((_PAGE_KERNEL & ~_PAGE_MTMASK) | _PAGE_IO)
#define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP)
@@ -942,6 +943,23 @@ static inline int pudp_test_and_clear_young(struct vm_area_struct *vma,
return ptep_test_and_clear_young(vma, address, (pte_t *)pudp);
}
+#define __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR
+static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm,
+ unsigned long address, pud_t *pudp)
+{
+#ifdef CONFIG_SMP
+ pud_t pud = __pud(xchg(&pudp->pud, 0));
+#else
+ pud_t pud = *pudp;
+
+ pud_clear(pudp);
+#endif
+
+ page_table_check_pud_clear(mm, pud);
+
+ return pud;
+}
+
static inline int pud_young(pud_t pud)
{
return pte_young(pud_pte(pud));
@@ -1118,6 +1136,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
WARN_ON_ONCE(pgd_present(*pgdp) && !pgd_same(*pgdp, pgd)); \
set_pgd(pgdp, pgd); \
})
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* _ASM_RISCV_PGTABLE_H */
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 24d3af4d3807..da5426122d28 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -54,7 +54,7 @@
#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3)
#endif
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct task_struct;
struct pt_regs;
@@ -215,6 +215,6 @@ long get_tagged_addr_ctrl(struct task_struct *task);
#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl(current)
#endif
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_PROCESSOR_H */
diff --git a/arch/riscv/include/asm/ptrace.h b/arch/riscv/include/asm/ptrace.h
index a7dc0e330757..addc8188152f 100644
--- a/arch/riscv/include/asm/ptrace.h
+++ b/arch/riscv/include/asm/ptrace.h
@@ -10,7 +10,7 @@
#include <asm/csr.h>
#include <linux/compiler.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct pt_regs {
unsigned long epc;
@@ -180,6 +180,6 @@ static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
return !(regs->status & SR_PIE);
}
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_PTRACE_H */
diff --git a/arch/riscv/include/asm/scs.h b/arch/riscv/include/asm/scs.h
index 0e45db78b24b..ab7714aa93bd 100644
--- a/arch/riscv/include/asm/scs.h
+++ b/arch/riscv/include/asm/scs.h
@@ -2,7 +2,7 @@
#ifndef _ASM_SCS_H
#define _ASM_SCS_H
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#include <asm/asm-offsets.h>
#ifdef CONFIG_SHADOW_CALL_STACK
@@ -49,6 +49,6 @@ _skip_scs:
.endm
#endif /* CONFIG_SHADOW_CALL_STACK */
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_SCS_H */
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
index ea263d3683ef..87389e93325a 100644
--- a/arch/riscv/include/asm/set_memory.h
+++ b/arch/riscv/include/asm/set_memory.h
@@ -6,7 +6,7 @@
#ifndef _ASM_RISCV_SET_MEMORY_H
#define _ASM_RISCV_SET_MEMORY_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
/*
* Functions to change memory attributes.
*/
@@ -45,7 +45,7 @@ int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
bool kernel_page_present(struct page *page);
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_XIP_KERNEL)
#ifdef CONFIG_64BIT
diff --git a/arch/riscv/include/asm/swab.h b/arch/riscv/include/asm/swab.h
new file mode 100644
index 000000000000..c1da22aa1326
--- /dev/null
+++ b/arch/riscv/include/asm/swab.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_RISCV_SWAB_H
+#define _ASM_RISCV_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <asm/cpufeature-macros.h>
+#include <asm/hwcap.h>
+#include <asm-generic/swab.h>
+
+#if defined(CONFIG_TOOLCHAIN_HAS_ZBB) && defined(CONFIG_RISCV_ISA_ZBB) && !defined(NO_ALTERNATIVE)
+
+// Duplicated from include/uapi/linux/swab.h
+#define ___constant_swab16(x) ((__u16)( \
+ (((__u16)(x) & (__u16)0x00ffU) << 8) | \
+ (((__u16)(x) & (__u16)0xff00U) >> 8)))
+
+#define ___constant_swab32(x) ((__u32)( \
+ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
+ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
+ (((__u32)(x) & (__u32)0xff000000UL) >> 24)))
+
+#define ___constant_swab64(x) ((__u64)( \
+ (((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
+ (((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
+ (((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+ (((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
+ (((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
+ (((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+ (((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+ (((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56)))
+
+#define ARCH_SWAB(size, value) \
+({ \
+ unsigned long x = value; \
+ \
+ if (riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) { \
+ asm volatile (".option push\n" \
+ ".option arch,+zbb\n" \
+ "rev8 %0, %1\n" \
+ ".option pop\n" \
+ : "=r" (x) : "r" (x)); \
+ x = x >> (BITS_PER_LONG - size); \
+ } else { \
+ x = ___constant_swab##size(value); \
+ } \
+ x; \
+})
+
+static __always_inline __u16 __arch_swab16(__u16 value)
+{
+ return ARCH_SWAB(16, value);
+}
+
+static __always_inline __u32 __arch_swab32(__u32 value)
+{
+ return ARCH_SWAB(32, value);
+}
+
+#ifdef CONFIG_64BIT
+static __always_inline __u64 __arch_swab64(__u64 value)
+{
+ return ARCH_SWAB(64, value);
+}
+#else
+static __always_inline __u64 __arch_swab64(__u64 value)
+{
+ __u32 h = value >> 32;
+ __u32 l = value & ((1ULL << 32) - 1);
+
+ return ((__u64)(__arch_swab32(l)) << 32) | ((__u64)(__arch_swab32(h)));
+}
+#endif
+
+#define __arch_swab64 __arch_swab64
+#define __arch_swab32 __arch_swab32
+#define __arch_swab16 __arch_swab16
+
+#undef ___constant_swab16
+#undef ___constant_swab32
+#undef ___constant_swab64
+
+#undef ARCH_SWAB
+
+#endif /* defined(CONFIG_TOOLCHAIN_HAS_ZBB) && defined(CONFIG_RISCV_ISA_ZBB) && !defined(NO_ALTERNATIVE) */
+#endif /* _ASM_RISCV_SWAB_H */
diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h
index f5916a70879a..836d80dd2921 100644
--- a/arch/riscv/include/asm/thread_info.h
+++ b/arch/riscv/include/asm/thread_info.h
@@ -37,7 +37,7 @@
#define IRQ_STACK_SIZE THREAD_SIZE
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/processor.h>
#include <asm/csr.h>
@@ -98,7 +98,7 @@ struct thread_info {
void arch_release_task_struct(struct task_struct *tsk);
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
/*
* thread information flags
@@ -107,23 +107,18 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
* - pending work-to-be-done flags are in lowest half-word
* - other flags in upper half-word(s)
*/
-#define TIF_NEED_RESCHED 0 /* rescheduling necessary */
-#define TIF_NEED_RESCHED_LAZY 1 /* Lazy rescheduling needed */
-#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
-#define TIF_SIGPENDING 3 /* signal pending */
-#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
-#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
-#define TIF_NOTIFY_SIGNAL 9 /* signal notifications exist */
-#define TIF_UPROBE 10 /* uprobe breakpoint or singlestep */
-#define TIF_32BIT 11 /* compat-mode 32bit process */
-#define TIF_RISCV_V_DEFER_RESTORE 12 /* restore Vector before returing to user */
-
-#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
-#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
-#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
-#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
-#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
-#define _TIF_UPROBE (1 << TIF_UPROBE)
-#define _TIF_RISCV_V_DEFER_RESTORE (1 << TIF_RISCV_V_DEFER_RESTORE)
+
+/*
+ * Tell the generic TIF infrastructure which bits riscv supports
+ */
+#define HAVE_TIF_NEED_RESCHED_LAZY
+#define HAVE_TIF_RESTORE_SIGMASK
+
+#include <asm-generic/thread_info_tif.h>
+
+#define TIF_32BIT 16 /* compat-mode 32bit process */
+#define TIF_RISCV_V_DEFER_RESTORE 17 /* restore Vector before returing to user */
+
+#define _TIF_RISCV_V_DEFER_RESTORE BIT(TIF_RISCV_V_DEFER_RESTORE)
#endif /* _ASM_RISCV_THREAD_INFO_H */
diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h
index c130d8100232..f80357fe24d1 100644
--- a/arch/riscv/include/asm/vdso.h
+++ b/arch/riscv/include/asm/vdso.h
@@ -16,7 +16,7 @@
#define __VDSO_PAGES 4
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <generated/vdso-offsets.h>
#define VDSO_SYMBOL(base, name) \
@@ -34,7 +34,7 @@ extern char compat_vdso_start[], compat_vdso_end[];
extern char vdso_start[], vdso_end[];
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* CONFIG_MMU */
diff --git a/arch/riscv/include/asm/vdso/getrandom.h b/arch/riscv/include/asm/vdso/getrandom.h
index c6d66895c1f5..ab4aef955099 100644
--- a/arch/riscv/include/asm/vdso/getrandom.h
+++ b/arch/riscv/include/asm/vdso/getrandom.h
@@ -5,7 +5,7 @@
#ifndef __ASM_VDSO_GETRANDOM_H
#define __ASM_VDSO_GETRANDOM_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/unistd.h>
@@ -25,6 +25,6 @@ static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, uns
return ret;
}
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* __ASM_VDSO_GETRANDOM_H */
diff --git a/arch/riscv/include/asm/vdso/gettimeofday.h b/arch/riscv/include/asm/vdso/gettimeofday.h
index 29164f84f93c..9ec08fa04d35 100644
--- a/arch/riscv/include/asm/vdso/gettimeofday.h
+++ b/arch/riscv/include/asm/vdso/gettimeofday.h
@@ -2,7 +2,7 @@
#ifndef __ASM_VDSO_GETTIMEOFDAY_H
#define __ASM_VDSO_GETTIMEOFDAY_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/barrier.h>
#include <asm/unistd.h>
@@ -79,6 +79,6 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
return csr_read(CSR_TIME);
}
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/riscv/include/asm/vdso/processor.h b/arch/riscv/include/asm/vdso/processor.h
index 8f383f05a290..c42f95dc8811 100644
--- a/arch/riscv/include/asm/vdso/processor.h
+++ b/arch/riscv/include/asm/vdso/processor.h
@@ -2,9 +2,10 @@
#ifndef __ASM_VDSO_PROCESSOR_H
#define __ASM_VDSO_PROCESSOR_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/barrier.h>
+#include <asm/errata_list.h>
#include <asm/insn-def.h>
static inline void cpu_relax(void)
@@ -19,10 +20,10 @@ static inline void cpu_relax(void)
* Reduce instruction retirement.
* This assumes the PC changes.
*/
- __asm__ __volatile__ (RISCV_PAUSE);
+ ALT_RISCV_PAUSE();
barrier();
}
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_VDSO_PROCESSOR_H */
diff --git a/arch/riscv/include/asm/vdso/vsyscall.h b/arch/riscv/include/asm/vdso/vsyscall.h
index 1140b54b4bc8..558eb9dfda52 100644
--- a/arch/riscv/include/asm/vdso/vsyscall.h
+++ b/arch/riscv/include/asm/vdso/vsyscall.h
@@ -2,13 +2,13 @@
#ifndef __ASM_VDSO_VSYSCALL_H
#define __ASM_VDSO_VSYSCALL_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <vdso/datapage.h>
/* The asm-generic header needs to be included after the definitions above */
#include <asm-generic/vdso/vsyscall.h>
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* __ASM_VDSO_VSYSCALL_H */
diff --git a/arch/riscv/include/asm/vendor_extensions/mips.h b/arch/riscv/include/asm/vendor_extensions/mips.h
new file mode 100644
index 000000000000..ea8ca747d691
--- /dev/null
+++ b/arch/riscv/include/asm/vendor_extensions/mips.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 MIPS.
+ */
+
+#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_MIPS_H
+#define _ASM_RISCV_VENDOR_EXTENSIONS_MIPS_H
+
+#include <linux/types.h>
+
+#define RISCV_ISA_VENDOR_EXT_XMIPSEXECTL 0
+
+#ifndef __ASSEMBLER__
+struct riscv_isa_vendor_ext_data_list;
+extern struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_mips;
+#endif
+
+/* Extension specific instructions */
+
+/*
+ * All of the xmipsexectl extension instructions are
+ * ‘hint’ encodings of the SLLI instruction,
+ * with rd = 0, rs1 = 0 and imm = 1 for IHB, imm = 3 for EHB,
+ * and imm = 5 for PAUSE.
+ * MIPS.PAUSE is an alternative opcode which is implemented to have the
+ * same behavior as PAUSE on some MIPS RISCV cores.
+ * MIPS.EHB clears all execution hazards before allowing
+ * any subsequent instructions to execute.
+ * MIPS.IHB clears all instruction hazards before
+ * allowing any subsequent instructions to fetch.
+ */
+
+#define MIPS_PAUSE ".4byte 0x00501013\n\t"
+#define MIPS_EHB ".4byte 0x00301013\n\t"
+#define MIPS_IHB ".4byte 0x00101013\n\t"
+
+#endif // _ASM_RISCV_VENDOR_EXTENSIONS_MIPS_H
diff --git a/arch/riscv/include/asm/vendor_extensions/mips_hwprobe.h b/arch/riscv/include/asm/vendor_extensions/mips_hwprobe.h
new file mode 100644
index 000000000000..e63f664b6b17
--- /dev/null
+++ b/arch/riscv/include/asm/vendor_extensions/mips_hwprobe.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 MIPS.
+ */
+
+#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_MIPS_HWPROBE_H_
+#define _ASM_RISCV_VENDOR_EXTENSIONS_MIPS_HWPROBE_H_
+
+#include <linux/cpumask.h>
+#include <uapi/asm/hwprobe.h>
+
+#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_MIPS
+void hwprobe_isa_vendor_ext_mips_0(struct riscv_hwprobe *pair, const struct cpumask *cpus);
+#else
+static inline void hwprobe_isa_vendor_ext_mips_0(struct riscv_hwprobe *pair,
+ const struct cpumask *cpus)
+{
+ pair->value = 0;
+}
+#endif
+
+#endif // _ASM_RISCV_VENDOR_EXTENSIONS_MIPS_HWPROBE_H_
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index a5150cdf34d8..3b09874d7a6d 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -9,5 +9,6 @@
#define MICROCHIP_VENDOR_ID 0x029
#define SIFIVE_VENDOR_ID 0x489
#define THEAD_VENDOR_ID 0x5b7
+#define MIPS_VENDOR_ID 0x722
#endif
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index aaf6ad970499..5d30a4fae37a 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -106,6 +106,7 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0 11
#define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
#define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0 13
+#define RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0 14
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
/* Flags */
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index ef27d4289da1..251099d860aa 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -9,7 +9,7 @@
#ifndef __LINUX_KVM_RISCV_H
#define __LINUX_KVM_RISCV_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/types.h>
#include <asm/bitsperlong.h>
diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h
index a38268b19c3d..beff8df80ac9 100644
--- a/arch/riscv/include/uapi/asm/ptrace.h
+++ b/arch/riscv/include/uapi/asm/ptrace.h
@@ -6,7 +6,7 @@
#ifndef _UAPI_ASM_RISCV_PTRACE_H
#define _UAPI_ASM_RISCV_PTRACE_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/types.h>
@@ -127,6 +127,6 @@ struct __riscv_v_regset_state {
*/
#define RISCV_MAX_VLENB (8192)
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _UAPI_ASM_RISCV_PTRACE_H */
diff --git a/arch/riscv/include/uapi/asm/sigcontext.h b/arch/riscv/include/uapi/asm/sigcontext.h
index cd4f175dc837..748dffc9ae19 100644
--- a/arch/riscv/include/uapi/asm/sigcontext.h
+++ b/arch/riscv/include/uapi/asm/sigcontext.h
@@ -15,7 +15,7 @@
/* The size of END signal context header. */
#define END_HDR_SIZE 0x0
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct __sc_riscv_v_state {
struct __riscv_v_ext_state v_state;
@@ -35,6 +35,6 @@ struct sigcontext {
};
};
-#endif /*!__ASSEMBLY__*/
+#endif /*!__ASSEMBLER__*/
#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */
diff --git a/arch/riscv/include/uapi/asm/vendor/mips.h b/arch/riscv/include/uapi/asm/vendor/mips.h
new file mode 100644
index 000000000000..e65ab268b265
--- /dev/null
+++ b/arch/riscv/include/uapi/asm/vendor/mips.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#define RISCV_HWPROBE_VENDOR_EXT_XMIPSEXECTL BIT(0)
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index c7b542573407..f60fce69b725 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -113,7 +113,7 @@ obj-$(CONFIG_VMCORE_INFO) += vmcore_info.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
-obj-$(CONFIG_CFI_CLANG) += cfi.o
+obj-$(CONFIG_CFI) += cfi.o
obj-$(CONFIG_EFI) += efi.o
obj-$(CONFIG_COMPAT) += compat_syscall_table.o
diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c
index 3f6d5a6789e8..71698ee11621 100644
--- a/arch/riscv/kernel/acpi.c
+++ b/arch/riscv/kernel/acpi.c
@@ -14,6 +14,7 @@
*/
#include <linux/acpi.h>
+#include <linux/efi-bgrt.h>
#include <linux/efi.h>
#include <linux/io.h>
#include <linux/memblock.h>
@@ -160,6 +161,8 @@ done:
early_init_dt_scan_chosen_stdout();
} else {
acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
+ if (IS_ENABLED(CONFIG_ACPI_BGRT))
+ acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
}
}
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index 7eb3cb1215c6..7642704c7f18 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -47,6 +47,11 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
cpu_mfr_info->patch_func = andes_errata_patch_func;
break;
#endif
+#ifdef CONFIG_ERRATA_MIPS
+ case MIPS_VENDOR_ID:
+ cpu_mfr_info->patch_func = mips_errata_patch_func;
+ break;
+#endif
#ifdef CONFIG_ERRATA_SIFIVE
case SIFIVE_VENDOR_ID:
cpu_mfr_info->patch_func = sifive_errata_patch_func;
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c
index 6e8c0d6feae9..7d42d3b8a32a 100644
--- a/arch/riscv/kernel/asm-offsets.c
+++ b/arch/riscv/kernel/asm-offsets.c
@@ -3,6 +3,7 @@
* Copyright (C) 2012 Regents of the University of California
* Copyright (C) 2017 SiFive
*/
+#define COMPILE_OFFSETS
#include <linux/kbuild.h>
#include <linux/mm.h>
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 743d53415572..67b59699357d 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -474,10 +474,10 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS),
__RISCV_ISA_EXT_DATA(zalrsc, RISCV_ISA_EXT_ZALRSC),
__RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS),
- __RISCV_ISA_EXT_DATA(zfa, RISCV_ISA_EXT_ZFA),
+ __RISCV_ISA_EXT_DATA_VALIDATE(zfa, RISCV_ISA_EXT_ZFA, riscv_ext_f_depends),
__RISCV_ISA_EXT_DATA_VALIDATE(zfbfmin, RISCV_ISA_EXT_ZFBFMIN, riscv_ext_f_depends),
- __RISCV_ISA_EXT_DATA(zfh, RISCV_ISA_EXT_ZFH),
- __RISCV_ISA_EXT_DATA(zfhmin, RISCV_ISA_EXT_ZFHMIN),
+ __RISCV_ISA_EXT_DATA_VALIDATE(zfh, RISCV_ISA_EXT_ZFH, riscv_ext_f_depends),
+ __RISCV_ISA_EXT_DATA_VALIDATE(zfhmin, RISCV_ISA_EXT_ZFHMIN, riscv_ext_f_depends),
__RISCV_ISA_EXT_DATA(zca, RISCV_ISA_EXT_ZCA),
__RISCV_ISA_EXT_DATA_VALIDATE(zcb, RISCV_ISA_EXT_ZCB, riscv_ext_zca_depends),
__RISCV_ISA_EXT_DATA_VALIDATE(zcd, RISCV_ISA_EXT_ZCD, riscv_ext_zcd_validate),
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index d0ded2438533..d3d92a4becc7 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/linkage.h>
+#include <asm/alternative-macros.h>
#include <asm/asm.h>
#include <asm/csr.h>
#include <asm/scs.h>
diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/machine_kexec_file.c
index b9eb41b0a975..dd9d92a96517 100644
--- a/arch/riscv/kernel/machine_kexec_file.c
+++ b/arch/riscv/kernel/machine_kexec_file.c
@@ -15,6 +15,7 @@
#include <linux/memblock.h>
#include <linux/vmalloc.h>
#include <asm/setup.h>
+#include <asm/insn.h>
const struct kexec_file_ops * const kexec_file_loaders[] = {
&elf_kexec_ops,
@@ -109,7 +110,6 @@ static char *setup_kdump_cmdline(struct kimage *image, char *cmdline,
}
#endif
-#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1))
#define RISCV_IMM_BITS 12
#define RISCV_IMM_REACH (1LL << RISCV_IMM_BITS)
#define RISCV_CONST_HIGH_PART(x) \
diff --git a/arch/riscv/kernel/pi/Makefile b/arch/riscv/kernel/pi/Makefile
index 7dd15be69c90..bc098edac898 100644
--- a/arch/riscv/kernel/pi/Makefile
+++ b/arch/riscv/kernel/pi/Makefile
@@ -39,4 +39,4 @@ $(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE
$(call if_changed_rule,cc_o_c)
obj-y := cmdline_early.pi.o fdt_early.pi.o string.pi.o ctype.pi.o lib-fdt.pi.o lib-fdt_ro.pi.o archrandom_early.pi.o
-extra-y := $(patsubst %.pi.o,%.o,$(obj-y))
+targets := $(patsubst %.pi.o,%.o,$(obj-y))
diff --git a/arch/riscv/kernel/pi/cmdline_early.c b/arch/riscv/kernel/pi/cmdline_early.c
index fbcdc9e4e143..389d086a0718 100644
--- a/arch/riscv/kernel/pi/cmdline_early.c
+++ b/arch/riscv/kernel/pi/cmdline_early.c
@@ -41,9 +41,9 @@ static char *get_early_cmdline(uintptr_t dtb_pa)
static u64 match_noXlvl(char *cmdline)
{
if (strstr(cmdline, "no4lvl"))
- return SATP_MODE_48;
+ return SATP_MODE_39;
else if (strstr(cmdline, "no5lvl"))
- return SATP_MODE_57;
+ return SATP_MODE_48;
return 0;
}
diff --git a/arch/riscv/kernel/pi/fdt_early.c b/arch/riscv/kernel/pi/fdt_early.c
index 9bdee2fafe47..a12ff8090f19 100644
--- a/arch/riscv/kernel/pi/fdt_early.c
+++ b/arch/riscv/kernel/pi/fdt_early.c
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/libfdt.h>
#include <linux/ctype.h>
+#include <asm/csr.h>
#include "pi.h"
@@ -183,3 +184,42 @@ bool fdt_early_match_extension_isa(const void *fdt, const char *ext_name)
return ret;
}
+
+/**
+ * set_satp_mode_from_fdt - determine SATP mode based on the MMU type in fdt
+ *
+ * @dtb_pa: physical address of the device tree blob
+ *
+ * Returns the SATP mode corresponding to the MMU type of the first enabled CPU,
+ * 0 otherwise
+ */
+u64 set_satp_mode_from_fdt(uintptr_t dtb_pa)
+{
+ const void *fdt = (const void *)dtb_pa;
+ const char *mmu_type;
+ int node, parent;
+
+ parent = fdt_path_offset(fdt, "/cpus");
+ if (parent < 0)
+ return 0;
+
+ fdt_for_each_subnode(node, fdt, parent) {
+ if (!fdt_node_name_eq(fdt, node, "cpu"))
+ continue;
+
+ if (!fdt_device_is_available(fdt, node))
+ continue;
+
+ mmu_type = fdt_getprop(fdt, node, "mmu-type", NULL);
+ if (!mmu_type)
+ break;
+
+ if (!strcmp(mmu_type, "riscv,sv39"))
+ return SATP_MODE_39;
+ else if (!strcmp(mmu_type, "riscv,sv48"))
+ return SATP_MODE_48;
+ break;
+ }
+
+ return 0;
+}
diff --git a/arch/riscv/kernel/pi/pi.h b/arch/riscv/kernel/pi/pi.h
index 21141d84fea6..3fee2cfddf7c 100644
--- a/arch/riscv/kernel/pi/pi.h
+++ b/arch/riscv/kernel/pi/pi.h
@@ -14,6 +14,7 @@ u64 get_kaslr_seed(uintptr_t dtb_pa);
u64 get_kaslr_seed_zkr(const uintptr_t dtb_pa);
bool set_nokaslr_from_cmdline(uintptr_t dtb_pa);
u64 set_satp_mode_from_cmdline(uintptr_t dtb_pa);
+u64 set_satp_mode_from_fdt(uintptr_t dtb_pa);
bool fdt_early_match_extension_isa(const void *fdt, const char *ext_name);
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index 6c166029079c..fa581590c1f8 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -41,19 +41,16 @@ bool __kprobes simulate_jal(u32 opcode, unsigned long addr, struct pt_regs *regs
* 1 10 1 8 5 JAL/J
*/
bool ret;
- u32 imm;
- u32 index = (opcode >> 7) & 0x1f;
+ s32 imm;
+ u32 index = RV_EXTRACT_RD_REG(opcode);
ret = rv_insn_reg_set_val(regs, index, addr + 4);
if (!ret)
return ret;
- imm = ((opcode >> 21) & 0x3ff) << 1;
- imm |= ((opcode >> 20) & 0x1) << 11;
- imm |= ((opcode >> 12) & 0xff) << 12;
- imm |= ((opcode >> 31) & 0x1) << 20;
+ imm = RV_EXTRACT_JTYPE_IMM(opcode);
- instruction_pointer_set(regs, addr + sign_extend32((imm), 20));
+ instruction_pointer_set(regs, addr + imm);
return ret;
}
@@ -67,9 +64,9 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
*/
bool ret;
unsigned long base_addr;
- u32 imm = (opcode >> 20) & 0xfff;
- u32 rd_index = (opcode >> 7) & 0x1f;
- u32 rs1_index = (opcode >> 15) & 0x1f;
+ u32 imm = RV_EXTRACT_ITYPE_IMM(opcode);
+ u32 rd_index = RV_EXTRACT_RD_REG(opcode);
+ u32 rs1_index = RV_EXTRACT_RS1_REG(opcode);
ret = rv_insn_reg_get_val(regs, rs1_index, &base_addr);
if (!ret)
@@ -84,20 +81,6 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
return ret;
}
-#define auipc_rd_idx(opcode) \
- ((opcode >> 7) & 0x1f)
-
-#define auipc_imm(opcode) \
- ((((opcode) >> 12) & 0xfffff) << 12)
-
-#if __riscv_xlen == 64
-#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
-#elif __riscv_xlen == 32
-#define auipc_offset(opcode) auipc_imm(opcode)
-#else
-#error "Unexpected __riscv_xlen"
-#endif
-
bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
{
/*
@@ -107,8 +90,8 @@ bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *re
* 20 5 7
*/
- u32 rd_idx = auipc_rd_idx(opcode);
- unsigned long rd_val = addr + auipc_offset(opcode);
+ u32 rd_idx = RV_EXTRACT_RD_REG(opcode);
+ unsigned long rd_val = addr + (s32)RV_EXTRACT_UTYPE_IMM(opcode);
if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
return false;
@@ -118,24 +101,6 @@ bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *re
return true;
}
-#define branch_rs1_idx(opcode) \
- (((opcode) >> 15) & 0x1f)
-
-#define branch_rs2_idx(opcode) \
- (((opcode) >> 20) & 0x1f)
-
-#define branch_funct3(opcode) \
- (((opcode) >> 12) & 0x7)
-
-#define branch_imm(opcode) \
- (((((opcode) >> 8) & 0xf ) << 1) | \
- ((((opcode) >> 25) & 0x3f) << 5) | \
- ((((opcode) >> 7) & 0x1 ) << 11) | \
- ((((opcode) >> 31) & 0x1 ) << 12))
-
-#define branch_offset(opcode) \
- sign_extend32((branch_imm(opcode)), 12)
-
bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
{
/*
@@ -156,12 +121,12 @@ bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *r
unsigned long rs1_val;
unsigned long rs2_val;
- if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
- !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
+ if (!rv_insn_reg_get_val(regs, RV_EXTRACT_RS1_REG(opcode), &rs1_val) ||
+ !rv_insn_reg_get_val(regs, RV_EXTRACT_RS2_REG(opcode), &rs2_val))
return false;
- offset_tmp = branch_offset(opcode);
- switch (branch_funct3(opcode)) {
+ offset_tmp = RV_EXTRACT_BTYPE_IMM(opcode);
+ switch (RV_EXTRACT_FUNCT3(opcode)) {
case RVG_FUNCT3_BEQ:
offset = (rs1_val == rs2_val) ? offset_tmp : 4;
break;
@@ -191,24 +156,9 @@ bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *r
bool __kprobes simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs)
{
- /*
- * 15 13 12 2 1 0
- * | funct3 | offset[11|4|9:8|10|6|7|3:1|5] | opcode |
- * 3 11 2
- */
-
- s32 offset;
+ s32 offset = RVC_EXTRACT_JTYPE_IMM(opcode);
- offset = ((opcode >> 3) & 0x7) << 1;
- offset |= ((opcode >> 11) & 0x1) << 4;
- offset |= ((opcode >> 2) & 0x1) << 5;
- offset |= ((opcode >> 7) & 0x1) << 6;
- offset |= ((opcode >> 6) & 0x1) << 7;
- offset |= ((opcode >> 9) & 0x3) << 8;
- offset |= ((opcode >> 8) & 0x1) << 10;
- offset |= ((opcode >> 12) & 0x1) << 11;
-
- instruction_pointer_set(regs, addr + sign_extend32(offset, 11));
+ instruction_pointer_set(regs, addr + offset);
return true;
}
@@ -224,7 +174,7 @@ static bool __kprobes simulate_c_jr_jalr(u32 opcode, unsigned long addr, struct
unsigned long jump_addr;
- u32 rs1 = (opcode >> 7) & 0x1f;
+ u32 rs1 = RVC_EXTRACT_C2_RS1_REG(opcode);
if (rs1 == 0) /* C.JR is only valid when rs1 != x0 */
return false;
@@ -268,16 +218,10 @@ static bool __kprobes simulate_c_bnez_beqz(u32 opcode, unsigned long addr, struc
if (!rv_insn_reg_get_val(regs, rs1, &rs1_val))
return false;
- if ((rs1_val != 0 && is_bnez) || (rs1_val == 0 && !is_bnez)) {
- offset = ((opcode >> 3) & 0x3) << 1;
- offset |= ((opcode >> 10) & 0x3) << 3;
- offset |= ((opcode >> 2) & 0x1) << 5;
- offset |= ((opcode >> 5) & 0x3) << 6;
- offset |= ((opcode >> 12) & 0x1) << 8;
- offset = sign_extend32(offset, 8);
- } else {
+ if ((rs1_val != 0 && is_bnez) || (rs1_val == 0 && !is_bnez))
+ offset = RVC_EXTRACT_BTYPE_IMM(opcode);
+ else
offset = 2;
- }
instruction_pointer_set(regs, addr + offset);
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index a0a40889d79a..31a392993cb4 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -223,7 +223,7 @@ asmlinkage void ret_from_fork_user(struct pt_regs *regs)
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
{
- unsigned long clone_flags = args->flags;
+ u64 clone_flags = args->flags;
unsigned long usp = args->stack;
unsigned long tls = args->tls;
struct pt_regs *childregs = task_pt_regs(p);
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index 53836a9235e3..5e8cde055264 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -148,7 +148,7 @@ static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
static void sbi_set_power_off(void)
{
- pm_power_off = sbi_shutdown;
+ register_platform_power_off(sbi_shutdown);
}
#else
static void __sbi_set_timer_v01(uint64_t stime_value)
@@ -682,7 +682,7 @@ void __init sbi_init(void)
if (sbi_spec_version >= sbi_mk_version(0, 3) &&
sbi_probe_extension(SBI_EXT_SRST)) {
pr_info("SBI SRST extension detected\n");
- pm_power_off = sbi_srst_power_off;
+ register_platform_power_off(sbi_srst_power_off);
sbi_srst_reboot_nb.notifier_call = sbi_srst_reboot;
sbi_srst_reboot_nb.priority = 192;
register_restart_handler(&sbi_srst_reboot_nb);
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index f90cce7a3ace..14235e58c539 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -290,6 +290,7 @@ static void __init riscv_spinlock_init(void)
if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) &&
IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) &&
+ IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZACAS) &&
riscv_isa_extension_available(NULL, ZABHA) &&
riscv_isa_extension_available(NULL, ZACAS)) {
using_ext = "using Zabha";
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index 0b170e18a2be..000f4451a9d8 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -15,6 +15,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/vector.h>
+#include <asm/vendor_extensions/mips_hwprobe.h>
#include <asm/vendor_extensions/sifive_hwprobe.h>
#include <asm/vendor_extensions/thead_hwprobe.h>
#include <vdso/vsyscall.h>
@@ -153,14 +154,12 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZVKT);
}
- if (has_fpu()) {
- EXT_KEY(ZCD);
- EXT_KEY(ZCF);
- EXT_KEY(ZFA);
- EXT_KEY(ZFBFMIN);
- EXT_KEY(ZFH);
- EXT_KEY(ZFHMIN);
- }
+ EXT_KEY(ZCD);
+ EXT_KEY(ZCF);
+ EXT_KEY(ZFA);
+ EXT_KEY(ZFBFMIN);
+ EXT_KEY(ZFH);
+ EXT_KEY(ZFHMIN);
if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM))
EXT_KEY(SUPM);
@@ -309,6 +308,9 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
hwprobe_isa_vendor_ext_thead_0(pair, cpus);
break;
+ case RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0:
+ hwprobe_isa_vendor_ext_mips_0(pair, cpus);
+ break;
/*
* For forward compatibility, unknown keys don't fail the whole
diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c
index d77afe05578f..795b2e815ac9 100644
--- a/arch/riscv/kernel/sys_riscv.c
+++ b/arch/riscv/kernel/sys_riscv.c
@@ -10,7 +10,7 @@
static long riscv_sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
- unsigned long fd, off_t offset,
+ unsigned long fd, unsigned long offset,
unsigned long page_shift_offset)
{
if (unlikely(offset & (~PAGE_MASK >> page_shift_offset)))
diff --git a/arch/riscv/kernel/tests/Kconfig.debug b/arch/riscv/kernel/tests/Kconfig.debug
index 78cea5d2c270..5db4df44279e 100644
--- a/arch/riscv/kernel/tests/Kconfig.debug
+++ b/arch/riscv/kernel/tests/Kconfig.debug
@@ -30,6 +30,18 @@ config RISCV_MODULE_LINKING_KUNIT
If unsure, say N.
+config RISCV_KPROBES_KUNIT
+ bool "KUnit test for riscv kprobes" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ depends on KPROBES
+ default KUNIT_ALL_TESTS
+ help
+ Enable testing for riscv kprobes. Useful for riscv and/or kprobes
+ development. The test verifies that kprobes do not change the behaviour
+ of some sample functions.
+
+ If unsure, say N.
+
endif # RUNTIME_TESTING_MENU
endmenu # "arch/riscv/kernel runtime Testing"
diff --git a/arch/riscv/kernel/tests/Makefile b/arch/riscv/kernel/tests/Makefile
index 7d6c76cffe20..407e7e6c28dc 100644
--- a/arch/riscv/kernel/tests/Makefile
+++ b/arch/riscv/kernel/tests/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_RISCV_MODULE_LINKING_KUNIT) += module_test/
+obj-$(CONFIG_RISCV_KPROBES_KUNIT) += kprobes/
diff --git a/arch/riscv/kernel/tests/kprobes/Makefile b/arch/riscv/kernel/tests/kprobes/Makefile
new file mode 100644
index 000000000000..4cb6c66a98e8
--- /dev/null
+++ b/arch/riscv/kernel/tests/kprobes/Makefile
@@ -0,0 +1 @@
+obj-y += test-kprobes.o test-kprobes-asm.o
diff --git a/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S b/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S
new file mode 100644
index 000000000000..b951d0f12482
--- /dev/null
+++ b/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+#include "test-kprobes.h"
+
+SYM_FUNC_START(test_kprobes_add)
+ li a1, KPROBE_TEST_MAGIC_UPPER
+ li a2, KPROBE_TEST_MAGIC_LOWER
+test_kprobes_add_addr1:
+ add a1, a1, a2
+test_kprobes_add_addr2:
+ add a0, a1, x0
+ ret
+SYM_FUNC_END(test_kprobes_add)
+
+SYM_FUNC_START(test_kprobes_jal)
+ li a0, 0
+ mv a1, ra
+ .option push
+ .option norvc
+test_kprobes_jal_addr1:
+ jal x0, 2f
+ ret
+ .option pop
+1: li a0, KPROBE_TEST_MAGIC_UPPER
+ ret
+ .option push
+ .option norvc
+test_kprobes_jal_addr2:
+2: jal 1b
+ .option pop
+ li a2, KPROBE_TEST_MAGIC_LOWER
+ add a0, a0, a2
+ jr a1
+SYM_FUNC_END(test_kprobes_jal)
+
+SYM_FUNC_START(test_kprobes_jalr)
+ la a0, 1f
+ mv a1, ra
+ .option push
+ .option norvc
+test_kprobes_jalr_addr:
+ jalr a0
+ .option pop
+ li t0, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, t0
+ jr a1
+1: li a0, KPROBE_TEST_MAGIC_LOWER
+ ret
+SYM_FUNC_END(test_kprobes_jalr)
+
+SYM_FUNC_START(test_kprobes_auipc)
+test_kprobes_auipc_addr:
+ auipc a0, KPROBE_TEST_MAGIC_LOWER
+ la a1, test_kprobes_auipc_addr
+ sub a0, a0, a1
+ srli a0, a0, 12
+ li a1, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, a1
+ ret
+SYM_FUNC_END(test_kprobes_auipc)
+
+SYM_FUNC_START(test_kprobes_branch)
+ .option push
+ .option norvc
+ li a0, 0
+ li a1, 1
+ li a2, 2
+test_kprobes_branch_addr1:
+ beqz a0, 1f
+ ret
+1:
+test_kprobes_branch_addr2:
+ beqz a1, 3f
+test_kprobes_branch_addr3:
+ bnez a0, 3f
+test_kprobes_branch_addr4:
+ bnez a2, 1f
+ ret
+1:
+test_kprobes_branch_addr5:
+ bge a1, a2, 3f
+test_kprobes_branch_addr6:
+ bge a2, a1, 2f
+ ret
+1:
+ li t0, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, t0
+ ret
+2:
+test_kprobes_branch_addr7:
+ blt a2, a1, 3f
+ li a0, KPROBE_TEST_MAGIC_LOWER
+test_kprobes_branch_addr8:
+ blt a1, a2, 1b
+3:
+ li a0, 0
+ ret
+ .option pop
+SYM_FUNC_END(test_kprobes_branch)
+
+#ifdef CONFIG_RISCV_ISA_C
+
+SYM_FUNC_START(test_kprobes_c_j)
+ li a0, 0
+test_kprobes_branch_c_j_addr1:
+ c.j 2f
+1:
+ li a1, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, a1
+ ret
+2: li a0, KPROBE_TEST_MAGIC_LOWER
+test_kprobes_branch_c_j_addr2:
+ c.j 1b
+SYM_FUNC_END(test_kprobes_c_j)
+
+SYM_FUNC_START(test_kprobes_c_jr)
+ la a0, 2f
+test_kprobes_c_jr_addr1:
+ c.jr a0
+ ret
+1: li a1, KPROBE_TEST_MAGIC_LOWER
+ add a0, a0, a1
+ ret
+2:
+ li a0, KPROBE_TEST_MAGIC_UPPER
+ la a1, 1b
+test_kprobes_c_jr_addr2:
+ c.jr a1
+SYM_FUNC_END(test_kprobes_c_jr)
+
+SYM_FUNC_START(test_kprobes_c_jalr)
+ mv a1, ra
+ la a0, 1f
+test_kprobes_c_jalr_addr:
+ c.jalr a0
+ li a2, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, a2
+ jr a1
+1: li a0, KPROBE_TEST_MAGIC_LOWER
+ ret
+SYM_FUNC_END(test_kprobes_c_jalr)
+
+SYM_FUNC_START(test_kprobes_c_beqz)
+ li a0, 0
+ li a1, 1
+test_kprobes_c_beqz_addr1:
+ c.beqz a0, 2f
+ ret
+1: li a1, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, a1
+ ret
+test_kprobes_c_beqz_addr2:
+2: c.beqz a1, 3f
+ li a0, KPROBE_TEST_MAGIC_LOWER
+ mv a1, x0
+test_kprobes_c_beqz_addr3:
+ c.beqz a1, 1b
+3: li a0, 0
+ ret
+SYM_FUNC_END(test_kprobes_c_beqz)
+
+SYM_FUNC_START(test_kprobes_c_bnez)
+ li a0, 0
+ li a1, 1
+test_kprobes_c_bnez_addr1:
+ c.bnez a1, 2f
+ ret
+1: li a1, KPROBE_TEST_MAGIC_UPPER
+ add a0, a0, a1
+ ret
+test_kprobes_c_bnez_addr2:
+2: c.bnez a0, 3f
+ li a0, KPROBE_TEST_MAGIC_LOWER
+test_kprobes_c_bnez_addr3:
+ c.bnez a0, 1b
+3: li a0, 0
+ ret
+SYM_FUNC_END(test_kprobes_c_bnez)
+
+#endif /* CONFIG_RISCV_ISA_C */
+
+SYM_DATA_START(test_kprobes_addresses)
+ RISCV_PTR test_kprobes_add_addr1
+ RISCV_PTR test_kprobes_add_addr2
+ RISCV_PTR test_kprobes_jal_addr1
+ RISCV_PTR test_kprobes_jal_addr2
+ RISCV_PTR test_kprobes_jalr_addr
+ RISCV_PTR test_kprobes_auipc_addr
+ RISCV_PTR test_kprobes_branch_addr1
+ RISCV_PTR test_kprobes_branch_addr2
+ RISCV_PTR test_kprobes_branch_addr3
+ RISCV_PTR test_kprobes_branch_addr4
+ RISCV_PTR test_kprobes_branch_addr5
+ RISCV_PTR test_kprobes_branch_addr6
+ RISCV_PTR test_kprobes_branch_addr7
+ RISCV_PTR test_kprobes_branch_addr8
+#ifdef CONFIG_RISCV_ISA_C
+ RISCV_PTR test_kprobes_branch_c_j_addr1
+ RISCV_PTR test_kprobes_branch_c_j_addr2
+ RISCV_PTR test_kprobes_c_jr_addr1
+ RISCV_PTR test_kprobes_c_jr_addr2
+ RISCV_PTR test_kprobes_c_jalr_addr
+ RISCV_PTR test_kprobes_c_beqz_addr1
+ RISCV_PTR test_kprobes_c_beqz_addr2
+ RISCV_PTR test_kprobes_c_beqz_addr3
+ RISCV_PTR test_kprobes_c_bnez_addr1
+ RISCV_PTR test_kprobes_c_bnez_addr2
+ RISCV_PTR test_kprobes_c_bnez_addr3
+#endif /* CONFIG_RISCV_ISA_C */
+ RISCV_PTR 0
+SYM_DATA_END(test_kprobes_addresses)
+
+SYM_DATA_START(test_kprobes_functions)
+ RISCV_PTR test_kprobes_add
+ RISCV_PTR test_kprobes_jal
+ RISCV_PTR test_kprobes_jalr
+ RISCV_PTR test_kprobes_auipc
+ RISCV_PTR test_kprobes_branch
+#ifdef CONFIG_RISCV_ISA_C
+ RISCV_PTR test_kprobes_c_j
+ RISCV_PTR test_kprobes_c_jr
+ RISCV_PTR test_kprobes_c_jalr
+ RISCV_PTR test_kprobes_c_beqz
+ RISCV_PTR test_kprobes_c_bnez
+#endif /* CONFIG_RISCV_ISA_C */
+ RISCV_PTR 0
+SYM_DATA_END(test_kprobes_functions)
diff --git a/arch/riscv/kernel/tests/kprobes/test-kprobes.c b/arch/riscv/kernel/tests/kprobes/test-kprobes.c
new file mode 100644
index 000000000000..6f6cdfbf5a95
--- /dev/null
+++ b/arch/riscv/kernel/tests/kprobes/test-kprobes.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <kunit/test.h>
+#include "test-kprobes.h"
+
+static int kprobe_dummy_handler(struct kprobe *kp, struct pt_regs *regs)
+{
+ return 0;
+}
+
+static void test_kprobe_riscv(struct kunit *test)
+{
+ unsigned int num_kprobe = 0;
+ long (*func)(void);
+ struct kprobe *kp;
+ int i;
+
+ while (test_kprobes_addresses[num_kprobe])
+ num_kprobe++;
+
+ kp = kcalloc(num_kprobe, sizeof(*kp), GFP_KERNEL);
+ KUNIT_EXPECT_TRUE(test, kp);
+ if (!kp)
+ return;
+
+ for (i = 0; i < num_kprobe; ++i) {
+ kp[i].addr = test_kprobes_addresses[i];
+ kp[i].pre_handler = kprobe_dummy_handler;
+ KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp[i]));
+ }
+
+ for (i = 0;; ++i) {
+ func = test_kprobes_functions[i];
+ if (!func)
+ break;
+ KUNIT_EXPECT_EQ_MSG(test, KPROBE_TEST_MAGIC, func(), "function %d broken", i);
+ }
+
+ for (i = 0; i < num_kprobe; ++i)
+ unregister_kprobe(&kp[i]);
+ kfree(kp);
+}
+
+static struct kunit_case kprobes_testcases[] = {
+ KUNIT_CASE(test_kprobe_riscv),
+ {}
+};
+
+static struct kunit_suite kprobes_test_suite = {
+ .name = "kprobes_test_riscv",
+ .test_cases = kprobes_testcases,
+};
+
+kunit_test_suites(&kprobes_test_suite);
diff --git a/arch/riscv/kernel/tests/kprobes/test-kprobes.h b/arch/riscv/kernel/tests/kprobes/test-kprobes.h
new file mode 100644
index 000000000000..3886ab491ecb
--- /dev/null
+++ b/arch/riscv/kernel/tests/kprobes/test-kprobes.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef TEST_KPROBES_H
+#define TEST_KPROBES_H
+
+/*
+ * The magic value that all the functions in the test_kprobes_functions array return. The test
+ * installs kprobes into these functions, and verify that the functions still correctly return this
+ * value.
+ */
+#define KPROBE_TEST_MAGIC 0xcafebabe
+#define KPROBE_TEST_MAGIC_LOWER 0x0000babe
+#define KPROBE_TEST_MAGIC_UPPER 0xcafe0000
+
+#ifndef __ASSEMBLY__
+
+/* array of addresses to install kprobes */
+extern void *test_kprobes_addresses[];
+
+/* array of functions that return KPROBE_TEST_MAGIC */
+extern long (*test_kprobes_functions[])(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* TEST_KPROBES_H */
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index f760e4fcc052..2a27d3ff4ac6 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -18,149 +18,7 @@
#include <asm/cpufeature.h>
#include <asm/sbi.h>
#include <asm/vector.h>
-
-#define INSN_MATCH_LB 0x3
-#define INSN_MASK_LB 0x707f
-#define INSN_MATCH_LH 0x1003
-#define INSN_MASK_LH 0x707f
-#define INSN_MATCH_LW 0x2003
-#define INSN_MASK_LW 0x707f
-#define INSN_MATCH_LD 0x3003
-#define INSN_MASK_LD 0x707f
-#define INSN_MATCH_LBU 0x4003
-#define INSN_MASK_LBU 0x707f
-#define INSN_MATCH_LHU 0x5003
-#define INSN_MASK_LHU 0x707f
-#define INSN_MATCH_LWU 0x6003
-#define INSN_MASK_LWU 0x707f
-#define INSN_MATCH_SB 0x23
-#define INSN_MASK_SB 0x707f
-#define INSN_MATCH_SH 0x1023
-#define INSN_MASK_SH 0x707f
-#define INSN_MATCH_SW 0x2023
-#define INSN_MASK_SW 0x707f
-#define INSN_MATCH_SD 0x3023
-#define INSN_MASK_SD 0x707f
-
-#define INSN_MATCH_FLW 0x2007
-#define INSN_MASK_FLW 0x707f
-#define INSN_MATCH_FLD 0x3007
-#define INSN_MASK_FLD 0x707f
-#define INSN_MATCH_FLQ 0x4007
-#define INSN_MASK_FLQ 0x707f
-#define INSN_MATCH_FSW 0x2027
-#define INSN_MASK_FSW 0x707f
-#define INSN_MATCH_FSD 0x3027
-#define INSN_MASK_FSD 0x707f
-#define INSN_MATCH_FSQ 0x4027
-#define INSN_MASK_FSQ 0x707f
-
-#define INSN_MATCH_C_LD 0x6000
-#define INSN_MASK_C_LD 0xe003
-#define INSN_MATCH_C_SD 0xe000
-#define INSN_MASK_C_SD 0xe003
-#define INSN_MATCH_C_LW 0x4000
-#define INSN_MASK_C_LW 0xe003
-#define INSN_MATCH_C_SW 0xc000
-#define INSN_MASK_C_SW 0xe003
-#define INSN_MATCH_C_LDSP 0x6002
-#define INSN_MASK_C_LDSP 0xe003
-#define INSN_MATCH_C_SDSP 0xe002
-#define INSN_MASK_C_SDSP 0xe003
-#define INSN_MATCH_C_LWSP 0x4002
-#define INSN_MASK_C_LWSP 0xe003
-#define INSN_MATCH_C_SWSP 0xc002
-#define INSN_MASK_C_SWSP 0xe003
-
-#define INSN_MATCH_C_FLD 0x2000
-#define INSN_MASK_C_FLD 0xe003
-#define INSN_MATCH_C_FLW 0x6000
-#define INSN_MASK_C_FLW 0xe003
-#define INSN_MATCH_C_FSD 0xa000
-#define INSN_MASK_C_FSD 0xe003
-#define INSN_MATCH_C_FSW 0xe000
-#define INSN_MASK_C_FSW 0xe003
-#define INSN_MATCH_C_FLDSP 0x2002
-#define INSN_MASK_C_FLDSP 0xe003
-#define INSN_MATCH_C_FSDSP 0xa002
-#define INSN_MASK_C_FSDSP 0xe003
-#define INSN_MATCH_C_FLWSP 0x6002
-#define INSN_MASK_C_FLWSP 0xe003
-#define INSN_MATCH_C_FSWSP 0xe002
-#define INSN_MASK_C_FSWSP 0xe003
-
-#define INSN_MATCH_C_LHU 0x8400
-#define INSN_MASK_C_LHU 0xfc43
-#define INSN_MATCH_C_LH 0x8440
-#define INSN_MASK_C_LH 0xfc43
-#define INSN_MATCH_C_SH 0x8c00
-#define INSN_MASK_C_SH 0xfc43
-
-#define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4)
-
-#if defined(CONFIG_64BIT)
-#define LOG_REGBYTES 3
-#define XLEN 64
-#else
-#define LOG_REGBYTES 2
-#define XLEN 32
-#endif
-#define REGBYTES (1 << LOG_REGBYTES)
-#define XLEN_MINUS_16 ((XLEN) - 16)
-
-#define SH_RD 7
-#define SH_RS1 15
-#define SH_RS2 20
-#define SH_RS2C 2
-
-#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1))
-#define RVC_LW_IMM(x) ((RV_X(x, 6, 1) << 2) | \
- (RV_X(x, 10, 3) << 3) | \
- (RV_X(x, 5, 1) << 6))
-#define RVC_LD_IMM(x) ((RV_X(x, 10, 3) << 3) | \
- (RV_X(x, 5, 2) << 6))
-#define RVC_LWSP_IMM(x) ((RV_X(x, 4, 3) << 2) | \
- (RV_X(x, 12, 1) << 5) | \
- (RV_X(x, 2, 2) << 6))
-#define RVC_LDSP_IMM(x) ((RV_X(x, 5, 2) << 3) | \
- (RV_X(x, 12, 1) << 5) | \
- (RV_X(x, 2, 3) << 6))
-#define RVC_SWSP_IMM(x) ((RV_X(x, 9, 4) << 2) | \
- (RV_X(x, 7, 2) << 6))
-#define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | \
- (RV_X(x, 7, 3) << 6))
-#define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3))
-#define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3))
-#define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5)
-
-#define SHIFT_RIGHT(x, y) \
- ((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
-
-#define REG_MASK \
- ((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
-
-#define REG_OFFSET(insn, pos) \
- (SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
-
-#define REG_PTR(insn, pos, regs) \
- (ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
-
-#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
-#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
-#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
-#define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
-#define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
-#define GET_SP(regs) (*REG_PTR(2, 0, regs))
-#define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
-#define IMM_I(insn) ((s32)(insn) >> 20)
-#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
- (s32)(((insn) >> 7) & 0x1f))
-#define MASK_FUNCT3 0x7000
-
-#define GET_PRECISION(insn) (((insn) >> 25) & 3)
-#define GET_RM(insn) (((insn) >> 12) & 7)
-#define PRECISION_S 0
-#define PRECISION_D 1
+#include <asm/insn.h>
#ifdef CONFIG_FPU
diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
index 184f780c932d..901e67adf576 100644
--- a/arch/riscv/kernel/vector.c
+++ b/arch/riscv/kernel/vector.c
@@ -93,7 +93,7 @@ bool insn_is_vector(u32 insn_buf)
return true;
case RVV_OPCODE_VL:
case RVV_OPCODE_VS:
- width = RVV_EXRACT_VL_VS_WIDTH(insn_buf);
+ width = RVV_EXTRACT_VL_VS_WIDTH(insn_buf);
if (width == RVV_VL_VS_WIDTH_8 || width == RVV_VL_VS_WIDTH_16 ||
width == RVV_VL_VS_WIDTH_32 || width == RVV_VL_VS_WIDTH_64)
return true;
diff --git a/arch/riscv/kernel/vendor_extensions.c b/arch/riscv/kernel/vendor_extensions.c
index 92d8ff81f42c..bb4a75923685 100644
--- a/arch/riscv/kernel/vendor_extensions.c
+++ b/arch/riscv/kernel/vendor_extensions.c
@@ -6,6 +6,7 @@
#include <asm/vendorid_list.h>
#include <asm/vendor_extensions.h>
#include <asm/vendor_extensions/andes.h>
+#include <asm/vendor_extensions/mips.h>
#include <asm/vendor_extensions/sifive.h>
#include <asm/vendor_extensions/thead.h>
@@ -16,6 +17,9 @@ struct riscv_isa_vendor_ext_data_list *riscv_isa_vendor_ext_list[] = {
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_ANDES
&riscv_isa_vendor_ext_list_andes,
#endif
+#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_MIPS
+ &riscv_isa_vendor_ext_list_mips,
+#endif
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_SIFIVE
&riscv_isa_vendor_ext_list_sifive,
#endif
@@ -49,6 +53,12 @@ bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsig
cpu_bmap = riscv_isa_vendor_ext_list_andes.per_hart_isa_bitmap;
break;
#endif
+ #ifdef CONFIG_RISCV_ISA_VENDOR_EXT_MIPS
+ case MIPS_VENDOR_ID:
+ bmap = &riscv_isa_vendor_ext_list_mips.all_harts_isa_bitmap;
+ cpu_bmap = riscv_isa_vendor_ext_list_mips.per_hart_isa_bitmap;
+ break;
+ #endif
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_SIFIVE
case SIFIVE_VENDOR_ID:
bmap = &riscv_isa_vendor_ext_list_sifive.all_harts_isa_bitmap;
diff --git a/arch/riscv/kernel/vendor_extensions/Makefile b/arch/riscv/kernel/vendor_extensions/Makefile
index a4eca96d1c8a..bf116c82b6bd 100644
--- a/arch/riscv/kernel/vendor_extensions/Makefile
+++ b/arch/riscv/kernel/vendor_extensions/Makefile
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_ANDES) += andes.o
+obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_MIPS) += mips.o
+obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_MIPS) += mips_hwprobe.o
obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_SIFIVE) += sifive.o
obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_SIFIVE) += sifive_hwprobe.o
obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_THEAD) += thead.o
diff --git a/arch/riscv/kernel/vendor_extensions/mips.c b/arch/riscv/kernel/vendor_extensions/mips.c
new file mode 100644
index 000000000000..f691129f96c2
--- /dev/null
+++ b/arch/riscv/kernel/vendor_extensions/mips.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 MIPS.
+ */
+
+#include <asm/cpufeature.h>
+#include <asm/vendor_extensions.h>
+#include <asm/vendor_extensions/mips.h>
+
+#include <linux/array_size.h>
+#include <linux/cpumask.h>
+#include <linux/types.h>
+
+/* All MIPS vendor extensions supported in Linux */
+static const struct riscv_isa_ext_data riscv_isa_vendor_ext_mips[] = {
+ __RISCV_ISA_EXT_DATA(xmipsexectl, RISCV_ISA_VENDOR_EXT_XMIPSEXECTL),
+};
+
+struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_mips = {
+ .ext_data_count = ARRAY_SIZE(riscv_isa_vendor_ext_mips),
+ .ext_data = riscv_isa_vendor_ext_mips,
+};
diff --git a/arch/riscv/kernel/vendor_extensions/mips_hwprobe.c b/arch/riscv/kernel/vendor_extensions/mips_hwprobe.c
new file mode 100644
index 000000000000..dc213a2ca70d
--- /dev/null
+++ b/arch/riscv/kernel/vendor_extensions/mips_hwprobe.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 MIPS.
+ */
+
+#include <asm/vendor_extensions.h>
+#include <asm/vendor_extensions/mips.h>
+#include <asm/vendor_extensions/mips_hwprobe.h>
+#include <asm/vendor_extensions/vendor_hwprobe.h>
+
+#include <linux/cpumask.h>
+#include <linux/types.h>
+
+#include <uapi/asm/hwprobe.h>
+#include <uapi/asm/vendor/mips.h>
+
+void hwprobe_isa_vendor_ext_mips_0(struct riscv_hwprobe *pair,
+ const struct cpumask *cpus)
+{
+ VENDOR_EXTENSION_SUPPORTED(pair, cpus,
+ riscv_isa_vendor_ext_list_mips.per_hart_isa_bitmap,
+ { VENDOR_EXT_KEY(XMIPSEXECTL); });
+}
diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
index 97dec18e6989..de1f96ea6225 100644
--- a/arch/riscv/kvm/vcpu_insn.c
+++ b/arch/riscv/kvm/vcpu_insn.c
@@ -8,133 +8,7 @@
#include <linux/kvm_host.h>
#include <asm/cpufeature.h>
-
-#define INSN_OPCODE_MASK 0x007c
-#define INSN_OPCODE_SHIFT 2
-#define INSN_OPCODE_SYSTEM 28
-
-#define INSN_MASK_WFI 0xffffffff
-#define INSN_MATCH_WFI 0x10500073
-
-#define INSN_MASK_WRS 0xffffffff
-#define INSN_MATCH_WRS 0x00d00073
-
-#define INSN_MATCH_CSRRW 0x1073
-#define INSN_MASK_CSRRW 0x707f
-#define INSN_MATCH_CSRRS 0x2073
-#define INSN_MASK_CSRRS 0x707f
-#define INSN_MATCH_CSRRC 0x3073
-#define INSN_MASK_CSRRC 0x707f
-#define INSN_MATCH_CSRRWI 0x5073
-#define INSN_MASK_CSRRWI 0x707f
-#define INSN_MATCH_CSRRSI 0x6073
-#define INSN_MASK_CSRRSI 0x707f
-#define INSN_MATCH_CSRRCI 0x7073
-#define INSN_MASK_CSRRCI 0x707f
-
-#define INSN_MATCH_LB 0x3
-#define INSN_MASK_LB 0x707f
-#define INSN_MATCH_LH 0x1003
-#define INSN_MASK_LH 0x707f
-#define INSN_MATCH_LW 0x2003
-#define INSN_MASK_LW 0x707f
-#define INSN_MATCH_LD 0x3003
-#define INSN_MASK_LD 0x707f
-#define INSN_MATCH_LBU 0x4003
-#define INSN_MASK_LBU 0x707f
-#define INSN_MATCH_LHU 0x5003
-#define INSN_MASK_LHU 0x707f
-#define INSN_MATCH_LWU 0x6003
-#define INSN_MASK_LWU 0x707f
-#define INSN_MATCH_SB 0x23
-#define INSN_MASK_SB 0x707f
-#define INSN_MATCH_SH 0x1023
-#define INSN_MASK_SH 0x707f
-#define INSN_MATCH_SW 0x2023
-#define INSN_MASK_SW 0x707f
-#define INSN_MATCH_SD 0x3023
-#define INSN_MASK_SD 0x707f
-
-#define INSN_MATCH_C_LD 0x6000
-#define INSN_MASK_C_LD 0xe003
-#define INSN_MATCH_C_SD 0xe000
-#define INSN_MASK_C_SD 0xe003
-#define INSN_MATCH_C_LW 0x4000
-#define INSN_MASK_C_LW 0xe003
-#define INSN_MATCH_C_SW 0xc000
-#define INSN_MASK_C_SW 0xe003
-#define INSN_MATCH_C_LDSP 0x6002
-#define INSN_MASK_C_LDSP 0xe003
-#define INSN_MATCH_C_SDSP 0xe002
-#define INSN_MASK_C_SDSP 0xe003
-#define INSN_MATCH_C_LWSP 0x4002
-#define INSN_MASK_C_LWSP 0xe003
-#define INSN_MATCH_C_SWSP 0xc002
-#define INSN_MASK_C_SWSP 0xe003
-
-#define INSN_16BIT_MASK 0x3
-
-#define INSN_IS_16BIT(insn) (((insn) & INSN_16BIT_MASK) != INSN_16BIT_MASK)
-
-#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4)
-
-#ifdef CONFIG_64BIT
-#define LOG_REGBYTES 3
-#else
-#define LOG_REGBYTES 2
-#endif
-#define REGBYTES (1 << LOG_REGBYTES)
-
-#define SH_RD 7
-#define SH_RS1 15
-#define SH_RS2 20
-#define SH_RS2C 2
-#define MASK_RX 0x1f
-
-#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1))
-#define RVC_LW_IMM(x) ((RV_X(x, 6, 1) << 2) | \
- (RV_X(x, 10, 3) << 3) | \
- (RV_X(x, 5, 1) << 6))
-#define RVC_LD_IMM(x) ((RV_X(x, 10, 3) << 3) | \
- (RV_X(x, 5, 2) << 6))
-#define RVC_LWSP_IMM(x) ((RV_X(x, 4, 3) << 2) | \
- (RV_X(x, 12, 1) << 5) | \
- (RV_X(x, 2, 2) << 6))
-#define RVC_LDSP_IMM(x) ((RV_X(x, 5, 2) << 3) | \
- (RV_X(x, 12, 1) << 5) | \
- (RV_X(x, 2, 3) << 6))
-#define RVC_SWSP_IMM(x) ((RV_X(x, 9, 4) << 2) | \
- (RV_X(x, 7, 2) << 6))
-#define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | \
- (RV_X(x, 7, 3) << 6))
-#define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3))
-#define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3))
-#define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5)
-
-#define SHIFT_RIGHT(x, y) \
- ((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
-
-#define REG_MASK \
- ((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
-
-#define REG_OFFSET(insn, pos) \
- (SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
-
-#define REG_PTR(insn, pos, regs) \
- ((ulong *)((ulong)(regs) + REG_OFFSET(insn, pos)))
-
-#define GET_FUNCT3(insn) (((insn) >> 12) & 7)
-
-#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
-#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
-#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
-#define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
-#define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
-#define GET_SP(regs) (*REG_PTR(2, 0, regs))
-#define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
-#define IMM_I(insn) ((s32)(insn) >> 20)
-#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
- (s32)(((insn) >> 7) & 0x1f))
+#include <asm/insn.h>
struct insn_func {
unsigned long mask;
diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c
index 4ca5aafce22e..d83a612464f6 100644
--- a/arch/riscv/mm/cacheflush.c
+++ b/arch/riscv/mm/cacheflush.c
@@ -101,9 +101,9 @@ void flush_icache_pte(struct mm_struct *mm, pte_t pte)
{
struct folio *folio = page_folio(pte_page(pte));
- if (!test_bit(PG_dcache_clean, &folio->flags)) {
+ if (!test_bit(PG_dcache_clean, &folio->flags.f)) {
flush_icache_mm(mm, false);
- set_bit(PG_dcache_clean, &folio->flags);
+ set_bit(PG_dcache_clean, &folio->flags.f);
}
}
#endif /* CONFIG_MMU */
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 15683ae13fa5..d85efe74a4b6 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -23,6 +23,7 @@
#include <linux/kfence.h>
#include <linux/execmem.h>
+#include <asm/alternative.h>
#include <asm/fixmap.h>
#include <asm/io.h>
#include <asm/kasan.h>
@@ -816,6 +817,7 @@ static __meminit pgprot_t pgprot_from_va(uintptr_t va)
#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL)
u64 __pi_set_satp_mode_from_cmdline(uintptr_t dtb_pa);
+u64 __pi_set_satp_mode_from_fdt(uintptr_t dtb_pa);
static void __init disable_pgtable_l5(void)
{
@@ -855,18 +857,22 @@ static void __init set_mmap_rnd_bits_max(void)
* underlying hardware: establish 1:1 mapping in 4-level page table mode
* then read SATP to see if the configuration was taken into account
* meaning sv48 is supported.
+ * The maximum SATP mode is limited by both the command line and the "mmu-type"
+ * property in the device tree, since some platforms may hang if an unsupported
+ * SATP mode is attempted.
*/
static __init void set_satp_mode(uintptr_t dtb_pa)
{
u64 identity_satp, hw_satp;
uintptr_t set_satp_mode_pmd = ((unsigned long)set_satp_mode) & PMD_MASK;
- u64 satp_mode_cmdline = __pi_set_satp_mode_from_cmdline(dtb_pa);
+ u64 satp_mode_limit = min_not_zero(__pi_set_satp_mode_from_cmdline(dtb_pa),
+ __pi_set_satp_mode_from_fdt(dtb_pa));
kernel_map.page_offset = PAGE_OFFSET_L5;
- if (satp_mode_cmdline == SATP_MODE_57) {
+ if (satp_mode_limit == SATP_MODE_48) {
disable_pgtable_l5();
- } else if (satp_mode_cmdline == SATP_MODE_48) {
+ } else if (satp_mode_limit == SATP_MODE_39) {
disable_pgtable_l5();
disable_pgtable_l4();
return;
@@ -1624,7 +1630,7 @@ static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d)
if (PageReserved(page))
free_reserved_page(page);
else
- free_pages((unsigned long)page_address(page), 0);
+ __free_pages(page, 0);
p4d_clear(p4d);
}
@@ -1646,7 +1652,7 @@ static void __meminit free_vmemmap_storage(struct page *page, size_t size,
return;
}
- free_pages((unsigned long)page_address(page), order);
+ __free_pages(page, order);
}
static void __meminit remove_pte_mapping(pte_t *pte_base, unsigned long addr, unsigned long end,
diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
index 41c635d6aca4..c4a2a9e5586e 100644
--- a/arch/riscv/mm/kasan_init.c
+++ b/arch/riscv/mm/kasan_init.c
@@ -533,4 +533,5 @@ void __init kasan_init(void)
csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode);
local_flush_tlb_all();
+ kasan_init_generic();
}
diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index e7b032dfd17f..632ced07bca4 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -13,21 +13,15 @@
#include <linux/filter.h>
#include <asm/cacheflush.h>
+/* verify runtime detection extension status */
+#define rv_ext_enabled(ext) \
+ (IS_ENABLED(CONFIG_RISCV_ISA_##ext) && riscv_has_extension_likely(RISCV_ISA_EXT_##ext))
+
static inline bool rvc_enabled(void)
{
return IS_ENABLED(CONFIG_RISCV_ISA_C);
}
-static inline bool rvzba_enabled(void)
-{
- return IS_ENABLED(CONFIG_RISCV_ISA_ZBA) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBA);
-}
-
-static inline bool rvzbb_enabled(void)
-{
- return IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBB);
-}
-
enum {
RV_REG_ZERO = 0, /* The constant value 0 */
RV_REG_RA = 1, /* Return address */
@@ -84,6 +78,8 @@ struct rv_jit_context {
int epilogue_offset;
int *offset; /* BPF to RV */
int nexentries;
+ int ex_insn_off;
+ int ex_jmp_off;
unsigned long flags;
int stack_size;
u64 arena_vm_start;
@@ -757,6 +753,17 @@ static inline u16 rvc_swsp(u32 imm8, u8 rs2)
return rv_css_insn(0x6, imm, rs2, 0x2);
}
+/* RVZACAS instructions. */
+static inline u32 rvzacas_amocas_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+{
+ return rv_amo_insn(0x5, aq, rl, rs2, rs1, 2, rd, 0x2f);
+}
+
+static inline u32 rvzacas_amocas_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+{
+ return rv_amo_insn(0x5, aq, rl, rs2, rs1, 3, rd, 0x2f);
+}
+
/* RVZBA instructions. */
static inline u32 rvzba_sh2add(u8 rd, u8 rs1, u8 rs2)
{
@@ -1123,7 +1130,7 @@ static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
{
- if (rvzba_enabled()) {
+ if (rv_ext_enabled(ZBA)) {
emit(rvzba_sh2add(rd, rs1, rs2), ctx);
return;
}
@@ -1134,7 +1141,7 @@ static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx
static inline void emit_sh3add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
{
- if (rvzba_enabled()) {
+ if (rv_ext_enabled(ZBA)) {
emit(rvzba_sh3add(rd, rs1, rs2), ctx);
return;
}
@@ -1184,7 +1191,7 @@ static inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
static inline void emit_sextb(u8 rd, u8 rs, struct rv_jit_context *ctx)
{
- if (rvzbb_enabled()) {
+ if (rv_ext_enabled(ZBB)) {
emit(rvzbb_sextb(rd, rs), ctx);
return;
}
@@ -1195,7 +1202,7 @@ static inline void emit_sextb(u8 rd, u8 rs, struct rv_jit_context *ctx)
static inline void emit_sexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
{
- if (rvzbb_enabled()) {
+ if (rv_ext_enabled(ZBB)) {
emit(rvzbb_sexth(rd, rs), ctx);
return;
}
@@ -1211,7 +1218,7 @@ static inline void emit_sextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
static inline void emit_zexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
{
- if (rvzbb_enabled()) {
+ if (rv_ext_enabled(ZBB)) {
emit(rvzbb_zexth(rd, rs), ctx);
return;
}
@@ -1222,7 +1229,7 @@ static inline void emit_zexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
static inline void emit_zextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
{
- if (rvzba_enabled()) {
+ if (rv_ext_enabled(ZBA)) {
emit(rvzba_zextw(rd, rs), ctx);
return;
}
@@ -1233,7 +1240,7 @@ static inline void emit_zextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
static inline void emit_bswap(u8 rd, s32 imm, struct rv_jit_context *ctx)
{
- if (rvzbb_enabled()) {
+ if (rv_ext_enabled(ZBB)) {
int bits = 64 - imm;
emit(rvzbb_rev8(rd, rd), ctx);
@@ -1289,6 +1296,35 @@ out_be:
emit_mv(rd, RV_REG_T2, ctx);
}
+static inline void emit_cmpxchg(u8 rd, u8 rs, u8 r0, bool is64, struct rv_jit_context *ctx)
+{
+ int jmp_offset;
+
+ if (rv_ext_enabled(ZACAS)) {
+ ctx->ex_insn_off = ctx->ninsns;
+ emit(is64 ? rvzacas_amocas_d(r0, rs, rd, 1, 1) :
+ rvzacas_amocas_w(r0, rs, rd, 1, 1), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
+ if (!is64)
+ emit_zextw(r0, r0, ctx);
+ return;
+ }
+
+ if (is64)
+ emit_mv(RV_REG_T2, r0, ctx);
+ else
+ emit_addiw(RV_REG_T2, r0, 0, ctx);
+ emit(is64 ? rv_lr_d(r0, 0, rd, 0, 0) :
+ rv_lr_w(r0, 0, rd, 0, 0), ctx);
+ jmp_offset = ninsns_rvoff(8);
+ emit(rv_bne(RV_REG_T2, r0, jmp_offset >> 1), ctx);
+ emit(is64 ? rv_sc_d(RV_REG_T3, rs, rd, 0, 1) :
+ rv_sc_w(RV_REG_T3, rs, rd, 0, 1), ctx);
+ jmp_offset = ninsns_rvoff(-6);
+ emit(rv_bne(RV_REG_T3, 0, jmp_offset >> 1), ctx);
+ emit_fence_rw_rw(ctx);
+}
+
#endif /* __riscv_xlen == 64 */
void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog);
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 9883a55d61b5..45cbc7c6fe49 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -18,7 +18,7 @@
#define RV_MAX_REG_ARGS 8
#define RV_FENTRY_NINSNS 2
#define RV_FENTRY_NBYTES (RV_FENTRY_NINSNS * 4)
-#define RV_KCFI_NINSNS (IS_ENABLED(CONFIG_CFI_CLANG) ? 1 : 0)
+#define RV_KCFI_NINSNS (IS_ENABLED(CONFIG_CFI) ? 1 : 0)
/* imm that allows emit_imm to emit max count insns */
#define RV_MAX_COUNT_IMM 0x7FFF7FF7FF7FF7FF
@@ -469,142 +469,96 @@ static int emit_call(u64 addr, bool fixed_addr, struct rv_jit_context *ctx)
static inline void emit_kcfi(u32 hash, struct rv_jit_context *ctx)
{
- if (IS_ENABLED(CONFIG_CFI_CLANG))
+ if (IS_ENABLED(CONFIG_CFI))
emit(hash, ctx);
}
-static int emit_load_8(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+static void emit_ldx_insn(u8 rd, s16 off, u8 rs, u8 size, bool sign_ext,
+ struct rv_jit_context *ctx)
{
- int insns_start;
-
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lb(rd, off, rs), ctx);
- else
- emit(rv_lbu(rd, off, rs), ctx);
- return ctx->ninsns - insns_start;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lb(rd, 0, RV_REG_T1), ctx);
- else
- emit(rv_lbu(rd, 0, RV_REG_T1), ctx);
- return ctx->ninsns - insns_start;
-}
-
-static int emit_load_16(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
-{
- int insns_start;
-
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lh(rd, off, rs), ctx);
- else
- emit(rv_lhu(rd, off, rs), ctx);
- return ctx->ninsns - insns_start;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lh(rd, 0, RV_REG_T1), ctx);
- else
- emit(rv_lhu(rd, 0, RV_REG_T1), ctx);
- return ctx->ninsns - insns_start;
-}
-
-static int emit_load_32(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
-{
- int insns_start;
-
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lw(rd, off, rs), ctx);
- else
- emit(rv_lwu(rd, off, rs), ctx);
- return ctx->ninsns - insns_start;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
- insns_start = ctx->ninsns;
- if (sign_ext)
- emit(rv_lw(rd, 0, RV_REG_T1), ctx);
- else
- emit(rv_lwu(rd, 0, RV_REG_T1), ctx);
- return ctx->ninsns - insns_start;
-}
-
-static int emit_load_64(bool sign_ext, u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
-{
- int insns_start;
-
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
+ switch (size) {
+ case BPF_B:
+ emit(sign_ext ? rv_lb(rd, off, rs) : rv_lbu(rd, off, rs), ctx);
+ break;
+ case BPF_H:
+ emit(sign_ext ? rv_lh(rd, off, rs) : rv_lhu(rd, off, rs), ctx);
+ break;
+ case BPF_W:
+ emit(sign_ext ? rv_lw(rd, off, rs) : rv_lwu(rd, off, rs), ctx);
+ break;
+ case BPF_DW:
emit_ld(rd, off, rs, ctx);
- return ctx->ninsns - insns_start;
+ break;
}
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
- insns_start = ctx->ninsns;
- emit_ld(rd, 0, RV_REG_T1, ctx);
- return ctx->ninsns - insns_start;
}
-static void emit_store_8(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+static void emit_stx_insn(u8 rd, s16 off, u8 rs, u8 size, struct rv_jit_context *ctx)
{
- if (is_12b_int(off)) {
+ switch (size) {
+ case BPF_B:
emit(rv_sb(rd, off, rs), ctx);
- return;
+ break;
+ case BPF_H:
+ emit(rv_sh(rd, off, rs), ctx);
+ break;
+ case BPF_W:
+ emit_sw(rd, off, rs, ctx);
+ break;
+ case BPF_DW:
+ emit_sd(rd, off, rs, ctx);
+ break;
}
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit(rv_sb(RV_REG_T1, 0, rs), ctx);
}
-static void emit_store_16(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+static void emit_ldx(u8 rd, s16 off, u8 rs, u8 size, bool sign_ext,
+ struct rv_jit_context *ctx)
{
if (is_12b_int(off)) {
- emit(rv_sh(rd, off, rs), ctx);
+ ctx->ex_insn_off = ctx->ninsns;
+ emit_ldx_insn(rd, off, rs, size, sign_ext, ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
return;
}
emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit(rv_sh(RV_REG_T1, 0, rs), ctx);
+ emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ ctx->ex_insn_off = ctx->ninsns;
+ emit_ldx_insn(rd, 0, RV_REG_T1, size, sign_ext, ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
}
-static void emit_store_32(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+static void emit_st(u8 rd, s16 off, s32 imm, u8 size, struct rv_jit_context *ctx)
{
+ emit_imm(RV_REG_T1, imm, ctx);
if (is_12b_int(off)) {
- emit_sw(rd, off, rs, ctx);
+ ctx->ex_insn_off = ctx->ninsns;
+ emit_stx_insn(rd, off, RV_REG_T1, size, ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
return;
}
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit_sw(RV_REG_T1, 0, rs, ctx);
+ emit_imm(RV_REG_T2, off, ctx);
+ emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ ctx->ex_insn_off = ctx->ninsns;
+ emit_stx_insn(RV_REG_T2, 0, RV_REG_T1, size, ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
}
-static void emit_store_64(u8 rd, s32 off, u8 rs, struct rv_jit_context *ctx)
+static void emit_stx(u8 rd, s16 off, u8 rs, u8 size, struct rv_jit_context *ctx)
{
if (is_12b_int(off)) {
- emit_sd(rd, off, rs, ctx);
+ ctx->ex_insn_off = ctx->ninsns;
+ emit_stx_insn(rd, off, rs, size, ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
return;
}
emit_imm(RV_REG_T1, off, ctx);
emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- emit_sd(RV_REG_T1, 0, rs, ctx);
+ ctx->ex_insn_off = ctx->ninsns;
+ emit_stx_insn(RV_REG_T1, 0, rs, size, ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
}
static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
@@ -617,20 +571,12 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
switch (imm) {
/* dst_reg = load_acquire(src_reg + off16) */
case BPF_LOAD_ACQ:
- switch (BPF_SIZE(code)) {
- case BPF_B:
- emit_load_8(false, rd, off, rs, ctx);
- break;
- case BPF_H:
- emit_load_16(false, rd, off, rs, ctx);
- break;
- case BPF_W:
- emit_load_32(false, rd, off, rs, ctx);
- break;
- case BPF_DW:
- emit_load_64(false, rd, off, rs, ctx);
- break;
+ if (BPF_MODE(code) == BPF_PROBE_ATOMIC) {
+ emit_add(RV_REG_T2, rs, RV_REG_ARENA, ctx);
+ rs = RV_REG_T2;
}
+
+ emit_ldx(rd, off, rs, BPF_SIZE(code), false, ctx);
emit_fence_r_rw(ctx);
/* If our next insn is a redundant zext, return 1 to tell
@@ -641,21 +587,13 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
break;
/* store_release(dst_reg + off16, src_reg) */
case BPF_STORE_REL:
- emit_fence_rw_w(ctx);
- switch (BPF_SIZE(code)) {
- case BPF_B:
- emit_store_8(rd, off, rs, ctx);
- break;
- case BPF_H:
- emit_store_16(rd, off, rs, ctx);
- break;
- case BPF_W:
- emit_store_32(rd, off, rs, ctx);
- break;
- case BPF_DW:
- emit_store_64(rd, off, rs, ctx);
- break;
+ if (BPF_MODE(code) == BPF_PROBE_ATOMIC) {
+ emit_add(RV_REG_T2, rd, RV_REG_ARENA, ctx);
+ rd = RV_REG_T2;
}
+
+ emit_fence_rw_w(ctx);
+ emit_stx(rd, off, rs, BPF_SIZE(code), ctx);
break;
default:
pr_err_once("bpf-jit: invalid atomic load/store opcode %02x\n", imm);
@@ -668,17 +606,15 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
struct rv_jit_context *ctx)
{
- u8 r0, code = insn->code;
+ u8 code = insn->code;
s16 off = insn->off;
s32 imm = insn->imm;
- int jmp_offset;
- bool is64;
+ bool is64 = BPF_SIZE(code) == BPF_DW;
if (BPF_SIZE(code) != BPF_W && BPF_SIZE(code) != BPF_DW) {
pr_err_once("bpf-jit: 1- and 2-byte RMW atomics are not supported\n");
return -EINVAL;
}
- is64 = BPF_SIZE(code) == BPF_DW;
if (off) {
if (is_12b_int(off)) {
@@ -690,72 +626,82 @@ static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
rd = RV_REG_T1;
}
+ if (BPF_MODE(code) == BPF_PROBE_ATOMIC) {
+ emit_add(RV_REG_T1, rd, RV_REG_ARENA, ctx);
+ rd = RV_REG_T1;
+ }
+
switch (imm) {
/* lock *(u32/u64 *)(dst_reg + off16) <op>= src_reg */
case BPF_ADD:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoadd_d(RV_REG_ZERO, rs, rd, 0, 0) :
rv_amoadd_w(RV_REG_ZERO, rs, rd, 0, 0), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
break;
case BPF_AND:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoand_d(RV_REG_ZERO, rs, rd, 0, 0) :
rv_amoand_w(RV_REG_ZERO, rs, rd, 0, 0), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
break;
case BPF_OR:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoor_d(RV_REG_ZERO, rs, rd, 0, 0) :
rv_amoor_w(RV_REG_ZERO, rs, rd, 0, 0), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
break;
case BPF_XOR:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoxor_d(RV_REG_ZERO, rs, rd, 0, 0) :
rv_amoxor_w(RV_REG_ZERO, rs, rd, 0, 0), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
break;
/* src_reg = atomic_fetch_<op>(dst_reg + off16, src_reg) */
case BPF_ADD | BPF_FETCH:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoadd_d(rs, rs, rd, 1, 1) :
rv_amoadd_w(rs, rs, rd, 1, 1), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
if (!is64)
emit_zextw(rs, rs, ctx);
break;
case BPF_AND | BPF_FETCH:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoand_d(rs, rs, rd, 1, 1) :
rv_amoand_w(rs, rs, rd, 1, 1), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
if (!is64)
emit_zextw(rs, rs, ctx);
break;
case BPF_OR | BPF_FETCH:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoor_d(rs, rs, rd, 1, 1) :
rv_amoor_w(rs, rs, rd, 1, 1), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
if (!is64)
emit_zextw(rs, rs, ctx);
break;
case BPF_XOR | BPF_FETCH:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoxor_d(rs, rs, rd, 1, 1) :
rv_amoxor_w(rs, rs, rd, 1, 1), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
if (!is64)
emit_zextw(rs, rs, ctx);
break;
/* src_reg = atomic_xchg(dst_reg + off16, src_reg); */
case BPF_XCHG:
+ ctx->ex_insn_off = ctx->ninsns;
emit(is64 ? rv_amoswap_d(rs, rs, rd, 1, 1) :
rv_amoswap_w(rs, rs, rd, 1, 1), ctx);
+ ctx->ex_jmp_off = ctx->ninsns;
if (!is64)
emit_zextw(rs, rs, ctx);
break;
/* r0 = atomic_cmpxchg(dst_reg + off16, r0, src_reg); */
case BPF_CMPXCHG:
- r0 = bpf_to_rv_reg(BPF_REG_0, ctx);
- if (is64)
- emit_mv(RV_REG_T2, r0, ctx);
- else
- emit_addiw(RV_REG_T2, r0, 0, ctx);
- emit(is64 ? rv_lr_d(r0, 0, rd, 0, 0) :
- rv_lr_w(r0, 0, rd, 0, 0), ctx);
- jmp_offset = ninsns_rvoff(8);
- emit(rv_bne(RV_REG_T2, r0, jmp_offset >> 1), ctx);
- emit(is64 ? rv_sc_d(RV_REG_T3, rs, rd, 0, 1) :
- rv_sc_w(RV_REG_T3, rs, rd, 0, 1), ctx);
- jmp_offset = ninsns_rvoff(-6);
- emit(rv_bne(RV_REG_T3, 0, jmp_offset >> 1), ctx);
- emit_fence_rw_rw(ctx);
+ emit_cmpxchg(rd, rs, regmap[BPF_REG_0], is64, ctx);
break;
default:
pr_err_once("bpf-jit: invalid atomic RMW opcode %02x\n", imm);
@@ -765,6 +711,39 @@ static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
return 0;
}
+/*
+ * Sign-extend the register if necessary
+ */
+static int sign_extend(u8 rd, u8 rs, u8 sz, bool sign, struct rv_jit_context *ctx)
+{
+ if (!sign && (sz == 1 || sz == 2)) {
+ if (rd != rs)
+ emit_mv(rd, rs, ctx);
+ return 0;
+ }
+
+ switch (sz) {
+ case 1:
+ emit_sextb(rd, rs, ctx);
+ break;
+ case 2:
+ emit_sexth(rd, rs, ctx);
+ break;
+ case 4:
+ emit_sextw(rd, rs, ctx);
+ break;
+ case 8:
+ if (rd != rs)
+ emit_mv(rd, rs, ctx);
+ break;
+ default:
+ pr_err("bpf-jit: invalid size %d for sign_extend\n", sz);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
#define REG_DONT_CLEAR_MARKER 0 /* RV_REG_ZERO unused in pt_regmap */
@@ -783,9 +762,8 @@ bool ex_handler_bpf(const struct exception_table_entry *ex,
}
/* For accesses to BTF pointers, add an entry to the exception table */
-static int add_exception_handler(const struct bpf_insn *insn,
- struct rv_jit_context *ctx,
- int dst_reg, int insn_len)
+static int add_exception_handler(const struct bpf_insn *insn, int dst_reg,
+ struct rv_jit_context *ctx)
{
struct exception_table_entry *ex;
unsigned long pc;
@@ -793,21 +771,23 @@ static int add_exception_handler(const struct bpf_insn *insn,
off_t fixup_offset;
if (!ctx->insns || !ctx->ro_insns || !ctx->prog->aux->extable ||
- (BPF_MODE(insn->code) != BPF_PROBE_MEM && BPF_MODE(insn->code) != BPF_PROBE_MEMSX &&
- BPF_MODE(insn->code) != BPF_PROBE_MEM32))
+ ctx->ex_insn_off <= 0 || ctx->ex_jmp_off <= 0)
return 0;
- if (WARN_ON_ONCE(ctx->nexentries >= ctx->prog->aux->num_exentries))
- return -EINVAL;
+ if (BPF_MODE(insn->code) != BPF_PROBE_MEM &&
+ BPF_MODE(insn->code) != BPF_PROBE_MEMSX &&
+ BPF_MODE(insn->code) != BPF_PROBE_MEM32 &&
+ BPF_MODE(insn->code) != BPF_PROBE_ATOMIC)
+ return 0;
- if (WARN_ON_ONCE(insn_len > ctx->ninsns))
+ if (WARN_ON_ONCE(ctx->nexentries >= ctx->prog->aux->num_exentries))
return -EINVAL;
- if (WARN_ON_ONCE(!rvc_enabled() && insn_len == 1))
+ if (WARN_ON_ONCE(ctx->ex_insn_off > ctx->ninsns || ctx->ex_jmp_off > ctx->ninsns))
return -EINVAL;
ex = &ctx->prog->aux->extable[ctx->nexentries];
- pc = (unsigned long)&ctx->ro_insns[ctx->ninsns - insn_len];
+ pc = (unsigned long)&ctx->ro_insns[ctx->ex_insn_off];
/*
* This is the relative offset of the instruction that may fault from
@@ -831,7 +811,7 @@ static int add_exception_handler(const struct bpf_insn *insn,
* that may fault. The execution will jump to this after handling the
* fault.
*/
- fixup_offset = (long)&ex->fixup - (pc + insn_len * sizeof(u16));
+ fixup_offset = (long)&ex->fixup - (long)&ctx->ro_insns[ctx->ex_jmp_off];
if (!FIELD_FIT(BPF_FIXUP_OFFSET_MASK, fixup_offset))
return -ERANGE;
@@ -848,6 +828,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
FIELD_PREP(BPF_FIXUP_REG_MASK, dst_reg);
ex->type = EX_TYPE_BPF;
+ ctx->ex_insn_off = 0;
+ ctx->ex_jmp_off = 0;
ctx->nexentries++;
return 0;
}
@@ -1079,10 +1061,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
stack_size += 16;
save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
- if (save_ret) {
+ if (save_ret)
stack_size += 16; /* Save both A5 (BPF R0) and A0 */
- retval_off = stack_size;
- }
+ retval_off = stack_size;
stack_size += nr_arg_slots * 8;
args_off = stack_size;
@@ -1226,8 +1207,15 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
restore_args(min_t(int, nr_arg_slots, RV_MAX_REG_ARGS), args_off, ctx);
if (save_ret) {
- emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx);
emit_ld(regmap[BPF_REG_0], -(retval_off - 8), RV_REG_FP, ctx);
+ if (is_struct_ops) {
+ ret = sign_extend(RV_REG_A0, regmap[BPF_REG_0], m->ret_size,
+ m->ret_flags & BTF_FMODEL_SIGNED_ARG, ctx);
+ if (ret)
+ goto out;
+ } else {
+ emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx);
+ }
}
emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx);
@@ -1320,7 +1308,6 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image,
goto out;
}
- bpf_flush_icache(ro_image, ro_image_end);
out:
kvfree(image);
return ret < 0 ? ret : size;
@@ -1857,7 +1844,6 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_LDX | BPF_PROBE_MEM32 | BPF_DW:
{
bool sign_ext;
- int insn_len;
sign_ext = BPF_MODE(insn->code) == BPF_MEMSX ||
BPF_MODE(insn->code) == BPF_PROBE_MEMSX;
@@ -1867,22 +1853,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
rs = RV_REG_T2;
}
- switch (BPF_SIZE(code)) {
- case BPF_B:
- insn_len = emit_load_8(sign_ext, rd, off, rs, ctx);
- break;
- case BPF_H:
- insn_len = emit_load_16(sign_ext, rd, off, rs, ctx);
- break;
- case BPF_W:
- insn_len = emit_load_32(sign_ext, rd, off, rs, ctx);
- break;
- case BPF_DW:
- insn_len = emit_load_64(sign_ext, rd, off, rs, ctx);
- break;
- }
+ emit_ldx(rd, off, rs, BPF_SIZE(code), sign_ext, ctx);
- ret = add_exception_handler(insn, ctx, rd, insn_len);
+ ret = add_exception_handler(insn, rd, ctx);
if (ret)
return ret;
@@ -1890,238 +1863,73 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
return 1;
break;
}
+
/* speculation barrier */
case BPF_ST | BPF_NOSPEC:
break;
/* ST: *(size *)(dst + off) = imm */
case BPF_ST | BPF_MEM | BPF_B:
- emit_imm(RV_REG_T1, imm, ctx);
- if (is_12b_int(off)) {
- emit(rv_sb(rd, off, RV_REG_T1), ctx);
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
- break;
-
case BPF_ST | BPF_MEM | BPF_H:
- emit_imm(RV_REG_T1, imm, ctx);
- if (is_12b_int(off)) {
- emit(rv_sh(rd, off, RV_REG_T1), ctx);
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
- break;
case BPF_ST | BPF_MEM | BPF_W:
- emit_imm(RV_REG_T1, imm, ctx);
- if (is_12b_int(off)) {
- emit_sw(rd, off, RV_REG_T1, ctx);
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
- break;
case BPF_ST | BPF_MEM | BPF_DW:
- emit_imm(RV_REG_T1, imm, ctx);
- if (is_12b_int(off)) {
- emit_sd(rd, off, RV_REG_T1, ctx);
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
- break;
-
+ /* ST | PROBE_MEM32: *(size *)(dst + RV_REG_ARENA + off) = imm */
case BPF_ST | BPF_PROBE_MEM32 | BPF_B:
case BPF_ST | BPF_PROBE_MEM32 | BPF_H:
case BPF_ST | BPF_PROBE_MEM32 | BPF_W:
case BPF_ST | BPF_PROBE_MEM32 | BPF_DW:
- {
- int insn_len, insns_start;
-
- emit_add(RV_REG_T3, rd, RV_REG_ARENA, ctx);
- rd = RV_REG_T3;
-
- /* Load imm to a register then store it */
- emit_imm(RV_REG_T1, imm, ctx);
-
- switch (BPF_SIZE(code)) {
- case BPF_B:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit(rv_sb(rd, off, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- insns_start = ctx->ninsns;
- emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- case BPF_H:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit(rv_sh(rd, off, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- insns_start = ctx->ninsns;
- emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- case BPF_W:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit_sw(rd, off, RV_REG_T1, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- insns_start = ctx->ninsns;
- emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- case BPF_DW:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit_sd(rd, off, RV_REG_T1, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T2, off, ctx);
- emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
- insns_start = ctx->ninsns;
- emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
+ if (BPF_MODE(insn->code) == BPF_PROBE_MEM32) {
+ emit_add(RV_REG_T3, rd, RV_REG_ARENA, ctx);
+ rd = RV_REG_T3;
}
- ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
- insn_len);
+ emit_st(rd, off, imm, BPF_SIZE(code), ctx);
+
+ ret = add_exception_handler(insn, REG_DONT_CLEAR_MARKER, ctx);
if (ret)
return ret;
-
break;
- }
/* STX: *(size *)(dst + off) = src */
case BPF_STX | BPF_MEM | BPF_B:
- emit_store_8(rd, off, rs, ctx);
- break;
case BPF_STX | BPF_MEM | BPF_H:
- emit_store_16(rd, off, rs, ctx);
- break;
case BPF_STX | BPF_MEM | BPF_W:
- emit_store_32(rd, off, rs, ctx);
- break;
case BPF_STX | BPF_MEM | BPF_DW:
- emit_store_64(rd, off, rs, ctx);
+ /* STX | PROBE_MEM32: *(size *)(dst + RV_REG_ARENA + off) = src */
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_H:
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_W:
+ case BPF_STX | BPF_PROBE_MEM32 | BPF_DW:
+ if (BPF_MODE(insn->code) == BPF_PROBE_MEM32) {
+ emit_add(RV_REG_T2, rd, RV_REG_ARENA, ctx);
+ rd = RV_REG_T2;
+ }
+
+ emit_stx(rd, off, rs, BPF_SIZE(code), ctx);
+
+ ret = add_exception_handler(insn, REG_DONT_CLEAR_MARKER, ctx);
+ if (ret)
+ return ret;
break;
+
+ /* Atomics */
case BPF_STX | BPF_ATOMIC | BPF_B:
case BPF_STX | BPF_ATOMIC | BPF_H:
case BPF_STX | BPF_ATOMIC | BPF_W:
case BPF_STX | BPF_ATOMIC | BPF_DW:
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
if (bpf_atomic_is_load_store(insn))
ret = emit_atomic_ld_st(rd, rs, insn, ctx);
else
ret = emit_atomic_rmw(rd, rs, insn, ctx);
- if (ret)
- return ret;
- break;
- case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
- case BPF_STX | BPF_PROBE_MEM32 | BPF_H:
- case BPF_STX | BPF_PROBE_MEM32 | BPF_W:
- case BPF_STX | BPF_PROBE_MEM32 | BPF_DW:
- {
- int insn_len, insns_start;
-
- emit_add(RV_REG_T2, rd, RV_REG_ARENA, ctx);
- rd = RV_REG_T2;
-
- switch (BPF_SIZE(code)) {
- case BPF_B:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit(rv_sb(rd, off, rs), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- insns_start = ctx->ninsns;
- emit(rv_sb(RV_REG_T1, 0, rs), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- case BPF_H:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit(rv_sh(rd, off, rs), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- insns_start = ctx->ninsns;
- emit(rv_sh(RV_REG_T1, 0, rs), ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- case BPF_W:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit_sw(rd, off, rs, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- insns_start = ctx->ninsns;
- emit_sw(RV_REG_T1, 0, rs, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- case BPF_DW:
- if (is_12b_int(off)) {
- insns_start = ctx->ninsns;
- emit_sd(rd, off, rs, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- emit_imm(RV_REG_T1, off, ctx);
- emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
- insns_start = ctx->ninsns;
- emit_sd(RV_REG_T1, 0, rs, ctx);
- insn_len = ctx->ninsns - insns_start;
- break;
- }
-
- ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
- insn_len);
+ ret = ret ?: add_exception_handler(insn, REG_DONT_CLEAR_MARKER, ctx);
if (ret)
return ret;
-
break;
- }
default:
pr_err("bpf-jit: unknown opcode %02x\n", code);
@@ -2249,6 +2057,25 @@ bool bpf_jit_supports_arena(void)
return true;
}
+bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
+{
+ if (in_arena) {
+ switch (insn->code) {
+ case BPF_STX | BPF_ATOMIC | BPF_W:
+ case BPF_STX | BPF_ATOMIC | BPF_DW:
+ if (insn->imm == BPF_CMPXCHG)
+ return rv_ext_enabled(ZACAS);
+ break;
+ case BPF_LDX | BPF_MEMSX | BPF_B:
+ case BPF_LDX | BPF_MEMSX | BPF_H:
+ case BPF_LDX | BPF_MEMSX | BPF_W:
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool bpf_jit_supports_percpu_insn(void)
{
return true;
diff --git a/arch/riscv/purgatory/Makefile b/arch/riscv/purgatory/Makefile
index 240592e3f5c2..530e497ca2f9 100644
--- a/arch/riscv/purgatory/Makefile
+++ b/arch/riscv/purgatory/Makefile
@@ -71,7 +71,7 @@ ifdef CONFIG_STACKPROTECTOR_STRONG
PURGATORY_CFLAGS_REMOVE += -fstack-protector-strong
endif
-ifdef CONFIG_CFI_CLANG
+ifdef CONFIG_CFI
PURGATORY_CFLAGS_REMOVE += $(CC_FLAGS_CFI)
endif