RISC-V updates for v7.4

- Add support for crash hotplug
 
 - Improve user copy performance on cores with fast misaligned
   accesses
 
 - Optimize code paths involving pgtable_l{4,5}_enabled() by patching
   in the return values during early boot (since these don't change
   during runtime), or by specifying the return values directly in
   Kconfig files (for purpose-built kernels)
 
 - Change the PCIe bus reassignment behavior to depend on the
   PCI_REASSIGN_ALL_BUS PCI flag (as ARM64 does)
 
 - Avoid an unnecessary sstatus CSR read during context switch
 
 - Make the sbi_ecall() macro variadic, improving code clarity
 
 - Refactor __switch_to_vector() to prepare for upcoming vector context
   switch optimizations
 
 - Add a kselftest for vectorized user copy
 
 - Add bounds checking on the shadow stack restore token address to
   avoid it being used as an attack vector
 
 - Fix the shadow stack and indirect branch landing pad control functions to
   only update the CPU's envcfg CSR when operating on the current task
 
 - For MIPS RISC-V systems, add support for early boot-applied errata;
   and for P8700 RISC-V systems, avoid WFI usage in the kernel (since
   it is buggy)
 
 - Add the "B" RISC-V ISA extension to hwcap and hwprobe reporting
 
 - Add support for specifying and reporting the "Zic64b" RISC-V ISA
   extension, and add it to the SpacemiT K1, K3, and Sophgo SG2044 DT
   files
 
 - Require the block size of cache management operations to be
   specified in DT schema validation for the RISC-V ISA extensions
   Zicbom, Zicbop, and Zicboz
 
 - Some miscellaneous fixes: fix an incorrect bitfield width in the
   RVG_SYSTEM_CSR_MASK bitmask macro; make RISCV_ALTERNATIVE mandatory,
   now that XIP kernel support has been removed; and remove some
   unnecessary includes in kernel/smp.c
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEElRDoIDdEz9/svf2Kx4+xDQu9KksFAmrivM8ACgkQx4+xDQu9
 KkubQw//ann5hPn4CqJh4UjYlhbHM4QxaVpYs6i9fTGdyw1R+JcWxglcAuCkuEHl
 At5BFt2aR5y1FQwJqbVUYI0nxJCVCQNPf+6aormHtWnCrxM+9e5jE4Wqhae9BDpB
 yUNjRixJVU2Fz8O4WTeJBYsPaOguZXLNltlt5Oi14Zw85hCOX71bSkrORToY3CfQ
 L3FLe1gvGfeZyr6jj3c5RkcLHW01zrR0H3/dOcy8T+rEfVLHp90/fUufZPnrW5rj
 fIlbDRpQ5ZRlYr5hZ8X+U6Zs6qThGV5LX00wPghrfzdCiD6X7EnYNtmMaTV9aLlS
 UZSNrOCHf8lwogvwxYhdQuO+6F72Vj38Y/3CYjwi1+1FuukDlT2mejsXXU3JN8T/
 8tCY7zAB0KpTDK1N2Udr+zDXKCQuZ7YYpQJ9UxKjMAn7NwZKB4PmUjfXfSIsKLps
 FtzGWa8OM8a5GagpSHewA5c/SVLlkmrlE/0/GtzA4DfVMJyNt37OUWfEogXT7A8A
 9neAIgG8K1Dhq8U20scDmDKyZHobOX7+nsVohUiduZgfSgL2P/qHuWhkjNeACliK
 FhJcwtGITsF/lrUUBBoAnSYjZwkytaoOwA8eSnNRRxrfzYCgQWCxyYcXqMKI2KyK
 FQQlKbEm8eML88f+E9W0t6QqeFMtq6h8GXU8+B0TvrVz0DGfoH0=
 =Vdpl
 -----END PGP SIGNATURE-----

Merge tag 'riscv-for-linus-7.4-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V updates from Paul Walmsley:

 - Add support for crash hotplug

 - Improve user copy performance on cores with fast misaligned accesses

 - Optimize code paths involving pgtable_l{4,5}_enabled() by patching in
   the return values during early boot (since these don't change during
   runtime), or by specifying the return values directly in Kconfig
   files (for purpose-built kernels)

 - Change the PCIe bus reassignment behavior to depend on the
   PCI_REASSIGN_ALL_BUS PCI flag (as ARM64 does)

 - Avoid an unnecessary sstatus CSR read during context switch

 - Make the sbi_ecall() macro variadic, improving code clarity

 - Refactor __switch_to_vector() to prepare for upcoming vector context
   switch optimizations

 - Add a kselftest for vectorized user copy

 - Add bounds checking on the shadow stack restore token address to
   avoid it being used as an attack vector

 - Fix the shadow stack and indirect branch landing pad control
   functions to only update the CPU's envcfg CSR when operating on the
   current task

 - For MIPS RISC-V systems, add support for early boot-applied errata;
   and for P8700 RISC-V systems, avoid WFI usage in the kernel (since it
   is buggy)

 - Add the "B" RISC-V ISA extension to hwcap and hwprobe reporting

 - Add support for specifying and reporting the "Zic64b" RISC-V ISA
   extension, and add it to the SpacemiT K1, K3, and Sophgo SG2044 DT
   files

 - Require the block size of cache management operations to be specified
   in DT schema validation for the RISC-V ISA extensions Zicbom, Zicbop,
   and Zicboz

 - Some miscellaneous fixes: fix an incorrect bitfield width in the
   RVG_SYSTEM_CSR_MASK bitmask macro; make RISCV_ALTERNATIVE mandatory,
   now that XIP kernel support has been removed; and remove some
   unnecessary includes in kernel/smp.c

* tag 'riscv-for-linus-7.4-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (28 commits)
  riscv: mm: unexport _pgtable_l4_enabled and _pgtable_l5_enabled
  riscv: introduce RISCV_ISA_SV48 and RISCV_ISA_SV57
  riscv: support early isa ext and use it to optimize pgtable_l4|l5_enabled
  riscv: convert pgtable_l4|l5_enabled to inline function
  riscv: remove RISCV_ALTERNATIVE Kconfig option
  riscv: Add a getter for user PMLEN support
  riscv: dts: sophgo: sg2044: Add Zic64b ISA extension
  riscv: dts: spacemit: k1: Add Zic64b ISA extension
  riscv: dts: spacemit: k3: Add Zic64b ISA extension
  riscv: Add Zic64b to cpufeature and hwprobe
  dt-bindings: riscv: Add Zic64b extension description
  dt-bindings: riscv: Require block-size for Zicbom, Zicbop, and Zicboz
  riscv: Add B to hwcap and hwprobe
  riscv: remove unused profile.h includes
  riscv: cfi: Only write envcfg CSR when task is current
  riscv: cfi: Bounds check restore token before swap
  riscv: Add ERRATA_MIPS_P8700_WFI to replace WFI with mips.pause
  selftest: riscv: test vectorized user copy
  riscv: vector: refactor context switch for kernel-mode vector
  riscv: do not read csr in vector context switch
  ...
This commit is contained in:
Linus Torvalds 2026-10-29 12:33:25 -10:00
commit 1b8b675037
58 changed files with 1171 additions and 486 deletions

View File

@ -423,3 +423,11 @@ The following keys are defined:
* :c:macro:`RISCV_HWPROBE_EXT_ZA64RS`: The Za64rs extension is supported,
as defined in the RISC-V Profiles specification starting from commit
b1d80660 ("Updated to ratified state.")
* :c:macro:`RISCV_HWPROBE_EXT_B`: The B extension is supported, as defined
in version 1.0 of the Bit-Manipulation ISA extensions, and implies the
presence of the Zba, Zbb, and Zbs sub-extensions.
* :c:macro:`RISCV_HWPROBE_EXT_ZIC64B`: The Zic64b extension is supported,
as defined in the RISC-V Profiles specification starting from commit
b1d80660 ("Updated to ratified state.")

View File

@ -537,6 +537,12 @@ properties:
in commit 64074bc ("Update version numbers for Zfh/Zfinx") of
riscv-isa-manual.
- const: zic64b
description:
The standard Zic64b extension for 64-byte naturally aligned cache
blocks, as ratified in RISC-V Profiles Version 1.0, with commit
b1d806605f87 ("Updated to ratified state.")
- const: zicbom
description:
The standard Zicbom extension for base cache management operations as
@ -1211,6 +1217,54 @@ allOf:
not:
contains:
const: zilsd
# Zic64b mandates 64-byte naturally aligned cache blocks
- if:
properties:
riscv,isa-extensions:
contains:
const: zic64b
required:
- riscv,isa-extensions
then:
properties:
riscv,cbom-block-size:
const: 64
riscv,cbop-block-size:
const: 64
riscv,cboz-block-size:
const: 64
# All three Zicbo* extensions require their block size property as there's no
# default.
- if:
properties:
riscv,isa-extensions:
contains:
const: zicbom
required:
- riscv,isa-extensions
then:
required:
- riscv,cbom-block-size
- if:
properties:
riscv,isa-extensions:
contains:
const: zicbop
required:
- riscv,isa-extensions
then:
required:
- riscv,cbop-block-size
- if:
properties:
riscv,isa-extensions:
contains:
const: zicboz
required:
- riscv,isa-extensions
then:
required:
- riscv,cboz-block-size
additionalProperties: true
...

View File

@ -215,7 +215,7 @@ config RISCV
select PCI_ECAM if (ACPI && PCI)
select PCI_MSI if PCI
select RELOCATABLE if !MMU && !PHYS_RAM_BASE_FIXED
select RISCV_ALTERNATIVE
select RISCV_ALTERNATIVE_EARLY if 64BIT
select RISCV_APLIC
select RISCV_IMSIC
select RISCV_INTC
@ -537,17 +537,8 @@ config RISCV_COMBO_SPINLOCKS
endchoice
config RISCV_ALTERNATIVE
bool
help
This Kconfig allows the kernel to automatically patch the
erratum or cpufeature required by the execution platform at run
time. The code patching overhead is minimal, as it's only done
once at boot and once on each module load.
config RISCV_ALTERNATIVE_EARLY
bool
depends on RISCV_ALTERNATIVE
help
Allows early patching of the kernel for special errata
@ -576,7 +567,6 @@ config RISCV_ISA_SUPM
config RISCV_ISA_SVNAPOT
bool "Svnapot extension support for supervisor mode NAPOT pages"
depends on 64BIT && MMU
depends on RISCV_ALTERNATIVE
default y
help
Enable support for the Svnapot ISA-extension when it is detected
@ -610,10 +600,33 @@ config RISCV_ISA_SSQOSID
cache partitioning scheme and use the MCID to track how much
cache a process, or a group of processes, is using.
config RISCV_ISA_SV48
bool "Page-Based 48-bit Virtual-Memory System"
depends on 64BIT
default y
help
Add support for the Page-Based 48-bit Virtual-Memory System.
Enable this option for systems for which a 39-bit virtual address
space is insufficient. But if 39-bit is enough, disabling this
option will result in smaller kernel size and slighly better
performance.
config RISCV_ISA_SV57
bool "Page-Based 57-bit Virtual-Memory System"
depends on 64BIT
default y
help
Add support for the Page-Based 57-bit Virtual-Memory System.
Enable this option for systems for which a 48-bit virtual address
space is insufficient. But if 48-bit is enough, disabling this
option will result in smaller kernel size and slighly better
performance.
config RISCV_ISA_SVPBMT
bool "Svpbmt extension support for supervisor mode page-based memory types"
depends on 64BIT && MMU
depends on RISCV_ALTERNATIVE
default y
help
Add support for the Svpbmt ISA-extension (Supervisor-mode:
@ -683,7 +696,6 @@ config RISCV_ISA_V_PREEMPTIVE
config RISCV_ISA_ZAWRS
bool "Zawrs extension support for more efficient busy waiting"
depends on RISCV_ALTERNATIVE
default y
help
The Zawrs extension defines instructions to be used in polling loops
@ -702,7 +714,6 @@ config TOOLCHAIN_HAS_ZABHA
config RISCV_ISA_ZABHA
bool "Zabha extension support for atomic byte/halfword operations"
depends on TOOLCHAIN_HAS_ZABHA
depends on RISCV_ALTERNATIVE
default y
help
Enable the use of the Zabha ISA-extension to implement kernel
@ -719,7 +730,6 @@ config TOOLCHAIN_HAS_ZACAS
config RISCV_ISA_ZACAS
bool "Zacas extension support for atomic CAS"
depends on RISCV_ALTERNATIVE
default y
help
Enable the use of the Zacas ISA-extension to implement kernel atomic
@ -764,7 +774,6 @@ config RISCV_ISA_ZBA
config RISCV_ISA_ZBB
bool "Zbb extension support for bit manipulation instructions"
depends on RISCV_ALTERNATIVE
default y
help
Add support for enabling optimisations in the kernel when the
@ -789,7 +798,6 @@ config RISCV_ISA_ZBC
bool "Zbc extension support for carry-less multiplication instructions"
depends on TOOLCHAIN_HAS_ZBC
depends on MMU
depends on RISCV_ALTERNATIVE
default y
help
Adds support to dynamically detect the presence of the Zbc
@ -811,7 +819,6 @@ config TOOLCHAIN_HAS_ZBKB
config RISCV_ISA_ZBKB
bool "Zbkb extension support for bit manipulation instructions"
depends on TOOLCHAIN_HAS_ZBKB
depends on RISCV_ALTERNATIVE
default y
help
Adds support to dynamically detect the presence of the ZBKB
@ -825,7 +832,6 @@ config RISCV_ISA_ZBKB
config RISCV_ISA_ZICBOM
bool "Zicbom extension support for non-coherent DMA operation"
depends on MMU
depends on RISCV_ALTERNATIVE
default y
select RISCV_DMA_NONCOHERENT
select DMA_DIRECT_REMAP
@ -841,7 +847,6 @@ config RISCV_ISA_ZICBOM
config RISCV_ISA_ZICBOZ
bool "Zicboz extension support for faster zeroing of memory"
depends on RISCV_ALTERNATIVE
default y
help
Enable the use of the Zicboz extension (cbo.zero instruction)
@ -854,7 +859,6 @@ config RISCV_ISA_ZICBOZ
config RISCV_ISA_ZICBOP
bool "Zicbop extension support for cache block prefetch"
depends on MMU
depends on RISCV_ALTERNATIVE
default y
help
Adds support to dynamically detect the presence of the ZICBOP
@ -869,7 +873,6 @@ config RISCV_ISA_ZICBOP
config RISCV_ISA_SVRSW60T59B
bool "Svrsw60t59b extension support for using PTE bits 60 and 59"
depends on MMU && 64BIT
depends on RISCV_ALTERNATIVE
default y
help
Adds support to dynamically detect the presence of the Svrsw60t59b
@ -1131,6 +1134,9 @@ config ARCH_DEFAULT_CRASH_DUMP
config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
def_bool CRASH_RESERVE
config ARCH_SUPPORTS_CRASH_HOTPLUG
def_bool y
config COMPAT
bool "Kernel support for 32-bit U-mode"
default 64BIT
@ -1202,7 +1208,6 @@ config RISCV_USER_CFI
bool "riscv userspace control flow integrity"
depends on 64BIT && MMU && \
$(cc-option,-mabi=lp64 -march=rv64ima_zicfiss_zicfilp -fcf-protection=full)
depends on RISCV_ALTERNATIVE
select RISCV_SBI
select ARCH_HAS_USER_SHADOW_STACK
select ARCH_USES_HIGH_VMA_FLAGS

View File

@ -2,7 +2,7 @@ menu "CPU errata selection"
config ERRATA_ANDES
bool "Andes AX45MP errata"
depends on RISCV_ALTERNATIVE && RISCV_SBI
depends on RISCV_SBI
help
All Andes errata Kconfig depend on this Kconfig. Disabling
this Kconfig will disable all Andes errata. Please say "Y"
@ -23,7 +23,7 @@ config ERRATA_ANDES_CMO
config ERRATA_MIPS
bool "MIPS errata"
depends on RISCV_ALTERNATIVE
select RISCV_ALTERNATIVE_EARLY
help
All MIPS errata Kconfig depend on this Kconfig. Disabling
this Kconfig will disable all MIPS errata. Please say "Y"
@ -44,9 +44,20 @@ config ERRATA_MIPS_P8700_PAUSE_OPCODE
If you are not using the P8700 processor, say n.
config ERRATA_MIPS_P8700_WFI
bool "Replace WFI with mips.pause for MIPS P8700"
depends on ERRATA_MIPS && 64BIT
default n
help
The RISCV MIPS P8700 has bugs with the WFI instruction.
This errata replaces all WFI instructions with the MIPS
P8700 pause opcode to avoid these issues.
If you are not using the P8700 processor, say n.
config ERRATA_SIFIVE
bool "SiFive errata"
depends on RISCV_ALTERNATIVE && 64BIT
depends on 64BIT
help
All SiFive errata Kconfig depend on this Kconfig. Disabling
this Kconfig will disable all SiFive errata. Please say "Y"
@ -112,7 +123,6 @@ config ERRATA_SIFIVE_MAL_9092
config ERRATA_THEAD
bool "T-HEAD errata"
depends on RISCV_ALTERNATIVE
help
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
this Kconfig will disable all T-HEAD errata. Please say "Y"

View File

@ -31,7 +31,7 @@ cpu0: cpu@0 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -67,7 +67,7 @@ cpu1: cpu@1 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -103,7 +103,7 @@ cpu2: cpu@2 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -139,7 +139,7 @@ cpu3: cpu@3 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -175,7 +175,7 @@ cpu4: cpu@4 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -211,7 +211,7 @@ cpu5: cpu@5 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -247,7 +247,7 @@ cpu6: cpu@6 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -283,7 +283,7 @@ cpu7: cpu@7 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -319,7 +319,7 @@ cpu8: cpu@8 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -355,7 +355,7 @@ cpu9: cpu@9 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -391,7 +391,7 @@ cpu10: cpu@a {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -427,7 +427,7 @@ cpu11: cpu@b {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -463,7 +463,7 @@ cpu12: cpu@c {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -499,7 +499,7 @@ cpu13: cpu@d {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -535,7 +535,7 @@ cpu14: cpu@e {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -571,7 +571,7 @@ cpu15: cpu@f {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -607,7 +607,7 @@ cpu16: cpu@10 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -643,7 +643,7 @@ cpu17: cpu@11 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -679,7 +679,7 @@ cpu18: cpu@12 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -715,7 +715,7 @@ cpu19: cpu@13 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -751,7 +751,7 @@ cpu20: cpu@14 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -787,7 +787,7 @@ cpu21: cpu@15 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -823,7 +823,7 @@ cpu22: cpu@16 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -859,7 +859,7 @@ cpu23: cpu@17 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -895,7 +895,7 @@ cpu24: cpu@18 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -931,7 +931,7 @@ cpu25: cpu@19 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -967,7 +967,7 @@ cpu26: cpu@1a {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1003,7 +1003,7 @@ cpu27: cpu@1b {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1039,7 +1039,7 @@ cpu28: cpu@1c {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1075,7 +1075,7 @@ cpu29: cpu@1d {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1111,7 +1111,7 @@ cpu30: cpu@1e {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1147,7 +1147,7 @@ cpu31: cpu@1f {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1183,7 +1183,7 @@ cpu32: cpu@20 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1219,7 +1219,7 @@ cpu33: cpu@21 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1255,7 +1255,7 @@ cpu34: cpu@22 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1291,7 +1291,7 @@ cpu35: cpu@23 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1327,7 +1327,7 @@ cpu36: cpu@24 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1363,7 +1363,7 @@ cpu37: cpu@25 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1399,7 +1399,7 @@ cpu38: cpu@26 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1435,7 +1435,7 @@ cpu39: cpu@27 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1471,7 +1471,7 @@ cpu40: cpu@28 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1507,7 +1507,7 @@ cpu41: cpu@29 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1543,7 +1543,7 @@ cpu42: cpu@2a {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1579,7 +1579,7 @@ cpu43: cpu@2b {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1615,7 +1615,7 @@ cpu44: cpu@2c {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1651,7 +1651,7 @@ cpu45: cpu@2d {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1687,7 +1687,7 @@ cpu46: cpu@2e {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1723,7 +1723,7 @@ cpu47: cpu@2f {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1759,7 +1759,7 @@ cpu48: cpu@30 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1795,7 +1795,7 @@ cpu49: cpu@31 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1831,7 +1831,7 @@ cpu50: cpu@32 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1867,7 +1867,7 @@ cpu51: cpu@33 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1903,7 +1903,7 @@ cpu52: cpu@34 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1939,7 +1939,7 @@ cpu53: cpu@35 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -1975,7 +1975,7 @@ cpu54: cpu@36 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2011,7 +2011,7 @@ cpu55: cpu@37 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2047,7 +2047,7 @@ cpu56: cpu@38 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2083,7 +2083,7 @@ cpu57: cpu@39 {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2119,7 +2119,7 @@ cpu58: cpu@3a {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2155,7 +2155,7 @@ cpu59: cpu@3b {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2191,7 +2191,7 @@ cpu60: cpu@3c {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2227,7 +2227,7 @@ cpu61: cpu@3d {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2263,7 +2263,7 @@ cpu62: cpu@3e {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",
@ -2299,7 +2299,7 @@ cpu63: cpu@3f {
"svinval", "svnapot", "svpbmt",
"zawrs", "zba", "zbb", "zbc",
"zbs", "zca", "zcb", "zcd",
"zfa", "zfbfmin", "zfh", "zfhmin",
"zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
"zicbom", "zicbop", "zicboz", "ziccrse",
"zicntr", "zicond","zicsr", "zifencei",
"zihintntl", "zihintpause", "zihpm",

View File

@ -57,12 +57,12 @@ cpu_0: cpu@0 {
device_type = "cpu";
reg = <0>;
clocks = <&syscon_apmu CLK_CPU_C0_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -88,12 +88,12 @@ cpu_1: cpu@1 {
device_type = "cpu";
reg = <1>;
clocks = <&syscon_apmu CLK_CPU_C0_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -119,12 +119,12 @@ cpu_2: cpu@2 {
device_type = "cpu";
reg = <2>;
clocks = <&syscon_apmu CLK_CPU_C0_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -150,12 +150,12 @@ cpu_3: cpu@3 {
device_type = "cpu";
reg = <3>;
clocks = <&syscon_apmu CLK_CPU_C0_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -181,12 +181,12 @@ cpu_4: cpu@4 {
device_type = "cpu";
reg = <4>;
clocks = <&syscon_apmu CLK_CPU_C1_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -212,12 +212,12 @@ cpu_5: cpu@5 {
device_type = "cpu";
reg = <5>;
clocks = <&syscon_apmu CLK_CPU_C1_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -243,12 +243,12 @@ cpu_6: cpu@6 {
device_type = "cpu";
reg = <6>;
clocks = <&syscon_apmu CLK_CPU_C1_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
@ -274,12 +274,12 @@ cpu_7: cpu@7 {
device_type = "cpu";
reg = <7>;
clocks = <&syscon_apmu CLK_CPU_C1_CORE>;
riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa = "rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
"zicbop", "zicboz", "zicntr", "zicond", "zicsr",
"zifencei", "zihintpause", "zihpm", "zfh", "zba",
"zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zic64b",
"zicbom", "zicbop", "zicboz", "zicntr", "zicond",
"zicsr", "zifencei", "zihintpause", "zihpm", "zfh",
"zba", "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
"sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;

View File

@ -38,9 +38,9 @@ cpu_0: cpu@0 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -79,9 +79,9 @@ cpu_1: cpu@1 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -120,9 +120,9 @@ cpu_2: cpu@2 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -161,9 +161,9 @@ cpu_3: cpu@3 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -202,9 +202,9 @@ cpu_4: cpu@4 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -243,9 +243,9 @@ cpu_5: cpu@5 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -284,9 +284,9 @@ cpu_6: cpu@6 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",
@ -325,9 +325,9 @@ cpu_7: cpu@7 {
"svinval", "svnapot", "svpbmt", "za64rs",
"zawrs", "zba", "zbb", "zbc", "zbs", "zca",
"zcb", "zcd", "zcmop", "zfa", "zfbfmin",
"zfh", "zfhmin", "zicbom", "zicbop", "zicboz",
"ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr",
"zicond", "zicsr", "zifencei", "zihintntl",
"zfh", "zfhmin", "zic64b", "zicbom", "zicbop",
"zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse",
"zicntr", "zicond", "zicsr", "zifencei", "zihintntl",
"zihintpause", "zihpm", "zimop", "zkt", "zvbb",
"zvbc", "zvfbfmin", "zvfbfwma", "zvfh",
"zvfhmin", "zvkb", "zvkg", "zvkn", "zvknc",

View File

@ -1,5 +1,11 @@
ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
CFLAGS_errata.o := -mcmodel=medany
ifdef CONFIG_FTRACE
CFLAGS_REMOVE_errata.o = $(CC_FLAGS_FTRACE)
endif
ifdef CONFIG_KASAN
KASAN_SANITIZE_errata.o := n
endif
endif
obj-y += errata.o

View File

@ -7,12 +7,13 @@
#include <linux/module.h>
#include <asm/text-patching.h>
#include <asm/alternative.h>
#include <asm/cacheflush.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)
static inline bool errata_probe_pause(unsigned int stage)
{
if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE))
return false;
@ -20,16 +21,36 @@ static inline bool errata_probe_pause(void)
if (!riscv_isa_vendor_extension_available(MIPS_VENDOR_ID, XMIPSEXECTL))
return false;
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return false;
return true;
}
static u32 mips_errata_probe(void)
static inline bool errata_probe_wfi(unsigned int stage)
{
if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_WFI))
return false;
if (!riscv_isa_vendor_extension_available(MIPS_VENDOR_ID, XMIPSEXECTL))
return false;
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return false;
return true;
}
static u32 mips_errata_probe(unsigned int stage)
{
u32 cpu_req_errata = 0;
if (errata_probe_pause())
if (errata_probe_pause(stage))
cpu_req_errata |= BIT(ERRATA_MIPS_P8700_PAUSE_OPCODE);
if (errata_probe_wfi(stage))
cpu_req_errata |= BIT(ERRATA_MIPS_P8700_WFI);
return cpu_req_errata;
}
@ -38,30 +59,34 @@ void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage)
{
struct alt_entry *alt;
u32 cpu_req_errata = mips_errata_probe();
u32 cpu_req_errata = mips_errata_probe(stage);
u32 tmp;
void *oldptr, *altptr;
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);
if (alt->patch_id >= ERRATA_MIPS_NUMBER)
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);
oldptr = ALT_OLD_PTR(alt);
altptr = ALT_ALT_PTR(alt);
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) {
memcpy(oldptr, altptr, alt->alt_len);
} else {
mutex_lock(&text_mutex);
patch_text_nosync(oldptr, altptr, alt->alt_len);
mutex_unlock(&text_mutex);
}
}
}
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
local_flush_icache_all();
}

View File

@ -2,8 +2,6 @@
#ifndef __ASM_ALTERNATIVE_MACROS_H
#define __ASM_ALTERNATIVE_MACROS_H
#ifdef CONFIG_RISCV_ALTERNATIVE
#ifdef __ASSEMBLER__
.macro ALT_ENTRY oldptr newptr vendor_id patch_id new_len
@ -108,28 +106,6 @@
__ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, patch_id_1, IS_ENABLED(CONFIG_k_1), \
new_c_2, vendor_id_2, patch_id_2, IS_ENABLED(CONFIG_k_2))
#else /* CONFIG_RISCV_ALTERNATIVE */
#ifdef __ASSEMBLER__
.macro ALTERNATIVE_CFG old_c
\old_c
.endm
#define __ALTERNATIVE_CFG(old_c, ...) ALTERNATIVE_CFG old_c
#define __ALTERNATIVE_CFG_2(old_c, ...) ALTERNATIVE_CFG old_c
#else /* !__ASSEMBLER__ */
#define __ALTERNATIVE_CFG(old_c, ...) old_c "\n"
#define __ALTERNATIVE_CFG_2(old_c, ...) old_c "\n"
#endif /* __ASSEMBLER__ */
#define _ALTERNATIVE_CFG(old_c, ...) __ALTERNATIVE_CFG(old_c)
#define _ALTERNATIVE_CFG_2(old_c, ...) __ALTERNATIVE_CFG_2(old_c)
#endif /* CONFIG_RISCV_ALTERNATIVE */
/*
* Usage:
* ALTERNATIVE(old_content, new_content, vendor_id, patch_id, CONFIG_k)

View File

@ -10,8 +10,6 @@
#ifndef __ASSEMBLER__
#ifdef CONFIG_RISCV_ALTERNATIVE
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
@ -35,7 +33,7 @@ void __init apply_early_boot_alternatives(void);
void apply_module_alternatives(void *start, size_t length);
void riscv_alternative_fix_offsets(void *alt_ptr, unsigned int len,
int patch_offset);
int patch_offset, bool early);
struct alt_entry {
s32 old_offset; /* offset relative to original instruction or data */
@ -61,13 +59,5 @@ void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage);
#else /* CONFIG_RISCV_ALTERNATIVE */
static inline void apply_boot_alternatives(void) { }
static inline void apply_early_boot_alternatives(void) { }
static inline void apply_module_alternatives(void *start, size_t length) { }
#endif /* CONFIG_RISCV_ALTERNATIVE */
#endif
#endif

View File

@ -47,20 +47,14 @@ static __always_inline bool riscv_has_extension_unlikely(const unsigned long ext
{
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
return __riscv_has_extension_unlikely(STANDARD_EXT, ext);
return __riscv_isa_extension_available(NULL, ext);
return __riscv_has_extension_unlikely(STANDARD_EXT, ext);
}
static __always_inline bool riscv_has_extension_likely(const unsigned long ext)
{
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
return __riscv_has_extension_likely(STANDARD_EXT, ext);
return __riscv_isa_extension_available(NULL, ext);
return __riscv_has_extension_likely(STANDARD_EXT, ext);
}
#endif /* _ASM_CPUFEATURE_MACROS_H */

View File

@ -36,6 +36,8 @@ extern const struct seq_operations cpuinfo_op;
/* Per-cpu ISA extensions. */
extern struct riscv_isainfo hart_isa[NR_CPUS];
extern DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX);
extern u32 thead_vlenb_of;
void __init riscv_user_isa_enable(void);
@ -136,8 +138,7 @@ static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsign
{
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
__riscv_has_extension_likely(STANDARD_EXT, ext))
if (__riscv_has_extension_likely(STANDARD_EXT, ext))
return true;
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
@ -147,8 +148,7 @@ static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsi
{
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
__riscv_has_extension_unlikely(STANDARD_EXT, ext))
if (__riscv_has_extension_unlikely(STANDARD_EXT, ext))
return true;
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);

View File

@ -25,6 +25,16 @@ 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)
#ifdef CONFIG_ERRATA_MIPS_P8700_WFI
#define ALT_WFI \
ALTERNATIVE("wfi; .rept 7; nop; .endr;", \
".rept 8; .4byte 0x00501013; .endr;", MIPS_VENDOR_ID, \
ERRATA_MIPS_P8700_WFI, CONFIG_ERRATA_MIPS_P8700_WFI)
#else
#define ALT_WFI wfi
#endif
#else /* !__ASSEMBLER__ */
#define ALT_SFENCE_VMA_ASID(asid) \
@ -53,6 +63,33 @@ asm(ALTERNATIVE( \
: /* no inputs */ \
: "memory")
#ifdef CONFIG_ERRATA_MIPS_P8700_WFI
/*
* A WFI instruction after a mispredicted branch can result in erroneous address translation
* on the MIPS P8700.
* The number of MIPS_PAUSE instructions required was determined by measuring
* Coremark performance on a one-core, two-hart configuration. Eight PAUSE instructions matched
* the latency of a single WFI instruction.
* Usually, the maximum number of cycles per PAUSE instruction is 63. Exceptionally, if the hart's
* LR reservation bit is set, the maximum number of cycles is extended to 255
* (and the hart is woken up once it is cleared). This case should not affect the patched sites.
*/
#define ALT_RISCV_WFI() \
asm volatile(ALTERNATIVE( \
"wfi\n" /* Original RISC-V wfi insn */ \
__nops(7), \
".rept 8;" MIPS_PAUSE ".endr;\n", /* Replacement: mips.pause for P8700 */ \
MIPS_VENDOR_ID, /* Vendor ID to match */ \
ERRATA_MIPS_P8700_WFI, /* patch_id */ \
CONFIG_ERRATA_MIPS_P8700_WFI) \
: /* no outputs */ \
: /* no inputs */ \
: "memory")
#else
#define ALT_RISCV_WFI() \
__asm__ __volatile__ ("wfi")
#endif
/*
* _val is marked as "will be overwritten", so need to set it to 0
* in the default case.

View File

@ -23,8 +23,9 @@
#endif
#ifdef CONFIG_ERRATA_MIPS
#define ERRATA_MIPS_P8700_PAUSE_OPCODE 0
#define ERRATA_MIPS_NUMBER 1
#define ERRATA_MIPS_P8700_PAUSE_OPCODE 0
#define ERRATA_MIPS_P8700_WFI 1
#define ERRATA_MIPS_NUMBER 2
#endif
#endif /* ASM_ERRATA_LIST_VENDORS_H */

View File

@ -11,6 +11,7 @@
#include <uapi/asm/hwcap.h>
#define RISCV_ISA_EXT_A ('a' - 'a')
#define RISCV_ISA_EXT_B ('b' - 'a')
#define RISCV_ISA_EXT_C ('c' - 'a')
#define RISCV_ISA_EXT_D ('d' - 'a')
#define RISCV_ISA_EXT_F ('f' - 'a')
@ -122,6 +123,9 @@
#define RISCV_ISA_EXT_ZICCAMOA 113
#define RISCV_ISA_EXT_ZICCIF 114
#define RISCV_ISA_EXT_ZA64RS 115
#define RISCV_ISA_EXT_ZIC64B 116
#define RISCV_ISA_EXT_SV48 117
#define RISCV_ISA_EXT_SV57 118
#define RISCV_ISA_EXT_XLINUXENVCFG 127

View File

@ -142,7 +142,7 @@
#define RVG_OPCODE_JAL 0x6f
#define RVG_OPCODE_SYSTEM 0x73
#define RVG_SYSTEM_CSR_OFF 20
#define RVG_SYSTEM_CSR_MASK GENMASK(12, 0)
#define RVG_SYSTEM_CSR_MASK GENMASK(11, 0)
/* parts of opcode for RVF, RVD and RVQ */
#define RVFDQ_FL_FS_WIDTH_OFF 12

View File

@ -65,6 +65,32 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke
label:
return true;
}
#else
#include <asm/asm.h>
#define JUMP_TABLE_ENTRY(key, label) \
.pushsection __jump_table, "aw"; \
.align RISCV_LGPTR; \
.long 1b - ., label - .; \
RISCV_PTR key - .; \
.popsection
#define ARCH_STATIC_BRANCH_ASM(key, label) \
.align 2; \
.option push; \
.option norelax; \
.option norvc; \
1: nop; \
.option pop; \
JUMP_TABLE_ENTRY(key, label)
#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \
.align 2; \
.option push; \
.option norelax; \
.option norvc; \
1: j label; \
.option pop; \
JUMP_TABLE_ENTRY(key, label)
#endif /* __ASSEMBLER__ */
#endif /* __ASM_JUMP_LABEL_H */

View File

@ -75,4 +75,17 @@ int load_extra_segments(struct kimage *image, unsigned long kernel_start,
unsigned long cmdline_len);
#endif
#ifdef CONFIG_CRASH_HOTPLUG
struct kimage;
void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
#define arch_crash_handle_hotplug_event arch_crash_handle_hotplug_event
int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
#define arch_crash_hotplug_support arch_crash_hotplug_support
unsigned int arch_crash_get_elfcorehdr_size(void);
#define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size
#endif
#endif

View File

@ -98,7 +98,7 @@ do { \
#define nacl_sync_hfence(__e) \
sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SYNC_HFENCE, \
(__e), 0, 0, 0, 0, 0)
(__e))
#define nacl_hfence_mkconfig(__type, __order, __vmid, __asid) \
({ \
@ -198,7 +198,7 @@ do { \
#define nacl_sync_csr(__csr) \
sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SYNC_CSR, \
(__csr), 0, 0, 0, 0, 0)
(__csr))
/*
* Each ncsr_xyz() macro defined below has it's own static-branch so every

View File

@ -15,6 +15,11 @@
#define PCIBIOS_MIN_IO 4
#define PCIBIOS_MIN_MEM 16
/*
* Set to 1 if the kernel should re-assign all PCI bus numbers
*/
#define pcibios_assign_all_busses() (pci_has_flag(PCI_REASSIGN_ALL_BUS))
#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
static inline int pcibus_to_node(struct pci_bus *bus)
{

View File

@ -41,7 +41,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
{
if (pgtable_l4_enabled) {
if (pgtable_l4_enabled()) {
unsigned long pfn = virt_to_pfn(pud);
set_p4d(p4d, __p4d((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
@ -51,7 +51,7 @@ static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
static inline void p4d_populate_safe(struct mm_struct *mm, p4d_t *p4d,
pud_t *pud)
{
if (pgtable_l4_enabled) {
if (pgtable_l4_enabled()) {
unsigned long pfn = virt_to_pfn(pud);
set_p4d_safe(p4d,
@ -61,7 +61,7 @@ static inline void p4d_populate_safe(struct mm_struct *mm, p4d_t *p4d,
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d)
{
if (pgtable_l5_enabled) {
if (pgtable_l5_enabled()) {
unsigned long pfn = virt_to_pfn(p4d);
set_pgd(pgd, __pgd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
@ -71,7 +71,7 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d)
static inline void pgd_populate_safe(struct mm_struct *mm, pgd_t *pgd,
p4d_t *p4d)
{
if (pgtable_l5_enabled) {
if (pgtable_l5_enabled()) {
unsigned long pfn = virt_to_pfn(p4d);
set_pgd_safe(pgd,
@ -82,21 +82,21 @@ static inline void pgd_populate_safe(struct mm_struct *mm, pgd_t *pgd,
#define pud_free pud_free
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
__pud_free(mm, pud);
}
static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
unsigned long addr)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud));
}
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
unsigned long addr)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
}
#endif /* __PAGETABLE_PMD_FOLDED */

View File

@ -33,7 +33,7 @@
_PAGE_WRITE | _PAGE_EXEC | \
_PAGE_USER | _PAGE_GLOBAL))
static const __maybe_unused int pgtable_l4_enabled;
static const __maybe_unused int pgtable_l5_enabled;
static inline bool pgtable_l4_enabled(void) { return false; }
static inline bool pgtable_l5_enabled(void) { return false; }
#endif /* _ASM_RISCV_PGTABLE_32_H */

View File

@ -10,14 +10,48 @@
#include <linux/const.h>
#include <asm/errata_list.h>
extern bool pgtable_l4_enabled;
extern bool pgtable_l5_enabled;
extern bool _pgtable_l4_enabled;
extern bool _pgtable_l5_enabled;
#ifdef USE_EARLY_PGTABLE_LEVELS
static __always_inline bool pgtable_l5_enabled(void)
{
if (!IS_ENABLED(CONFIG_RISCV_ISA_SV57))
return false;
return _pgtable_l5_enabled;
}
static __always_inline bool pgtable_l4_enabled(void)
{
if (!IS_ENABLED(CONFIG_RISCV_ISA_SV48))
return false;
return _pgtable_l4_enabled;
}
#else
static __always_inline bool pgtable_l5_enabled(void)
{
if (!IS_ENABLED(CONFIG_RISCV_ISA_SV57))
return false;
return riscv_has_extension_likely(RISCV_ISA_EXT_SV57);
}
static __always_inline bool pgtable_l4_enabled(void)
{
if (!IS_ENABLED(CONFIG_RISCV_ISA_SV48))
return false;
return riscv_has_extension_likely(RISCV_ISA_EXT_SV48);
}
#endif
#define PGDIR_SHIFT_L3 30
#define PGDIR_SHIFT_L4 39
#define PGDIR_SHIFT_L5 48
#define PGDIR_SHIFT (pgtable_l5_enabled ? PGDIR_SHIFT_L5 : \
(pgtable_l4_enabled ? PGDIR_SHIFT_L4 : PGDIR_SHIFT_L3))
#define PGDIR_SHIFT (pgtable_l5_enabled() ? PGDIR_SHIFT_L5 : \
(pgtable_l4_enabled() ? PGDIR_SHIFT_L4 : PGDIR_SHIFT_L3))
/* Size of region mapped by a page global directory */
#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE - 1))
@ -26,8 +60,8 @@ extern bool pgtable_l5_enabled;
#define P4D_SHIFT_L3 30
#define P4D_SHIFT_L4 39
#define P4D_SHIFT_L5 39
#define P4D_SHIFT (pgtable_l5_enabled ? P4D_SHIFT_L5 : \
(pgtable_l4_enabled ? P4D_SHIFT_L4 : P4D_SHIFT_L3))
#define P4D_SHIFT (pgtable_l5_enabled() ? P4D_SHIFT_L5 : \
(pgtable_l4_enabled() ? P4D_SHIFT_L4 : P4D_SHIFT_L3))
#define P4D_SIZE (_AC(1, UL) << P4D_SHIFT)
#define P4D_MASK (~(P4D_SIZE - 1))
@ -233,7 +267,7 @@ static inline struct page *pud_page(pud_t pud)
#define mm_p4d_folded mm_p4d_folded
static inline bool mm_p4d_folded(struct mm_struct *mm)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
return false;
return true;
@ -242,7 +276,7 @@ static inline bool mm_p4d_folded(struct mm_struct *mm)
#define mm_pud_folded mm_pud_folded
static inline bool mm_pud_folded(struct mm_struct *mm)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
return false;
return true;
@ -266,7 +300,7 @@ static inline unsigned long _pmd_pfn(pmd_t pmd)
static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
WRITE_ONCE(*p4dp, p4d);
else
set_pud((pud_t *)p4dp, (pud_t){ p4d_val(p4d) });
@ -274,7 +308,7 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
static inline int p4d_none(p4d_t p4d)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
return (p4d_val(p4d) == 0);
return 0;
@ -282,7 +316,7 @@ static inline int p4d_none(p4d_t p4d)
static inline int p4d_present(p4d_t p4d)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
return (p4d_val(p4d) & _PAGE_PRESENT);
return 1;
@ -290,7 +324,7 @@ static inline int p4d_present(p4d_t p4d)
static inline int p4d_bad(p4d_t p4d)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
return !p4d_present(p4d);
return 0;
@ -298,7 +332,7 @@ static inline int p4d_bad(p4d_t p4d)
static inline void p4d_clear(p4d_t *p4d)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
set_p4d(p4d, __p4d(0));
}
@ -314,7 +348,7 @@ static inline unsigned long _p4d_pfn(p4d_t p4d)
static inline pud_t *p4d_pgtable(p4d_t p4d)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
return (pud_t *)pfn_to_virt(__page_val_to_pfn(p4d_val(p4d)));
return (pud_t *)pud_pgtable((pud_t) { p4d_val(p4d) });
@ -333,7 +367,7 @@ pud_t *pud_offset(p4d_t *p4d, unsigned long address);
static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
WRITE_ONCE(*pgdp, pgd);
else
set_p4d((p4d_t *)pgdp, (p4d_t){ pgd_val(pgd) });
@ -341,7 +375,7 @@ static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
static inline int pgd_none(pgd_t pgd)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
return (pgd_val(pgd) == 0);
return 0;
@ -349,7 +383,7 @@ static inline int pgd_none(pgd_t pgd)
static inline int pgd_present(pgd_t pgd)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
return (pgd_val(pgd) & _PAGE_PRESENT);
return 1;
@ -357,7 +391,7 @@ static inline int pgd_present(pgd_t pgd)
static inline int pgd_bad(pgd_t pgd)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
return !pgd_present(pgd);
return 0;
@ -365,13 +399,13 @@ static inline int pgd_bad(pgd_t pgd)
static inline void pgd_clear(pgd_t *pgd)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
set_pgd(pgd, __pgd(0));
}
static inline p4d_t *pgd_pgtable(pgd_t pgd)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
return (p4d_t *)pfn_to_virt(__page_val_to_pfn(pgd_val(pgd)));
return (p4d_t *)p4d_pgtable((p4d_t) { pgd_val(pgd) });

View File

@ -75,8 +75,8 @@
#define VA_BITS_SV48 48
#define VA_BITS_SV57 57
#define VA_BITS (pgtable_l5_enabled ? \
VA_BITS_SV57 : (pgtable_l4_enabled ? VA_BITS_SV48 : VA_BITS_SV39))
#define VA_BITS (pgtable_l5_enabled() ? \
VA_BITS_SV57 : (pgtable_l4_enabled() ? VA_BITS_SV48 : VA_BITS_SV39))
#else
#define VA_BITS VA_BITS_SV32
#endif

View File

@ -17,6 +17,7 @@
#include <asm/alternative-macros.h>
#include <asm/hwcap.h>
#include <asm/usercfi.h>
#include <asm/errata_list.h>
#define arch_get_mmap_end(addr, len, flags) \
({ \
@ -187,7 +188,7 @@ extern unsigned long __get_wchan(struct task_struct *p);
static inline void wait_for_interrupt(void)
{
__asm__ __volatile__ ("wfi");
ALT_RISCV_WFI();
}
extern phys_addr_t dma32_phys_limit;
@ -225,6 +226,10 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg);
long get_tagged_addr_ctrl(struct task_struct *task);
#define SET_TAGGED_ADDR_CTRL(arg) set_tagged_addr_ctrl(current, arg)
#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl(current)
bool riscv_have_user_pmlen(u8 len);
#else
static inline bool riscv_have_user_pmlen(u8 len) { return false; }
#endif
#endif /* __ASSEMBLER__ */

View File

@ -7,9 +7,11 @@
#ifndef _ASM_RISCV_SBI_H
#define _ASM_RISCV_SBI_H
#include <linux/args.h>
#include <linux/types.h>
#include <linux/cpumask.h>
#include <linux/jump_label.h>
#include <linux/tracepoint-defs.h>
#ifdef CONFIG_RISCV_SBI
enum sbi_ext_id {
@ -563,14 +565,81 @@ struct sbiret {
long value;
};
#ifdef CONFIG_TRACEPOINTS
DECLARE_TRACEPOINT(sbi_call);
DECLARE_TRACEPOINT(sbi_return);
extern void do_trace_sbi_call(int ext, int fid);
extern void do_trace_sbi_return(int ext, long error, long value);
#else
static inline void do_trace_sbi_call(int ext, int fid) {};
static inline void do_trace_sbi_return(int ext, long error, long value) {};
#endif
void sbi_init(void);
long __sbi_base_ecall(int fid);
struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5,
int fid, int ext);
#define sbi_ecall(e, f, a0, a1, a2, a3, a4, a5) \
__sbi_ecall(a0, a1, a2, a3, a4, a5, f, e)
#define __sbi_ecall_args2(e, f) \
uintptr_t __ta7 = (uintptr_t)(e); \
uintptr_t __ta6 = (uintptr_t)(f)
#define __sbi_ecall_args3(e, f, a0) \
__sbi_ecall_args2(e, f); uintptr_t __ta0 = (uintptr_t)(a0)
#define __sbi_ecall_args4(e, f, a0, a1) \
__sbi_ecall_args3(e, f, a0); uintptr_t __ta1 = (uintptr_t)(a1)
#define __sbi_ecall_args5(e, f, a0, a1, a2) \
__sbi_ecall_args4(e, f, a0, a1); uintptr_t __ta2 = (uintptr_t)(a2)
#define __sbi_ecall_args6(e, f, a0, a1, a2, a3) \
__sbi_ecall_args5(e, f, a0, a1, a2); uintptr_t __ta3 = (uintptr_t)(a3)
#define __sbi_ecall_args7(e, f, a0, a1, a2, a3, a4) \
__sbi_ecall_args6(e, f, a0, a1, a2, a3); uintptr_t __ta4 = (uintptr_t)(a4)
#define __sbi_ecall_args8(e, f, a0, a1, a2, a3, a4, a5) \
__sbi_ecall_args7(e, f, a0, a1, a2, a3, a4); uintptr_t __ta5 = (uintptr_t)(a5)
#define __sbi_ecall_regs2 \
register uintptr_t __a7 asm ("a7") = __ta7; \
register uintptr_t __a6 asm ("a6") = __ta6
#define __sbi_ecall_regs3 __sbi_ecall_regs2; register uintptr_t __a0 asm ("a0") = __ta0
#define __sbi_ecall_regs4 __sbi_ecall_regs3; register uintptr_t __a1 asm ("a1") = __ta1
#define __sbi_ecall_regs5 __sbi_ecall_regs4; register uintptr_t __a2 asm ("a2") = __ta2
#define __sbi_ecall_regs6 __sbi_ecall_regs5; register uintptr_t __a3 asm ("a3") = __ta3
#define __sbi_ecall_regs7 __sbi_ecall_regs6; register uintptr_t __a4 asm ("a4") = __ta4
#define __sbi_ecall_regs8 __sbi_ecall_regs7; register uintptr_t __a5 asm ("a5") = __ta5
#define __sbi_ecall_constraints1 "r" (__a7)
#define __sbi_ecall_constraints2 __sbi_ecall_constraints1, "r" (__a6)
#define __sbi_ecall_constraints3 __sbi_ecall_constraints2, "r" (__a0)
#define __sbi_ecall_constraints4 __sbi_ecall_constraints3, "r" (__a1)
#define __sbi_ecall_constraints5 __sbi_ecall_constraints4, "r" (__a2)
#define __sbi_ecall_constraints6 __sbi_ecall_constraints5, "r" (__a3)
#define __sbi_ecall_constraints7 __sbi_ecall_constraints6, "r" (__a4)
#define __sbi_ecall_constraints8 __sbi_ecall_constraints7, "r" (__a5)
#define __sbi_ecall_trace_call() \
if (tracepoint_enabled(sbi_call)) \
do_trace_sbi_call(__ta7, __ta6)
#define __sbi_ecall_trace_return() \
if (tracepoint_enabled(sbi_return)) \
do_trace_sbi_return(__ta7, __ret.error, __ret.value)
/*
* Clear a1 to avoid leaking unrelated kernel state through tracepoints in case
* the register doesn't get overwritten by the ecall nor the arguments.
*/
#define sbi_ecall(A...) \
({ \
CONCATENATE(__sbi_ecall_args, COUNT_ARGS(A))(A); \
__sbi_ecall_trace_call(); \
register uintptr_t __r0 asm ("a0"); \
register uintptr_t __r1 asm ("a1") = 0; \
CONCATENATE(__sbi_ecall_regs, COUNT_ARGS(A)); \
asm volatile ("ecall" \
: "=r" (__r0), "=r" (__r1) \
: CONCATENATE(__sbi_ecall_constraints, COUNT_ARGS(A)) \
: "memory"); \
struct sbiret __ret = {.error = __r0, .value = __r1}; \
__sbi_ecall_trace_return(); \
__ret; \
})
#ifdef CONFIG_RISCV_SBI_V01
void sbi_console_putchar(int ch);

View File

@ -377,12 +377,12 @@ static inline void __switch_to_vector(struct task_struct *prev,
struct pt_regs *regs;
if (riscv_preempt_v_started(prev)) {
if (riscv_v_is_on()) {
WARN_ON(prev->thread.riscv_v_flags & RISCV_V_CTX_DEPTH_MASK);
if (!(current->thread.riscv_v_flags & RISCV_V_CTX_DEPTH_MASK)) {
/* Voluntary schedule(): nesting_end closed any dirty. */
WARN_ON(riscv_preempt_v_dirty(prev));
riscv_v_disable();
prev->thread.riscv_v_flags |= RISCV_PREEMPT_V_IN_SCHEDULE;
}
if (riscv_preempt_v_dirty(prev)) {
} else if (riscv_preempt_v_dirty(prev)) {
__riscv_v_vstate_save(&prev->thread.kernel_vstate,
prev->thread.kernel_vstate.datap);
riscv_preempt_v_clear_dirty(prev);

View File

@ -54,11 +54,9 @@ static __always_inline bool riscv_has_vendor_extension_likely(const unsigned lon
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
return false;
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
return __riscv_has_extension_likely(vendor,
ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
return __riscv_has_extension_likely(vendor,
ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, ext);
}
static __always_inline bool riscv_has_vendor_extension_unlikely(const unsigned long vendor,
@ -67,11 +65,9 @@ static __always_inline bool riscv_has_vendor_extension_unlikely(const unsigned l
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
return false;
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
return __riscv_has_extension_unlikely(vendor,
ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
return __riscv_has_extension_unlikely(vendor,
ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, ext);
}
static __always_inline bool riscv_cpu_has_vendor_extension_likely(const unsigned long vendor,
@ -80,8 +76,7 @@ static __always_inline bool riscv_cpu_has_vendor_extension_likely(const unsigned
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
return false;
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
__riscv_has_extension_likely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
if (__riscv_has_extension_likely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
return true;
return __riscv_isa_vendor_extension_available(cpu, vendor, ext);
@ -94,8 +89,7 @@ static __always_inline bool riscv_cpu_has_vendor_extension_unlikely(const unsign
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
return false;
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
__riscv_has_extension_unlikely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
if (__riscv_has_extension_unlikely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
return true;
return __riscv_isa_vendor_extension_available(cpu, vendor, ext);

View File

@ -3,15 +3,14 @@
#define _ASM_RISCV_VMALLOC_H
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
extern bool pgtable_l4_enabled, pgtable_l5_enabled;
#include <asm/pgtable.h>
#define IOREMAP_MAX_ORDER (PUD_SHIFT)
#define arch_vmap_pud_supported arch_vmap_pud_supported
static inline bool arch_vmap_pud_supported(pgprot_t prot)
{
return pgtable_l4_enabled || pgtable_l5_enabled;
return pgtable_l4_enabled() || pgtable_l5_enabled();
}
#define arch_vmap_pmd_supported arch_vmap_pmd_supported

View File

@ -21,6 +21,7 @@
#define COMPAT_HWCAP_ISA_F (1 << ('F' - 'A'))
#define COMPAT_HWCAP_ISA_D (1 << ('D' - 'A'))
#define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A'))
#define COMPAT_HWCAP_ISA_B (1 << ('B' - 'A'))
#define COMPAT_HWCAP_ISA_V (1 << ('V' - 'A'))
#endif /* _UAPI_ASM_RISCV_HWCAP_H */

View File

@ -122,6 +122,8 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_EXT_ZICCIF _BITULL(3)
#define RISCV_HWPROBE_EXT_ZICCRSE _BITULL(4)
#define RISCV_HWPROBE_EXT_ZA64RS _BITULL(5)
#define RISCV_HWPROBE_EXT_B _BITULL(6)
#define RISCV_HWPROBE_EXT_ZIC64B _BITULL(7)
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */

View File

@ -48,7 +48,7 @@ always-$(KBUILD_BUILTIN) += vmlinux.lds
obj-y += head.o
obj-y += soc.o
obj-$(CONFIG_RISCV_ALTERNATIVE) += alternative.o
obj-y += alternative.o
obj-y += cpu.o
obj-y += cpufeature.o
obj-y += entry.o
@ -111,6 +111,7 @@ obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KEXEC_CORE) += kexec_relocate.o crash_save_regs.o machine_kexec.o
obj-$(CONFIG_KEXEC_FILE) += kexec_elf.o kexec_image.o machine_kexec_file.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_CRASH_HOTPLUG) += crash.o
obj-$(CONFIG_VMCORE_INFO) += vmcore_info.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o

View File

@ -75,7 +75,8 @@ static u32 riscv_instruction_at(void *p)
}
static void riscv_alternative_fix_auipc_jalr(void *ptr, u32 auipc_insn,
u32 jalr_insn, int patch_offset)
u32 jalr_insn, int patch_offset,
bool early)
{
u32 call[2] = { auipc_insn, jalr_insn };
s32 imm;
@ -88,10 +89,15 @@ static void riscv_alternative_fix_auipc_jalr(void *ptr, u32 auipc_insn,
riscv_insn_insert_utype_itype_imm(&call[0], &call[1], imm);
/* patch the call place again */
patch_text_nosync(ptr, call, sizeof(u32) * 2);
if (early) {
memcpy(ptr, call, sizeof(call));
} else {
patch_text_nosync(ptr, call, sizeof(call));
}
}
static void riscv_alternative_fix_jal(void *ptr, u32 jal_insn, int patch_offset)
static void riscv_alternative_fix_jal(void *ptr, u32 jal_insn, int patch_offset,
bool early)
{
s32 imm;
@ -103,11 +109,14 @@ static void riscv_alternative_fix_jal(void *ptr, u32 jal_insn, int patch_offset)
riscv_insn_insert_jtype_imm(&jal_insn, imm);
/* patch the call place again */
patch_text_nosync(ptr, &jal_insn, sizeof(u32));
if (early)
memcpy(ptr, &jal_insn, sizeof(u32));
else
patch_text_nosync(ptr, &jal_insn, sizeof(u32));
}
void riscv_alternative_fix_offsets(void *alt_ptr, unsigned int len,
int patch_offset)
int patch_offset, bool early)
{
int num_insn = len / sizeof(u32);
int i;
@ -131,7 +140,8 @@ void riscv_alternative_fix_offsets(void *alt_ptr, unsigned int len,
continue;
riscv_alternative_fix_auipc_jalr(alt_ptr + i * sizeof(u32),
insn, insn2, patch_offset);
insn, insn2, patch_offset,
early);
i++;
}
@ -144,7 +154,7 @@ void riscv_alternative_fix_offsets(void *alt_ptr, unsigned int len,
continue;
riscv_alternative_fix_jal(alt_ptr + i * sizeof(u32),
insn, patch_offset);
insn, patch_offset, early);
}
}
}

View File

@ -292,9 +292,9 @@ static void print_mmu(struct seq_file *f)
#if defined(CONFIG_32BIT)
sv_type = "sv32";
#elif defined(CONFIG_64BIT)
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
sv_type = "sv57";
else if (pgtable_l4_enabled)
else if (pgtable_l4_enabled())
sv_type = "sv48";
else
sv_type = "sv39";

View File

@ -29,7 +29,7 @@ static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr,
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
hartid, saddr, priv, 0, 0, 0);
hartid, saddr, priv);
return sbi_err_map_linux_errno(ret.error);
}
@ -39,7 +39,7 @@ static int sbi_hsm_hart_stop(void)
{
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0, 0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP);
return sbi_err_map_linux_errno(ret.error);
}
@ -49,7 +49,7 @@ static int sbi_hsm_hart_get_status(unsigned long hartid)
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_STATUS,
hartid, 0, 0, 0, 0, 0);
hartid);
if (ret.error)
return sbi_err_map_linux_errno(ret.error);
else

View File

@ -39,7 +39,7 @@ static bool any_cpu_has_zicbom;
unsigned long elf_hwcap __read_mostly;
/* Host ISA bitmap */
static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
/* Per-cpu ISA extensions. */
struct riscv_isainfo hart_isa[NR_CPUS];
@ -136,6 +136,24 @@ static int riscv_ext_zicbop_validate(const struct riscv_isa_ext_data *data,
return 0;
}
static int riscv_ext_zic64b_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
/*
* Zic64b mandates 64-byte naturally aligned cache blocks; cross-check the
* cbom/cbop/cboz block-size (when declared) device-tree properties to
* avoid inconsistency.
*/
if ((riscv_cbom_block_size && riscv_cbom_block_size != 64) ||
(riscv_cbop_block_size && riscv_cbop_block_size != 64) ||
(riscv_cboz_block_size && riscv_cboz_block_size != 64)) {
pr_err("Zic64b detected in ISA string, disabling as a CBO block size is not 64 bytes\n");
return -EINVAL;
}
return 0;
}
static int riscv_ext_f_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
@ -484,6 +502,12 @@ static const unsigned int riscv_c_exts[] = {
RISCV_ISA_EXT_ZCD,
};
static const unsigned int riscv_b_exts[] = {
RISCV_ISA_EXT_ZBA,
RISCV_ISA_EXT_ZBB,
RISCV_ISA_EXT_ZBS,
};
/*
* The canonical order of ISA extension names in the ISA string is defined in
* Chapter 27 of the RISC-V Instruction Set Manual Volume I Unprivileged ISA
@ -532,9 +556,11 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA_VALIDATE(d, RISCV_ISA_EXT_D, riscv_ext_d_validate),
__RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_Q),
__RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_C, riscv_c_exts),
__RISCV_ISA_EXT_SUPERSET(b, RISCV_ISA_EXT_B, riscv_b_exts),
__RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_V, riscv_v_exts,
riscv_ext_vector_float_validate),
__RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_H),
__RISCV_ISA_EXT_DATA_VALIDATE(zic64b, RISCV_ISA_EXT_ZIC64B, riscv_ext_zic64b_validate),
__RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zicbop, RISCV_ISA_EXT_ZICBOP, riscv_ext_zicbop_validate),
__RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate),
@ -640,6 +666,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
__RISCV_ISA_EXT_DATA(svrsw60t59b, RISCV_ISA_EXT_SVRSW60T59B),
__RISCV_ISA_EXT_DATA(svvptc, RISCV_ISA_EXT_SVVPTC),
__RISCV_ISA_EXT_DATA(sv48, RISCV_ISA_EXT_SV48),
__RISCV_ISA_EXT_DATA(sv57, RISCV_ISA_EXT_SV57),
};
const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);
@ -938,6 +966,13 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
set_bit(RISCV_ISA_EXT_ZIHPM, source_isa);
}
#ifndef CONFIG_32BIT
if (_pgtable_l4_enabled)
set_bit(RISCV_ISA_EXT_SV48, source_isa);
if (_pgtable_l5_enabled)
set_bit(RISCV_ISA_EXT_SV57, source_isa);
#endif
/*
* "V" in ISA strings is ambiguous in practice: it should mean
* just the standard V-1.0 but vendors aren't well behaved.
@ -1098,6 +1133,13 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
riscv_isa_set_ext(ext, source_isa);
}
#ifndef CONFIG_32BIT
if (_pgtable_l4_enabled)
set_bit(RISCV_ISA_EXT_SV48, source_isa);
if (_pgtable_l5_enabled)
set_bit(RISCV_ISA_EXT_SV57, source_isa);
#endif
riscv_resolve_isa(source_isa, isainfo->isa, &this_hwcap, isa2hwcap);
riscv_fill_cpu_vendor_ext(cpu_node, cpu);
@ -1161,8 +1203,15 @@ void __init riscv_fill_hwcap(void)
isa2hwcap[RISCV_ISA_EXT_F] = COMPAT_HWCAP_ISA_F;
isa2hwcap[RISCV_ISA_EXT_D] = COMPAT_HWCAP_ISA_D;
isa2hwcap[RISCV_ISA_EXT_C] = COMPAT_HWCAP_ISA_C;
isa2hwcap[RISCV_ISA_EXT_B] = COMPAT_HWCAP_ISA_B;
isa2hwcap[RISCV_ISA_EXT_V] = COMPAT_HWCAP_ISA_V;
/*
* riscv_isa may have been touched by "early" ISA parsing, so zero it
* here to get a fresh slate.
*/
bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);
if (!acpi_disabled) {
riscv_fill_hwcap_from_isa_string(isa2hwcap);
} else {
@ -1245,7 +1294,6 @@ void riscv_clear_hypervisor_csr(void)
csr_clear(CSR_HSTATUS, HSTATUS_HU);
}
#ifdef CONFIG_RISCV_ALTERNATIVE
/*
* Alternative patch sites consider 48 bits when determining when to patch
* the old instruction sequence with the new. These bits are broken into a
@ -1279,6 +1327,17 @@ static bool riscv_cpufeature_patch_check(u16 id, u16 value)
return false;
}
static bool __init_or_module riscv_is_isa_ext_early_id(u16 id)
{
switch (id) {
case RISCV_ISA_EXT_SV48:
case RISCV_ISA_EXT_SV57:
return true;
}
return false;
}
void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
struct alt_entry *end,
unsigned int stage)
@ -1286,9 +1345,7 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
struct alt_entry *alt;
void *oldptr, *altptr;
u16 id, value, vendor;
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return;
bool early = stage == RISCV_ALTERNATIVES_EARLY_BOOT;
for (alt = begin; alt < end; alt++) {
id = PATCH_ID_CPUFEATURE_ID(alt->patch_id);
@ -1303,6 +1360,8 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
* vendor extension.
*/
if (id < RISCV_ISA_EXT_MAX) {
if (early && !riscv_is_isa_ext_early_id(id))
continue;
/*
* This patch should be treated as errata so skip
* processing here.
@ -1317,6 +1376,8 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
if (!riscv_cpufeature_patch_check(id, value))
continue;
} else if (id >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE) {
if (early)
continue;
if (!__riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor,
id - RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
continue;
@ -1328,10 +1389,20 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
oldptr = ALT_OLD_PTR(alt);
altptr = ALT_ALT_PTR(alt);
mutex_lock(&text_mutex);
patch_text_nosync(oldptr, altptr, alt->alt_len);
riscv_alternative_fix_offsets(oldptr, alt->alt_len, oldptr - altptr);
mutex_unlock(&text_mutex);
if (early) {
/* oldptr is writable through the MMU-off kernel mapping. */
memcpy(oldptr, altptr, alt->alt_len);
riscv_alternative_fix_offsets(oldptr, alt->alt_len,
oldptr - altptr, true);
} else {
mutex_lock(&text_mutex);
patch_text_nosync(oldptr, altptr, alt->alt_len);
riscv_alternative_fix_offsets(oldptr, alt->alt_len,
oldptr - altptr, false);
mutex_unlock(&text_mutex);
}
}
if (early)
local_flush_icache_all();
}
#endif

113
arch/riscv/kernel/crash.c Normal file
View File

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* RISC-V crash hotplug support
*
* Copyright (C) 2025 Bytedance Ltd.
*/
#include <linux/kexec.h>
#include <linux/crash_core.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#ifdef CONFIG_CRASH_HOTPLUG
#undef pr_fmt
#define pr_fmt(fmt) "crash hp: " fmt
int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
{
#ifdef CONFIG_KEXEC_FILE
if (image->file_mode)
return 1;
#endif
/*
* For the kexec_load() syscall path, the user space kexec tool
* needs to indicate that the elfcorehdr segment is excluded from
* SHA verification by setting the appropriate flags.
*/
return (kexec_flags & KEXEC_UPDATE_ELFCOREHDR ||
kexec_flags & KEXEC_CRASH_HOTPLUG_SUPPORT);
}
unsigned int arch_crash_get_elfcorehdr_size(void)
{
unsigned int sz;
/* kernel_map, VMCOREINFO and maximum CPUs */
sz = 2 + CONFIG_NR_CPUS;
if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
sz += CONFIG_CRASH_MAX_MEMORY_RANGES;
sz *= sizeof(Elf64_Phdr);
return sz;
}
/**
* arch_crash_handle_hotplug_event() - Handle hotplug elfcorehdr changes
* @image: a pointer to kexec_crash_image
* @arg: struct memory_notify handler for memory hotplug case and
* NULL for CPU hotplug case.
*
* Prepare the new elfcorehdr and replace the existing elfcorehdr.
*/
void arch_crash_handle_hotplug_event(struct kimage *image, void *arg)
{
void *elfbuf = NULL, *old_elfcorehdr;
unsigned long mem, memsz;
unsigned long elfsz = 0;
/*
* As crash_prepare_elf64_headers() has already described all
* possible CPUs, there is no need to update the elfcorehdr
* for additional CPU changes.
*/
if ((image->file_mode || image->elfcorehdr_updated) &&
((image->hp_action == KEXEC_CRASH_HP_ADD_CPU) ||
(image->hp_action == KEXEC_CRASH_HP_REMOVE_CPU)))
return;
/*
* Create the new elfcorehdr reflecting the changes to CPU and/or
* memory resources.
*/
if (crash_prepare_headers(true, &elfbuf, &elfsz, NULL)) {
pr_err("unable to create new elfcorehdr");
goto out;
}
/*
* Obtain address and size of the elfcorehdr segment, and
* check it against the new elfcorehdr buffer.
*/
mem = image->segment[image->elfcorehdr_index].mem;
memsz = image->segment[image->elfcorehdr_index].memsz;
if (elfsz > memsz) {
pr_err("update elfcorehdr elfsz %lu > memsz %lu",
elfsz, memsz);
goto out;
}
/*
* Copy new elfcorehdr over the old elfcorehdr at destination.
*/
old_elfcorehdr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
if (!old_elfcorehdr) {
pr_err("mapping elfcorehdr segment failed\n");
goto out;
}
/*
* Temporarily invalidate the crash image while the
* elfcorehdr is updated.
*/
xchg(&kexec_crash_image, NULL);
memcpy_flushcache(old_elfcorehdr, elfbuf, elfsz);
xchg(&kexec_crash_image, image);
kunmap_local(old_elfcorehdr);
pr_debug("updated elfcorehdr\n");
out:
vfree(elfbuf);
}
#endif /* CONFIG_CRASH_HOTPLUG */

View File

@ -15,6 +15,8 @@
#include <asm/image.h>
#include <asm/scs.h>
#include <asm/usercfi.h>
#include <asm/alternative.h>
#include <asm/errata_list.h>
#include "efi-header.S"
__HEAD
@ -189,7 +191,7 @@ secondary_start_sbi:
* - receive an early trap, before setup_trap_vector finished
* - fail in smp_callin(), as a successful one wouldn't return
*/
wfi
ALT_WFI
j .Lsecondary_park
.align 2

View File

@ -182,14 +182,6 @@ static int riscv_v_start_kernel_context(void)
get_cpu_vector_context();
__riscv_flush_vector_context();
put_cpu_vector_context();
/*
* A voluntary context switch caused by put_cpu_vector_context() can
* raise the NEED_RESTORE flag if preempt_v starts too early due to a
* failed risv_v_is_on() check.
*
* This causes the next context_nesting_end pollute the v-reg from
* the stale context memory in kernel-mode vector.
*/
riscv_v_start(RISCV_PREEMPT_V);
return 0;
}
@ -227,6 +219,7 @@ asmlinkage void riscv_v_context_nesting_end(struct pt_regs *regs)
__riscv_v_vstate_clean(regs);
riscv_preempt_v_reset_flags();
}
riscv_preempt_v_clear_dirty(current);
}
}
#else

View File

@ -51,7 +51,7 @@ static int sbi_sta_steal_time_set_shmem(unsigned long lo, unsigned long hi,
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_STA, SBI_EXT_STA_STEAL_TIME_SET_SHMEM,
lo, hi, flags, 0, 0, 0);
lo, hi, flags);
if (ret.error) {
if (lo == SBI_SHMEM_DISABLE && hi == SBI_SHMEM_DISABLE)
pr_warn("Failed to disable steal-time shmem");

View File

@ -302,6 +302,18 @@ enum {
static bool have_user_pmlen_7;
static bool have_user_pmlen_16;
bool riscv_have_user_pmlen(u8 len)
{
switch (len) {
case PMLEN_7:
return have_user_pmlen_7;
case PMLEN_16:
return have_user_pmlen_16;
default:
return false;
}
}
/*
* Control the relaxed ABI allowing tagged user addresses into the kernel.
*/

View File

@ -57,7 +57,7 @@ static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mas
*/
void sbi_console_putchar(int ch)
{
sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0);
sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch);
}
EXPORT_SYMBOL(sbi_console_putchar);
@ -70,7 +70,7 @@ int sbi_console_getchar(void)
{
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0, 0, 0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0);
return ret.error;
}
@ -83,7 +83,7 @@ EXPORT_SYMBOL(sbi_console_getchar);
*/
void sbi_shutdown(void)
{
sbi_ecall(SBI_EXT_0_1_SHUTDOWN, 0, 0, 0, 0, 0, 0, 0);
sbi_ecall(SBI_EXT_0_1_SHUTDOWN, 0);
}
EXPORT_SYMBOL(sbi_shutdown);
@ -97,9 +97,9 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
{
#if __riscv_xlen == 32
sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value,
stime_value >> 32, 0, 0, 0, 0);
stime_value >> 32);
#else
sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value, 0, 0, 0, 0, 0);
sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value);
#endif
}
@ -107,8 +107,7 @@ static void __sbi_send_ipi_v01(unsigned int cpu)
{
unsigned long hart_mask =
__sbi_v01_cpumask_to_hartmask(cpumask_of(cpu));
sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)(&hart_mask),
0, 0, 0, 0, 0);
sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)(&hart_mask));
}
static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
@ -126,17 +125,16 @@ static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
switch (fid) {
case SBI_EXT_RFENCE_REMOTE_FENCE_I:
sbi_ecall(SBI_EXT_0_1_REMOTE_FENCE_I, 0,
(unsigned long)&hart_mask, 0, 0, 0, 0, 0);
(unsigned long)&hart_mask);
break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA, 0,
(unsigned long)&hart_mask, start, size,
0, 0, 0);
(unsigned long)&hart_mask, start, size);
break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, 0,
(unsigned long)&hart_mask, start, size,
arg4, 0, 0);
arg4);
break;
default:
pr_err("SBI call [%d]not supported in SBI v0.1\n", fid);
@ -180,10 +178,9 @@ static void __sbi_set_timer_v02(uint64_t stime_value)
{
#if __riscv_xlen == 32
sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value,
stime_value >> 32, 0, 0, 0, 0);
stime_value >> 32);
#else
sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0,
0, 0, 0, 0);
sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value);
#endif
}
@ -193,7 +190,7 @@ static void __sbi_send_ipi_v02(unsigned int cpu)
struct sbiret ret = {0};
ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
1UL, cpuid_to_hartid_map(cpu), 0, 0, 0, 0);
1UL, cpuid_to_hartid_map(cpu));
if (ret.error) {
result = sbi_err_map_linux_errno(ret.error);
pr_err("%s: hbase = [%lu] failed (error [%d])\n",
@ -212,32 +209,32 @@ static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask,
switch (fid) {
case SBI_EXT_RFENCE_REMOTE_FENCE_I:
ret = sbi_ecall(ext, fid, hmask, hbase, 0, 0, 0, 0);
ret = sbi_ecall(ext, fid, hmask, hbase);
break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, 0, 0);
size);
break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, arg4, 0);
size, arg4);
break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, 0, 0);
size);
break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, arg4, 0);
size, arg4);
break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, 0, 0);
size);
break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, arg4, 0);
size, arg4);
break;
default:
pr_err("unknown function ID [%lu] for SBI extension [%d]\n",
@ -334,7 +331,7 @@ int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
return -EOPNOTSUPP;
ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
feature, value, flags, 0, 0, 0);
feature, value, flags);
return sbi_err_map_linux_errno(ret.error);
}
@ -510,8 +507,7 @@ EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid);
static void sbi_srst_reset(unsigned long type, unsigned long reason)
{
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason,
0, 0, 0, 0);
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason);
pr_warn("%s: type=0x%lx reason=0x%lx failed\n",
__func__, type, reason);
}
@ -544,8 +540,7 @@ long sbi_probe_extension(int extid)
{
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid,
0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid);
if (!ret.error)
return ret.value;
@ -607,10 +602,10 @@ int sbi_debug_console_write(const char *bytes, unsigned int num_bytes)
if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
num_bytes, lower_32_bits(base_addr),
upper_32_bits(base_addr), 0, 0, 0);
upper_32_bits(base_addr));
else
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
num_bytes, base_addr, 0, 0, 0, 0);
num_bytes, base_addr, 0);
if (ret.error == SBI_ERR_FAILURE)
return -EIO;
@ -636,10 +631,10 @@ int sbi_debug_console_read(char *bytes, unsigned int num_bytes)
if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
num_bytes, lower_32_bits(base_addr),
upper_32_bits(base_addr), 0, 0, 0);
upper_32_bits(base_addr));
else
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
num_bytes, base_addr, 0, 0, 0, 0);
num_bytes, base_addr, 0);
if (ret.error == SBI_ERR_FAILURE)
return -EIO;

View File

@ -9,7 +9,7 @@ long __sbi_base_ecall(int fid)
{
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_BASE, fid);
if (!ret.error)
return ret.value;
else
@ -17,32 +17,18 @@ long __sbi_base_ecall(int fid)
}
EXPORT_SYMBOL(__sbi_base_ecall);
struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5,
int fid, int ext)
#ifdef CONFIG_TRACEPOINTS
void do_trace_sbi_call(int ext, int fid)
{
struct sbiret ret;
trace_sbi_call(ext, fid);
register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
asm volatile ("ecall"
: "+r" (a0), "+r" (a1)
: "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
: "memory");
ret.error = a0;
ret.value = a1;
trace_sbi_return(ext, ret.error, ret.value);
return ret;
}
EXPORT_SYMBOL(__sbi_ecall);
EXPORT_SYMBOL(do_trace_sbi_call);
EXPORT_TRACEPOINT_SYMBOL(sbi_call);
void do_trace_sbi_return(int ext, long error, long value)
{
trace_sbi_return(ext, error, value);
}
EXPORT_SYMBOL(do_trace_sbi_return);
EXPORT_TRACEPOINT_SYMBOL(sbi_return);
#endif

View File

@ -15,7 +15,6 @@
#include <linux/kexec.h>
#include <linux/kgdb.h>
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/smp.h>
#include <linux/sched.h>
#include <linux/seq_file.h>

View File

@ -118,7 +118,7 @@ static int sbi_system_suspend(unsigned long sleep_type,
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_SUSP, SBI_EXT_SUSP_SYSTEM_SUSPEND,
sleep_type, resume_addr, opaque, 0, 0, 0);
sleep_type, resume_addr, opaque);
if (ret.error)
return sbi_err_map_linux_errno(ret.error);
@ -156,7 +156,7 @@ static int sbi_suspend_finisher(unsigned long suspend_type,
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_SUSPEND,
suspend_type, resume_addr, opaque, 0, 0, 0);
suspend_type, resume_addr, opaque);
return (ret.error) ? sbi_err_map_linux_errno(ret.error) : 0;
}

View File

@ -207,6 +207,8 @@ static void hwprobe_isa_ext1(struct riscv_hwprobe *pair,
EXT_KEY(isainfo->isa, ZICCIF, pair->value, missing);
EXT_KEY(isainfo->isa, ZICCRSE, pair->value, missing);
EXT_KEY(isainfo->isa, ZA64RS, pair->value, missing);
EXT_KEY(isainfo->isa, B, pair->value, missing);
EXT_KEY(isainfo->isa, ZIC64B, pair->value, missing);
}
/* Now turn off reporting features if any CPU is missing it. */

View File

@ -15,6 +15,7 @@
#include <linux/syscalls.h>
#include <linux/prctl.h>
#include <asm/csr.h>
#include <asm/switch_to.h>
#include <asm/usercfi.h>
unsigned long riscv_nousercfi __read_mostly;
@ -66,12 +67,7 @@ void set_shstk_status(struct task_struct *task, bool enable)
task->thread_info.user_cfi_state.ubcfi_en = enable ? 1 : 0;
if (enable)
task->thread.envcfg |= ENVCFG_SSE;
else
task->thread.envcfg &= ~ENVCFG_SSE;
csr_write(CSR_ENVCFG, task->thread.envcfg);
envcfg_update_bits(task, ENVCFG_SSE, enable ? ENVCFG_SSE : 0);
}
void set_shstk_lock(struct task_struct *task, bool lock)
@ -96,12 +92,7 @@ void set_indir_lp_status(struct task_struct *task, bool enable)
task->thread_info.user_cfi_state.ufcfi_en = enable ? 1 : 0;
if (enable)
task->thread.envcfg |= ENVCFG_LPE;
else
task->thread.envcfg &= ~ENVCFG_LPE;
csr_write(CSR_ENVCFG, task->thread.envcfg);
envcfg_update_bits(task, ENVCFG_LPE, enable ? ENVCFG_LPE : 0);
}
void set_indir_lp_lock(struct task_struct *task, bool lock)
@ -206,10 +197,13 @@ int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr)
*/
int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr)
{
unsigned long __user *token_ptr = (unsigned long __user *)shstk_ptr;
unsigned long token = 0;
token = amo_user_shstk((unsigned long __user *)shstk_ptr, 0);
if (!access_ok(token_ptr, sizeof(token)))
return -EFAULT;
token = amo_user_shstk(token_ptr, 0);
if (token == -1)
return -EFAULT;

View File

@ -73,7 +73,7 @@ int kvm_riscv_nacl_enable(void)
nacl = this_cpu_ptr(&kvm_riscv_nacl);
ret = sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SET_SHMEM,
nacl->shmem_phys, 0, 0, 0, 0, 0);
nacl->shmem_phys, 0, 0);
rc = sbi_err_map_linux_errno(ret.error);
if (rc)
return rc;
@ -87,7 +87,7 @@ void kvm_riscv_nacl_disable(void)
return;
sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SET_SHMEM,
SBI_SHMEM_DISABLE, SBI_SHMEM_DISABLE, 0, 0, 0, 0);
SBI_SHMEM_DISABLE, SBI_SHMEM_DISABLE, 0);
}
void kvm_riscv_nacl_exit(void)
@ -118,8 +118,7 @@ static long nacl_probe_feature(long feature_id)
if (!kvm_riscv_nacl_available())
return 0;
ret = sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_PROBE_FEATURE,
feature_id, 0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_PROBE_FEATURE, feature_id);
return ret.value;
}

View File

@ -5,6 +5,7 @@
#include <asm/csr.h>
#include <asm/hwcap.h>
#include <asm/alternative-macros.h>
#include <asm/jump_label.h>
.macro fixup op reg addr lbl
100:
@ -77,33 +78,11 @@ SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)
bltu a2, a3, .Lbyte_copy_tail
#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
/*
* Copy first bytes until dst is aligned to word boundary.
* a0 - start of dst
* t1 - start of aligned dst
*/
addi t1, a0, SZREG-1
andi t1, t1, ~(SZREG-1)
/* dst is already aligned, skip */
beq a0, t1, .Lskip_align_dst
1:
/* a5 - one byte for copying data */
fixup lb a5, 0(a1), 10f
addi a1, a1, 1 /* src */
fixup sb a5, 0(a0), 10f
addi a0, a0, 1 /* dst */
bltu a0, t1, 1b /* t1 - start of aligned dst */
.Lskip_align_dst:
/*
* Now dst is aligned.
* Use shift-copy if src is misaligned.
* Use word-copy if both src and dst are aligned because
* can not use shift-copy which do not require shifting
*/
/* a1 - start of src */
andi a3, a1, SZREG-1
bnez a3, .Lshift_copy
#if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS) && defined(CONFIG_JUMP_LABEL)
ARCH_STATIC_BRANCH_JUMP_ASM(fast_unaligned_access_speed_key + 1, .Lalign_dst)
#else
j .Lalign_dst
#endif
#endif
.Lword_copy:
/*
@ -139,6 +118,34 @@ SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)
j .Lbyte_copy_tail
#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
.Lalign_dst:
/*
* Copy first bytes until dst is aligned to word boundary.
* a0 - start of dst
* t1 - start of aligned dst
*/
addi t1, a0, SZREG-1
andi t1, t1, ~(SZREG-1)
/* dst is already aligned, skip */
beq a0, t1, .Lskip_align_dst
1:
/* a5 - one byte for copying data */
fixup lb a5, 0(a1), 10f
addi a1, a1, 1 /* src */
fixup sb a5, 0(a0), 10f
addi a0, a0, 1 /* dst */
bltu a0, t1, 1b /* t1 - start of aligned dst */
.Lskip_align_dst:
/*
* Now dst is aligned.
* Use shift-copy if src is misaligned.
* Use word-copy if both src and dst are aligned because
* can not use shift-copy which do not require shifting
*/
/* a1 - start of src */
andi a3, a1, SZREG-1
beqz a3, .Lword_copy
.Lshift_copy:
/*

View File

@ -6,6 +6,11 @@
* Nick Kossifidis <mick@ics.forth.gr>
*/
#ifdef CONFIG_64BIT
/* riscv_has_extension_likely() cannot be used this early */
#define USE_EARLY_PGTABLE_LEVELS
#endif
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/memblock.h>
@ -53,10 +58,8 @@ u64 satp_mode __ro_after_init = SATP_MODE_32;
EXPORT_SYMBOL(satp_mode);
#ifdef CONFIG_64BIT
bool pgtable_l4_enabled __ro_after_init = true;
bool pgtable_l5_enabled __ro_after_init = true;
EXPORT_SYMBOL(pgtable_l4_enabled);
EXPORT_SYMBOL(pgtable_l5_enabled);
bool _pgtable_l4_enabled __ro_after_init = true;
bool _pgtable_l5_enabled __ro_after_init = true;
#endif
phys_addr_t phys_ram_base __ro_after_init;
@ -653,23 +656,23 @@ static void __meminit create_p4d_mapping(p4d_t *p4dp, uintptr_t va, phys_addr_t
}
#define pgd_next_t p4d_t
#define alloc_pgd_next(__va) (pgtable_l5_enabled ? \
pt_ops.alloc_p4d(__va) : (pgtable_l4_enabled ? \
#define alloc_pgd_next(__va) (pgtable_l5_enabled() ? \
pt_ops.alloc_p4d(__va) : (pgtable_l4_enabled() ? \
pt_ops.alloc_pud(__va) : pt_ops.alloc_pmd(__va)))
#define get_pgd_next_virt(__pa) (pgtable_l5_enabled ? \
pt_ops.get_p4d_virt(__pa) : (pgd_next_t *)(pgtable_l4_enabled ? \
#define get_pgd_next_virt(__pa) (pgtable_l5_enabled() ? \
pt_ops.get_p4d_virt(__pa) : (pgd_next_t *)(pgtable_l4_enabled() ? \
pt_ops.get_pud_virt(__pa) : (pud_t *)pt_ops.get_pmd_virt(__pa)))
#define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \
(pgtable_l5_enabled ? \
(pgtable_l5_enabled() ? \
create_p4d_mapping(__nextp, __va, __pa, __sz, __prot) : \
(pgtable_l4_enabled ? \
(pgtable_l4_enabled() ? \
create_pud_mapping((pud_t *)__nextp, __va, __pa, __sz, __prot) : \
create_pmd_mapping((pmd_t *)__nextp, __va, __pa, __sz, __prot)))
#define fixmap_pgd_next (pgtable_l5_enabled ? \
(uintptr_t)fixmap_p4d : (pgtable_l4_enabled ? \
#define fixmap_pgd_next (pgtable_l5_enabled() ? \
(uintptr_t)fixmap_p4d : (pgtable_l4_enabled() ? \
(uintptr_t)fixmap_pud : (uintptr_t)fixmap_pmd))
#define trampoline_pgd_next (pgtable_l5_enabled ? \
(uintptr_t)trampoline_p4d : (pgtable_l4_enabled ? \
#define trampoline_pgd_next (pgtable_l5_enabled() ? \
(uintptr_t)trampoline_p4d : (pgtable_l4_enabled() ? \
(uintptr_t)trampoline_pud : (uintptr_t)trampoline_pmd))
#else
#define pgd_next_t pte_t
@ -714,11 +717,11 @@ static uintptr_t __meminit best_map_size(phys_addr_t pa, uintptr_t va, phys_addr
if (debug_pagealloc_enabled())
return PAGE_SIZE;
if (pgtable_l5_enabled &&
if (pgtable_l5_enabled() &&
!(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE)
return P4D_SIZE;
if (pgtable_l4_enabled &&
if (pgtable_l4_enabled() &&
!(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE)
return PUD_SIZE;
@ -770,14 +773,14 @@ u64 __pi_set_satp_mode_from_fdt(uintptr_t dtb_pa);
static void __init disable_pgtable_l5(void)
{
pgtable_l5_enabled = false;
_pgtable_l5_enabled = false;
kernel_map.page_offset = PAGE_OFFSET_L4;
satp_mode = SATP_MODE_48;
}
static void __init disable_pgtable_l4(void)
{
pgtable_l4_enabled = false;
_pgtable_l4_enabled = false;
kernel_map.page_offset = PAGE_OFFSET_L3;
satp_mode = SATP_MODE_39;
}
@ -840,6 +843,14 @@ static __init void set_satp_mode(uintptr_t dtb_pa)
kernel_map.page_offset = PAGE_OFFSET_L5;
/* Fall back to SV48 if RISCV_ISA_SV57 isn't enabled */
if (!IS_ENABLED(CONFIG_RISCV_ISA_SV57) && satp_mode_limit == 0)
satp_mode_limit = SATP_MODE_48;
/* Fall back to SV39 if RISCV_ISA_SV48 isn't enabled */
if (!IS_ENABLED(CONFIG_RISCV_ISA_SV48) && satp_mode_limit == SATP_MODE_48)
satp_mode_limit = SATP_MODE_39;
if (satp_mode_limit == SATP_MODE_48) {
disable_pgtable_l5();
} else if (satp_mode_limit == SATP_MODE_39) {
@ -868,7 +879,7 @@ static __init void set_satp_mode(uintptr_t dtb_pa)
create_pgd_mapping(early_pg_dir,
set_satp_mode_pmd,
pgtable_l5_enabled ?
pgtable_l5_enabled() ?
(uintptr_t)early_p4d : (uintptr_t)early_pud,
PGDIR_SIZE, PAGE_TABLE);
@ -880,7 +891,7 @@ static __init void set_satp_mode(uintptr_t dtb_pa)
local_flush_tlb_all();
if (hw_satp != identity_satp) {
if (pgtable_l5_enabled) {
if (pgtable_l5_enabled()) {
disable_pgtable_l5();
memset(early_pg_dir, 0, PAGE_SIZE);
goto retry;
@ -893,6 +904,10 @@ static __init void set_satp_mode(uintptr_t dtb_pa)
memset(early_p4d, 0, PAGE_SIZE);
memset(early_pud, 0, PAGE_SIZE);
memset(early_pmd, 0, PAGE_SIZE);
if (pgtable_l4_enabled())
set_bit(RISCV_ISA_EXT_SV48, riscv_isa);
if (pgtable_l5_enabled())
set_bit(RISCV_ISA_EXT_SV57, riscv_isa);
}
#endif
@ -1121,11 +1136,11 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
#ifndef __PAGETABLE_PMD_FOLDED
/* Setup fixmap P4D and PUD */
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
create_p4d_mapping(fixmap_p4d, FIXADDR_START,
(uintptr_t)fixmap_pud, P4D_SIZE, PAGE_TABLE);
/* Setup fixmap PUD and PMD */
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
create_pud_mapping(fixmap_pud, FIXADDR_START,
(uintptr_t)fixmap_pmd, PUD_SIZE, PAGE_TABLE);
create_pmd_mapping(fixmap_pmd, FIXADDR_START,
@ -1133,10 +1148,10 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
/* Setup trampoline PGD and PMD */
create_pgd_mapping(trampoline_pg_dir, kernel_map.virt_addr,
trampoline_pgd_next, PGDIR_SIZE, PAGE_TABLE);
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
create_p4d_mapping(trampoline_p4d, kernel_map.virt_addr,
(uintptr_t)trampoline_pud, P4D_SIZE, PAGE_TABLE);
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
create_pud_mapping(trampoline_pud, kernel_map.virt_addr,
(uintptr_t)trampoline_pmd, PUD_SIZE, PAGE_TABLE);
create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr,
@ -1407,7 +1422,7 @@ static void __init preallocate_pgd_pages_range(unsigned long start, unsigned lon
if (!p4d)
goto failed;
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
continue;
lvl = "pud";
@ -1415,7 +1430,7 @@ static void __init preallocate_pgd_pages_range(unsigned long start, unsigned lon
if (!pud)
goto failed;
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
continue;
lvl = "pmd";
@ -1627,13 +1642,13 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
for (; addr < end; addr = next) {
next = pud_addr_end(addr, end);
pudp = pgtable_l4_enabled ? pud_base + pud_index(addr) : pud_base;
pudp = pgtable_l4_enabled() ? pud_base + pud_index(addr) : pud_base;
pud = pudp_get(pudp);
if (!pud_present(pud))
continue;
if (pud_leaf(pud)) {
if (pgtable_l4_enabled) {
if (pgtable_l4_enabled()) {
pud_clear(pudp);
if (is_vmemmap)
free_vmemmap_storage(pud_page(pud), PUD_SIZE, altmap);
@ -1644,7 +1659,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
pmd_base = pmd_offset(pudp, 0);
remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, altmap);
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
free_pmd_table(pmd_base, pudp, is_vmemmap);
}
}
@ -1658,13 +1673,13 @@ static void __meminit remove_p4d_mapping(p4d_t *p4d_base, unsigned long addr, un
for (; addr < end; addr = next) {
next = p4d_addr_end(addr, end);
p4dp = pgtable_l5_enabled ? p4d_base + p4d_index(addr) : p4d_base;
p4dp = pgtable_l5_enabled() ? p4d_base + p4d_index(addr) : p4d_base;
p4d = p4dp_get(p4dp);
if (!p4d_present(p4d))
continue;
if (p4d_leaf(p4d)) {
if (pgtable_l5_enabled) {
if (pgtable_l5_enabled()) {
p4d_clear(p4dp);
if (is_vmemmap)
free_vmemmap_storage(p4d_page(p4d), P4D_SIZE, altmap);
@ -1675,7 +1690,7 @@ static void __meminit remove_p4d_mapping(p4d_t *p4d_base, unsigned long addr, un
pud_base = pud_offset(p4dp, 0);
remove_pud_mapping(pud_base, addr, next, is_vmemmap, altmap);
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
free_pud_table(pud_base, p4dp);
}
}

View File

@ -168,7 +168,7 @@ static void __init kasan_early_clear_pud(p4d_t *p4dp,
pud_t *pudp, *base_pud;
unsigned long next;
if (!pgtable_l4_enabled) {
if (!pgtable_l4_enabled()) {
pudp = (pud_t *)p4dp;
} else {
base_pud = pt_ops.get_pud_virt(pfn_to_phys(_p4d_pfn(p4dp_get(p4dp))));
@ -193,7 +193,7 @@ static void __init kasan_early_clear_p4d(pgd_t *pgdp,
p4d_t *p4dp, *base_p4d;
unsigned long next;
if (!pgtable_l5_enabled) {
if (!pgtable_l5_enabled()) {
p4dp = (p4d_t *)pgdp;
} else {
base_p4d = pt_ops.get_p4d_virt(pfn_to_phys(_pgd_pfn(pgdp_get(pgdp))));
@ -203,7 +203,7 @@ static void __init kasan_early_clear_p4d(pgd_t *pgdp,
do {
next = p4d_addr_end(vaddr, end);
if (pgtable_l4_enabled && IS_ALIGNED(vaddr, P4D_SIZE) &&
if (pgtable_l4_enabled() && IS_ALIGNED(vaddr, P4D_SIZE) &&
(next - vaddr) >= P4D_SIZE) {
p4d_clear(p4dp);
continue;
@ -221,7 +221,7 @@ static void __init kasan_early_clear_pgd(pgd_t *pgdp,
do {
next = pgd_addr_end(vaddr, end);
if (pgtable_l5_enabled && IS_ALIGNED(vaddr, PGDIR_SIZE) &&
if (pgtable_l5_enabled() && IS_ALIGNED(vaddr, PGDIR_SIZE) &&
(next - vaddr) >= PGDIR_SIZE) {
pgd_clear(pgdp);
continue;
@ -239,7 +239,7 @@ static void __init kasan_early_populate_pud(p4d_t *p4dp,
phys_addr_t phys_addr;
unsigned long next;
if (!pgtable_l4_enabled) {
if (!pgtable_l4_enabled()) {
pudp = (pud_t *)p4dp;
} else {
base_pud = pt_ops.get_pud_virt(pfn_to_phys(_p4d_pfn(p4dp_get(p4dp))));
@ -277,7 +277,7 @@ static void __init kasan_early_populate_p4d(pgd_t *pgdp,
* Note that this test is then completely equivalent to
* p4dp = p4d_offset(pgdp, vaddr)
*/
if (!pgtable_l5_enabled) {
if (!pgtable_l5_enabled()) {
p4dp = (p4d_t *)pgdp;
} else {
base_p4d = pt_ops.get_p4d_virt(pfn_to_phys(_pgd_pfn(pgdp_get(pgdp))));
@ -336,7 +336,7 @@ asmlinkage void __init kasan_early_init(void)
(__pa((uintptr_t)kasan_early_shadow_pte)),
PAGE_TABLE));
if (pgtable_l4_enabled) {
if (pgtable_l4_enabled()) {
for (i = 0; i < PTRS_PER_PUD; ++i)
set_pud(kasan_early_shadow_pud + i,
pfn_pud(PFN_DOWN
@ -344,7 +344,7 @@ asmlinkage void __init kasan_early_init(void)
PAGE_TABLE));
}
if (pgtable_l5_enabled) {
if (pgtable_l5_enabled()) {
for (i = 0; i < PTRS_PER_P4D; ++i)
set_p4d(kasan_early_shadow_p4d + i,
pfn_p4d(PFN_DOWN
@ -461,7 +461,7 @@ static void __init create_tmp_mapping(void)
memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(pgd_t) * PTRS_PER_PGD);
/* Copy the last p4d since it is shared with the kernel mapping. */
if (pgtable_l5_enabled) {
if (pgtable_l5_enabled()) {
ptr = (p4d_t *)pgd_page_vaddr(pgdp_get(pgd_offset_k(KASAN_SHADOW_END)));
memcpy(tmp_p4d, ptr, sizeof(p4d_t) * PTRS_PER_P4D);
set_pgd(&tmp_pg_dir[pgd_index(KASAN_SHADOW_END)],
@ -472,7 +472,7 @@ static void __init create_tmp_mapping(void)
}
/* Copy the last pud since it is shared with the kernel mapping. */
if (pgtable_l4_enabled) {
if (pgtable_l4_enabled()) {
ptr = (pud_t *)p4d_page_vaddr(p4dp_get(base_p4d + p4d_index(KASAN_SHADOW_END)));
memcpy(tmp_pud, ptr, sizeof(pud_t) * PTRS_PER_PUD);
set_p4d(&base_p4d[p4d_index(KASAN_SHADOW_END)],

View File

@ -41,7 +41,7 @@ EXPORT_SYMBOL_GPL(ptep_test_and_clear_young);
#ifdef CONFIG_64BIT
pud_t *pud_offset(p4d_t *p4d, unsigned long address)
{
if (pgtable_l4_enabled)
if (pgtable_l4_enabled())
return p4d_pgtable(p4dp_get(p4d)) + pud_index(address);
return (pud_t *)p4d;
@ -50,7 +50,7 @@ EXPORT_SYMBOL_GPL(pud_offset);
p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
{
if (pgtable_l5_enabled)
if (pgtable_l5_enabled())
return pgd_pgtable(pgdp_get(pgd)) + p4d_index(address);
return (p4d_t *)pgd;

View File

@ -446,8 +446,8 @@ static int __init ptdump_init(void)
kernel_ptd_info.base_addr = KERN_VIRT_START;
pg_level[1].name = pgtable_l5_enabled ? "P4D" : "PGD";
pg_level[2].name = pgtable_l4_enabled ? "PUD" : "PGD";
pg_level[1].name = pgtable_l5_enabled() ? "P4D" : "PGD";
pg_level[2].name = pgtable_l4_enabled() ? "PUD" : "PGD";
for (i = 0; i < ARRAY_SIZE(pg_level); i++)
for (j = 0; j < ARRAY_SIZE(pte_bits); j++)

View File

@ -51,7 +51,7 @@ static void sbi_cppc_read(void *read_data)
struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
data->ret = sbi_ecall(SBI_EXT_CPPC, SBI_CPPC_READ,
data->reg, 0, 0, 0, 0, 0);
data->reg);
}
static void sbi_cppc_write(void *write_data)
@ -59,7 +59,7 @@ static void sbi_cppc_write(void *write_data)
struct sbi_cppc_data *data = (struct sbi_cppc_data *)write_data;
data->ret = sbi_ecall(SBI_EXT_CPPC, SBI_CPPC_WRITE,
data->reg, data->val, 0, 0, 0, 0);
data->reg, data->val);
}
static void cppc_ffh_csr_read(void *read_data)

View File

@ -386,7 +386,7 @@ static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata)
edata->event_idx, 0);
if (!ret.error) {
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
ret.value, 0x1, SBI_PMU_STOP_FLAG_RESET, 0, 0, 0);
ret.value, 0x1, SBI_PMU_STOP_FLAG_RESET);
return;
}
}
@ -722,7 +722,7 @@ static int pmu_sbi_snapshot_disable(void)
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_SNAPSHOT_SET_SHMEM, SBI_SHMEM_DISABLE,
SBI_SHMEM_DISABLE, 0, 0, 0, 0);
SBI_SHMEM_DISABLE, 0);
if (ret.error) {
pr_warn("failed to disable snapshot shared memory\n");
return sbi_err_map_linux_errno(ret.error);
@ -746,10 +746,11 @@ static int pmu_sbi_snapshot_setup(struct riscv_pmu *pmu, int cpu)
if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_SNAPSHOT_SET_SHMEM,
cpu_hw_evt->snapshot_addr_phys,
(u64)(cpu_hw_evt->snapshot_addr_phys) >> 32, 0, 0, 0, 0);
(u64)(cpu_hw_evt->snapshot_addr_phys) >> 32,
0);
else
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_SNAPSHOT_SET_SHMEM,
cpu_hw_evt->snapshot_addr_phys, 0, 0, 0, 0, 0);
cpu_hw_evt->snapshot_addr_phys, 0, 0);
/* Free up the snapshot area memory and fall back to SBI PMU calls without snapshot */
if (ret.error) {
@ -783,14 +784,14 @@ static u64 pmu_sbi_ctr_read(struct perf_event *event)
if (pmu_sbi_is_fw_event(event)) {
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ,
hwc->idx, 0, 0, 0, 0, 0);
hwc->idx);
if (ret.error)
return 0;
val = ret.value;
if (IS_ENABLED(CONFIG_32BIT) && sbi_v2_available && info.width >= 32) {
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ_HI,
hwc->idx, 0, 0, 0, 0, 0);
hwc->idx);
if (!ret.error)
val |= ((u64)ret.value << 32);
else
@ -833,10 +834,10 @@ static void pmu_sbi_ctr_start(struct perf_event *event, u64 ival)
/* There is no benefit setting SNAPSHOT FLAG for a single counter */
#if defined(CONFIG_32BIT)
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, hwc->idx,
1, flag, ival, ival >> 32, 0);
1, flag, ival, ival >> 32);
#else
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, hwc->idx,
1, flag, ival, 0, 0);
1, flag, ival);
#endif
if (ret.error && (ret.error != SBI_ERR_ALREADY_STARTED))
pr_err("Starting counter idx %d failed with error %d\n",
@ -862,7 +863,8 @@ static void pmu_sbi_ctr_stop(struct perf_event *event, unsigned long flag)
if (sbi_pmu_snapshot_available())
flag |= SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT;
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, hwc->idx, 1, flag, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
hwc->idx, 1, flag);
if (!ret.error && sbi_pmu_snapshot_available()) {
/*
* The counter snapshot is based on the index base specified by hwc->idx.
@ -887,7 +889,7 @@ static int pmu_sbi_find_num_ctrs(void)
{
struct sbiret ret;
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_NUM_COUNTERS, 0, 0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_NUM_COUNTERS);
if (!ret.error)
return ret.value;
else
@ -905,7 +907,7 @@ static int pmu_sbi_get_ctrinfo(int nctr, unsigned long *mask)
return -ENOMEM;
for (i = 0; i < nctr; i++) {
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i);
if (ret.error)
/* The logical counter ids are not expected to be contiguous */
continue;
@ -938,7 +940,7 @@ static inline void pmu_sbi_stop_all(struct riscv_pmu *pmu)
continue;
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
i * BITS_PER_LONG, pmu->cmask[i],
SBI_PMU_STOP_FLAG_RESET, 0, 0, 0);
SBI_PMU_STOP_FLAG_RESET);
}
}
@ -960,7 +962,7 @@ static inline void pmu_sbi_stop_hw_ctrs(struct riscv_pmu *pmu)
for (i = 0; i < BITS_TO_LONGS(RISCV_MAX_COUNTERS); i++) {
/* No need to check the error here as we can't do anything about the error */
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, i * BITS_PER_LONG,
cpu_hw_evt->used_hw_ctrs[i], flag, 0, 0, 0);
cpu_hw_evt->used_hw_ctrs[i], flag);
if (!ret.error && sbi_pmu_snapshot_available()) {
/* Save the counter values to avoid clobbering */
for_each_set_bit(idx, &cpu_hw_evt->used_hw_ctrs[i], BITS_PER_LONG)
@ -1002,7 +1004,7 @@ static inline void pmu_sbi_start_ovf_ctrs_sbi(struct cpu_hw_events *cpu_hw_evt,
/* Start all the counters that did not overflow in a single shot */
if (ctr_start_mask) {
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, i * BITS_PER_LONG,
ctr_start_mask, 0, 0, 0, 0);
ctr_start_mask, 0);
}
}
@ -1014,11 +1016,11 @@ static inline void pmu_sbi_start_ovf_ctrs_sbi(struct cpu_hw_events *cpu_hw_evt,
max_period = riscv_pmu_ctr_get_width_mask(event);
init_val = local64_read(&hwc->prev_count) & max_period;
#if defined(CONFIG_32BIT)
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx, 1,
flag, init_val, init_val >> 32, 0);
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx,
1, flag, init_val, init_val >> 32);
#else
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx, 1,
flag, init_val, 0, 0);
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx,
1, flag, init_val);
#endif
perf_event_update_userpage(event);
}
@ -1057,8 +1059,9 @@ static inline void pmu_sbi_start_ovf_ctrs_snapshot(struct cpu_hw_events *cpu_hw_
sdata->ctr_values[idx] =
cpu_hw_evt->snapshot_cval_shcopy[idx + i * BITS_PER_LONG];
/* Start all the counters in a single shot */
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, idx * BITS_PER_LONG,
cpu_hw_evt->used_hw_ctrs[i], flag, 0, 0, 0);
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START,
idx * BITS_PER_LONG,
cpu_hw_evt->used_hw_ctrs[i], flag);
}
}

View File

@ -2,7 +2,8 @@
# Copyright (C) 2021 ARM Limited
# Originally tools/testing/arm64/abi/Makefile
TEST_GEN_PROGS := v_initval vstate_prctl vstate_ptrace validate_v_ptrace
TEST_GEN_PROGS := v_initval vstate_prctl vstate_ptrace validate_v_ptrace \
v_uaccess_stress
TEST_GEN_PROGS_EXTENDED := vstate_exec_nolibc v_exec_initval_nolibc
TEST_GEN_LIBS := v_helpers.c sys_hwprobe.c
@ -36,4 +37,7 @@ $(OUTPUT)/vstate_ptrace: vstate_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_hel
$(OUTPUT)/validate_v_ptrace: validate_v_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
$(OUTPUT)/v_uaccess_stress: v_uaccess_stress.c
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
EXTRA_CLEAN += $(TEST_GEN_OBJ)

View File

@ -0,0 +1,221 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Stress the kernel's user copy path from several processes at once.
*
* Each child pushes a 1KiB pseudo-random byte stream through a pipe: write()
* copies it from user space into the kernel (copy_from_user()) and read()
* copies it back out (copy_to_user()). The round trip is repeated 512 times
* per child, and every iteration the buffers are shifted so that the copies
* cover all of the source/destination alignment combinations.
*
* On RISC-V those copies may be serviced by kernel-mode vector routines, so
* the payload is generated and verified with plain scalar loads and stores
* only. The comparison goes through volatile pointers, which keeps both GCC
* and clang from turning the loop into a vectorised compare and keeps the
* check independent of the user vector state the kernel is supposed to
* preserve. memcmp() is avoided for the same reason: the libc version is free
* to use vector instructions.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include "kselftest_harness.h"
#define ITERATIONS 32768
#define STREAM_SIZE 1024
#define MAX_SHIFT 16
#define BUF_SIZE (STREAM_SIZE + MAX_SHIFT)
#define CONCURRENCY 16
/* xorshift64*, so the payload does not depend on any libc or kernel helper. */
static unsigned long prng_state;
static unsigned long prng_next(void)
{
prng_state ^= prng_state >> 12;
prng_state ^= prng_state << 25;
prng_state ^= prng_state >> 27;
return prng_state * 2685821657736338717UL;
}
static void fill_random(unsigned char *buf, size_t len)
{
size_t i;
for (i = 0; i < len; i++)
buf[i] = (unsigned char)(prng_next() >> 24);
}
/*
* Scalar, byte at a time comparison. Returns the offset of the first
* mismatching byte, or len when the two streams are identical.
*/
static size_t scalar_diff(const unsigned char *a, const unsigned char *b,
size_t len)
{
const volatile unsigned char *va = a;
const volatile unsigned char *vb = b;
size_t i;
for (i = 0; i < len; i++) {
if (va[i] != vb[i])
break;
}
return i;
}
static ssize_t write_all(int fd, const unsigned char *buf, size_t len)
{
size_t done = 0;
while (done < len) {
ssize_t ret = write(fd, buf + done, len - done);
if (ret < 0) {
if (errno == EINTR)
continue;
return -1;
}
done += ret;
}
return done;
}
static ssize_t read_all(int fd, unsigned char *buf, size_t len)
{
size_t done = 0;
while (done < len) {
ssize_t ret = read(fd, buf + done, len - done);
if (ret < 0) {
if (errno == EINTR)
continue;
return -1;
}
if (ret == 0)
return -1;
done += ret;
}
return done;
}
/* Runs in the child. Returns the exit status to hand back to the parent. */
static int child_loop(unsigned long seed)
{
unsigned char src[BUF_SIZE], dst[BUF_SIZE];
int pipefd[2];
int i;
prng_state = seed;
if (pipe(pipefd)) {
fprintf(stderr, "pid %d: pipe() failed: %s\n",
getpid(), strerror(errno));
return 1;
}
for (i = 0; i < ITERATIONS; i++) {
/*
* Walk the source and destination through every relative
* alignment, including the case where both are equally
* misaligned.
*/
unsigned char *in = src + (i % MAX_SHIFT);
unsigned char *out = dst + ((i / MAX_SHIFT) % MAX_SHIFT);
size_t off;
fill_random(in, STREAM_SIZE);
memset(out, 0, STREAM_SIZE);
if (write_all(pipefd[1], in, STREAM_SIZE) < 0) {
fprintf(stderr, "pid %d: iteration %d: write() failed: %s\n",
getpid(), i, strerror(errno));
return 1;
}
if (read_all(pipefd[0], out, STREAM_SIZE) < 0) {
fprintf(stderr, "pid %d: iteration %d: read() failed: %s\n",
getpid(), i, strerror(errno));
return 1;
}
off = scalar_diff(in, out, STREAM_SIZE);
if (off != STREAM_SIZE) {
fprintf(stderr,
"pid %d: iteration %d: mismatch at byte %zu of %d (in %p, out %p): expected 0x%02x, got 0x%02x\n",
getpid(), i, off, STREAM_SIZE, in, out,
in[off], out[off]);
return 1;
}
}
close(pipefd[0]);
close(pipefd[1]);
return 0;
}
static int nr_children(void)
{
long online = sysconf(_SC_NPROCESSORS_ONLN);
return online * CONCURRENCY;
}
TEST(uaccess_round_trip)
{
int nr = nr_children();
int failures = 0;
pid_t pids[nr];
int i;
ksft_print_msg("%d children, %d iterations of %d bytes each\n",
nr, ITERATIONS, STREAM_SIZE);
for (i = 0; i < nr; i++) {
pids[i] = fork();
ASSERT_LE(0, pids[i]) {
TH_LOG("fork() failed: %s", strerror(errno));
}
if (pids[i] == 0) {
/* A distinct, reproducible stream per child. */
_exit(child_loop(0x9e3779b97f4a7c15UL + i));
}
}
for (i = 0; i < nr; i++) {
int status;
if (waitpid(pids[i], &status, 0) < 0) {
TH_LOG("waitpid(%d) failed: %s", pids[i],
strerror(errno));
failures++;
continue;
}
if (WIFSIGNALED(status)) {
TH_LOG("child %d killed by signal %d", pids[i],
WTERMSIG(status));
failures++;
} else if (!WIFEXITED(status) || WEXITSTATUS(status)) {
TH_LOG("child %d failed", pids[i]);
failures++;
}
}
ASSERT_EQ(0, failures);
}
TEST_HARNESS_MAIN