aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/Kconfig56
-rw-r--r--arch/riscv/Kconfig.erratas3
-rw-r--r--arch/riscv/Kconfig.socs4
-rw-r--r--arch/riscv/boot/dts/canaan/k210.dtsi12
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs.dtsi27
-rw-r--r--arch/riscv/boot/dts/sifive/fu540-c000.dtsi24
-rw-r--r--arch/riscv/boot/dts/sifive/fu740-c000.dtsi24
-rw-r--r--arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts2
-rw-r--r--arch/riscv/boot/dts/starfive/jh7100.dtsi16
-rw-r--r--arch/riscv/configs/32-bit.config2
-rw-r--r--arch/riscv/configs/defconfig1
-rw-r--r--arch/riscv/configs/nommu_k210_defconfig1
-rw-r--r--arch/riscv/configs/nommu_k210_sdcard_defconfig1
-rw-r--r--arch/riscv/configs/nommu_virt_defconfig1
-rw-r--r--arch/riscv/configs/rv32_defconfig1
-rw-r--r--arch/riscv/errata/thead/errata.c38
-rw-r--r--arch/riscv/include/asm/hwcap.h25
-rw-r--r--arch/riscv/include/asm/pci.h4
-rw-r--r--arch/riscv/include/asm/switch_to.h4
-rw-r--r--arch/riscv/kernel/alternative.c18
-rw-r--r--arch/riscv/kernel/cpufeature.c51
21 files changed, 220 insertions, 95 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index c22f58155948..55d2cc458ace 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -223,6 +223,21 @@ source "arch/riscv/Kconfig.erratas"
menu "Platform type"
+config NONPORTABLE
+ bool "Allow configurations that result in non-portable kernels"
+ help
+ RISC-V kernel binaries are compatible between all known systems
+ whenever possible, but there are some use cases that can only be
+ satisfied by configurations that result in kernel binaries that are
+ not portable between systems.
+
+ Selecting N does not guarantee kernels will be portable to all known
+ systems. Selecting any of the options guarded by NONPORTABLE will
+ result in kernel binaries that are unlikely to be portable between
+ systems.
+
+ If unsure, say N.
+
choice
prompt "Base ISA"
default ARCH_RV64I
@@ -232,6 +247,7 @@ choice
config ARCH_RV32I
bool "RV32I"
+ depends on NONPORTABLE
select 32BIT
select GENERIC_LIB_ASHLDI3
select GENERIC_LIB_ASHRDI3
@@ -352,11 +368,11 @@ config RISCV_ISA_C
bool "Emit compressed instructions when building Linux"
default y
help
- Adds "C" to the ISA subsets that the toolchain is allowed to emit
- when building Linux, which results in compressed instructions in the
- Linux binary.
+ Adds "C" to the ISA subsets that the toolchain is allowed to emit
+ when building Linux, which results in compressed instructions in the
+ Linux binary.
- If you don't know what to do here, say Y.
+ If you don't know what to do here, say Y.
config RISCV_ISA_SVPBMT
bool "SVPBMT extension support"
@@ -364,8 +380,13 @@ config RISCV_ISA_SVPBMT
select RISCV_ALTERNATIVE
default y
help
- Adds support to dynamically detect the presence of the SVPBMT extension
- (Supervisor-mode: page-based memory types) and enable its usage.
+ Adds support to dynamically detect the presence of the SVPBMT
+ ISA-extension (Supervisor-mode: page-based memory types) and
+ enable its usage.
+
+ The memory type for a page contains a combination of attributes
+ that indicate the cacheability, idempotency, and ordering
+ properties for access to that page.
The SVPBMT extension is only available on 64Bit cpus.
@@ -380,7 +401,7 @@ config FPU
If you don't know what to do here, say Y.
-endmenu
+endmenu # "Platform type"
menu "Kernel features"
@@ -469,7 +490,7 @@ config COMPAT
If you want to execute 32-bit userspace applications, say Y.
-endmenu
+endmenu # "Kernel features"
menu "Boot options"
@@ -505,7 +526,6 @@ config CMDLINE_EXTEND
cases where the provided arguments are insufficient and
you don't want to or cannot modify them.
-
config CMDLINE_FORCE
bool "Always use the default kernel command string"
help
@@ -548,6 +568,7 @@ config STACKPROTECTOR_PER_TASK
config PHYS_RAM_BASE_FIXED
bool "Explicitly specified physical RAM address"
+ depends on NONPORTABLE
default n
config PHYS_RAM_BASE
@@ -561,7 +582,7 @@ config PHYS_RAM_BASE
config XIP_KERNEL
bool "Kernel Execute-In-Place from ROM"
- depends on MMU && SPARSEMEM
+ depends on MMU && SPARSEMEM && NONPORTABLE
# This prevents XIP from being enabled by all{yes,mod}config, which
# fail to build since XIP doesn't support large kernels.
depends on !COMPILE_TEST
@@ -597,23 +618,30 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.
-endmenu
+endmenu # "Boot options"
config BUILTIN_DTB
bool
- depends on OF
+ depends on OF && NONPORTABLE
default y if XIP_KERNEL
+config PORTABLE
+ bool
+ default !NONPORTABLE
+ select EFI
+ select OF
+ select MMU
+
menu "Power management options"
source "kernel/power/Kconfig"
-endmenu
+endmenu # "Power management options"
menu "CPU Power Management"
source "drivers/cpuidle/Kconfig"
-endmenu
+endmenu # "CPU Power Management"
source "arch/riscv/kvm/Kconfig"
diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
index ebfcd5cc6eaf..f62b62807e85 100644
--- a/arch/riscv/Kconfig.erratas
+++ b/arch/riscv/Kconfig.erratas
@@ -35,6 +35,7 @@ config ERRATA_SIFIVE_CIP_1200
config ERRATA_THEAD
bool "T-HEAD errata"
+ depends on !XIP_KERNEL
select RISCV_ALTERNATIVE
help
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
@@ -54,4 +55,4 @@ config ERRATA_THEAD_PBMT
If you don't know what to do here, say "Y".
-endmenu
+endmenu # "CPU errata selection"
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 85670dc9fe95..69774bb362d6 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -78,6 +78,6 @@ config SOC_CANAAN_K210_DTB_SOURCE
for the DTS file that will be used to produce the DTB linked into the
kernel.
-endif
+endif # SOC_CANAAN
-endmenu
+endmenu # "SoC selection"
diff --git a/arch/riscv/boot/dts/canaan/k210.dtsi b/arch/riscv/boot/dts/canaan/k210.dtsi
index 44d338514761..ec944d1537dc 100644
--- a/arch/riscv/boot/dts/canaan/k210.dtsi
+++ b/arch/riscv/boot/dts/canaan/k210.dtsi
@@ -65,6 +65,18 @@
compatible = "riscv,cpu-intc";
};
};
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
};
sram: memory@80000000 {
diff --git a/arch/riscv/boot/dts/microchip/mpfs.dtsi b/arch/riscv/boot/dts/microchip/mpfs.dtsi
index 8c3259134194..6b20828c919f 100644
--- a/arch/riscv/boot/dts/microchip/mpfs.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs.dtsi
@@ -138,6 +138,30 @@
interrupt-controller;
};
};
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+
+ core2 {
+ cpu = <&cpu2>;
+ };
+
+ core3 {
+ cpu = <&cpu3>;
+ };
+
+ core4 {
+ cpu = <&cpu4>;
+ };
+ };
+ };
};
refclk: mssrefclk {
@@ -278,7 +302,6 @@
interrupt-parent = <&plic>;
interrupts = <54>;
clocks = <&clkcfg CLK_SPI0>;
- spi-max-frequency = <25000000>;
status = "disabled";
};
@@ -290,7 +313,6 @@
interrupt-parent = <&plic>;
interrupts = <55>;
clocks = <&clkcfg CLK_SPI1>;
- spi-max-frequency = <25000000>;
status = "disabled";
};
@@ -302,7 +324,6 @@
interrupt-parent = <&plic>;
interrupts = <85>;
clocks = <&clkcfg CLK_QSPI>;
- spi-max-frequency = <25000000>;
status = "disabled";
};
diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
index e3172d0ffac4..24bba83bec77 100644
--- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
@@ -133,6 +133,30 @@
interrupt-controller;
};
};
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+
+ core2 {
+ cpu = <&cpu2>;
+ };
+
+ core3 {
+ cpu = <&cpu3>;
+ };
+
+ core4 {
+ cpu = <&cpu4>;
+ };
+ };
+ };
};
soc {
#address-cells = <2>;
diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
index 7b77c13496d8..43bed6c0a84f 100644
--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
@@ -134,6 +134,30 @@
interrupt-controller;
};
};
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+
+ core2 {
+ cpu = <&cpu2>;
+ };
+
+ core3 {
+ cpu = <&cpu3>;
+ };
+
+ core4 {
+ cpu = <&cpu4>;
+ };
+ };
+ };
};
soc {
#address-cells = <2>;
diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
index c4ed9efdff03..1f386b07a832 100644
--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
@@ -90,7 +90,7 @@
compatible = "dlg,da9063-rtc";
};
- wdt {
+ watchdog {
compatible = "dlg,da9063-watchdog";
};
diff --git a/arch/riscv/boot/dts/starfive/jh7100.dtsi b/arch/riscv/boot/dts/starfive/jh7100.dtsi
index 69f22f9aad9d..c617a61e26e2 100644
--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
@@ -17,7 +17,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ U74_0: cpu@0 {
compatible = "sifive,u74-mc", "riscv";
reg = <0>;
d-cache-block-size = <64>;
@@ -42,7 +42,7 @@
};
};
- cpu@1 {
+ U74_1: cpu@1 {
compatible = "sifive,u74-mc", "riscv";
reg = <1>;
d-cache-block-size = <64>;
@@ -66,6 +66,18 @@
#interrupt-cells = <1>;
};
};
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&U74_0>;
+ };
+
+ core1 {
+ cpu = <&U74_1>;
+ };
+ };
+ };
};
osc_sys: osc_sys {
diff --git a/arch/riscv/configs/32-bit.config b/arch/riscv/configs/32-bit.config
index 43f41323b67e..f6af0f708df4 100644
--- a/arch/riscv/configs/32-bit.config
+++ b/arch/riscv/configs/32-bit.config
@@ -1,2 +1,4 @@
CONFIG_ARCH_RV32I=y
CONFIG_32BIT=y
+# CONFIG_PORTABLE is not set
+CONFIG_NONPORTABLE=y
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 0cc17db8aaba..f8d7d9527c6e 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -18,6 +18,7 @@ CONFIG_EXPERT=y
CONFIG_PROFILING=y
CONFIG_SOC_MICROCHIP_POLARFIRE=y
CONFIG_SOC_SIFIVE=y
+CONFIG_SOC_STARFIVE=y
CONFIG_SOC_VIRT=y
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig
index 2438fa39f8ae..96fe8def644c 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -28,6 +28,7 @@ CONFIG_EMBEDDED=y
CONFIG_SLOB=y
# CONFIG_MMU is not set
CONFIG_SOC_CANAAN=y
+CONFIG_NONPORTABLE=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_CMDLINE="earlycon console=ttySIF0"
diff --git a/arch/riscv/configs/nommu_k210_sdcard_defconfig b/arch/riscv/configs/nommu_k210_sdcard_defconfig
index 9a133e63ae5b..379740654373 100644
--- a/arch/riscv/configs/nommu_k210_sdcard_defconfig
+++ b/arch/riscv/configs/nommu_k210_sdcard_defconfig
@@ -20,6 +20,7 @@ CONFIG_EMBEDDED=y
CONFIG_SLOB=y
# CONFIG_MMU is not set
CONFIG_SOC_CANAAN=y
+CONFIG_NONPORTABLE=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_CMDLINE="earlycon console=ttySIF0 root=/dev/mmcblk0p1 rootwait ro"
diff --git a/arch/riscv/configs/nommu_virt_defconfig b/arch/riscv/configs/nommu_virt_defconfig
index 5269fbb6b4fc..1a56eda5ce46 100644
--- a/arch/riscv/configs/nommu_virt_defconfig
+++ b/arch/riscv/configs/nommu_virt_defconfig
@@ -25,6 +25,7 @@ CONFIG_EXPERT=y
CONFIG_SLOB=y
# CONFIG_MMU is not set
CONFIG_SOC_VIRT=y
+CONFIG_NONPORTABLE=y
CONFIG_SMP=y
CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
CONFIG_CMDLINE_FORCE=y
diff --git a/arch/riscv/configs/rv32_defconfig b/arch/riscv/configs/rv32_defconfig
index 6cd9d84d3e13..38760e4296cf 100644
--- a/arch/riscv/configs/rv32_defconfig
+++ b/arch/riscv/configs/rv32_defconfig
@@ -18,6 +18,7 @@ CONFIG_EXPERT=y
CONFIG_PROFILING=y
CONFIG_SOC_SIFIVE=y
CONFIG_SOC_VIRT=y
+CONFIG_NONPORTABLE=y
CONFIG_ARCH_RV32I=y
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
index e5d75270b99c..b37b6fedd53b 100644
--- a/arch/riscv/errata/thead/errata.c
+++ b/arch/riscv/errata/thead/errata.c
@@ -14,40 +14,26 @@
#include <asm/patch.h>
#include <asm/vendorid_list.h>
-struct errata_info {
- char name[ERRATA_STRING_LENGTH_MAX];
- bool (*check_func)(unsigned long arch_id, unsigned long impid);
- unsigned int stage;
-};
-
-static bool errata_mt_check_func(unsigned long arch_id, unsigned long impid)
+static bool errata_probe_pbmt(unsigned int stage,
+ unsigned long arch_id, unsigned long impid)
{
if (arch_id != 0 || impid != 0)
return false;
- return true;
-}
-static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = {
- {
- .name = "memory-types",
- .stage = RISCV_ALTERNATIVES_EARLY_BOOT,
- .check_func = errata_mt_check_func
- },
-};
+ if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
+ stage == RISCV_ALTERNATIVES_MODULE)
+ return true;
+
+ return false;
+}
-static u32 thead_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid)
+static u32 thead_errata_probe(unsigned int stage,
+ unsigned long archid, unsigned long impid)
{
- const struct errata_info *info;
u32 cpu_req_errata = 0;
- int idx;
-
- for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) {
- info = &errata_list[idx];
- if ((stage == RISCV_ALTERNATIVES_MODULE ||
- info->stage == stage) && info->check_func(archid, impid))
- cpu_req_errata |= (1U << idx);
- }
+ if (errata_probe_pbmt(stage, archid, impid))
+ cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
return cpu_req_errata;
}
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 4e2486881840..e48eebdd2631 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -12,6 +12,7 @@
#include <uapi/asm/hwcap.h>
#ifndef __ASSEMBLY__
+#include <linux/jump_label.h>
/*
* This yields a mask that user programs can use to figure out what
* instruction set this cpu supports.
@@ -56,6 +57,16 @@ enum riscv_isa_ext_id {
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
};
+/*
+ * This enum represents the logical ID for each RISC-V ISA extension static
+ * keys. We can use static key to optimize code path if some ISA extensions
+ * are available.
+ */
+enum riscv_isa_ext_key {
+ RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */
+ RISCV_ISA_EXT_KEY_MAX,
+};
+
struct riscv_isa_ext_data {
/* Name of the extension displayed to userspace via /proc/cpuinfo */
char uprop[RISCV_ISA_EXT_NAME_LEN_MAX];
@@ -63,6 +74,20 @@ struct riscv_isa_ext_data {
unsigned int isa_ext_id;
};
+extern struct static_key_false riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_MAX];
+
+static __always_inline int riscv_isa_ext2key(int num)
+{
+ switch (num) {
+ case RISCV_ISA_EXT_f:
+ return RISCV_ISA_EXT_KEY_FPU;
+ case RISCV_ISA_EXT_d:
+ return RISCV_ISA_EXT_KEY_FPU;
+ default:
+ return -EINVAL;
+ }
+}
+
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
diff --git a/arch/riscv/include/asm/pci.h b/arch/riscv/include/asm/pci.h
index 7fd52a30e605..830ac621dbbc 100644
--- a/arch/riscv/include/asm/pci.h
+++ b/arch/riscv/include/asm/pci.h
@@ -12,8 +12,8 @@
#include <asm/io.h>
-#define PCIBIOS_MIN_IO 0
-#define PCIBIOS_MIN_MEM 0
+#define PCIBIOS_MIN_IO 4
+#define PCIBIOS_MIN_MEM 16
/* RISC-V shim does not initialize PCI bus */
#define pcibios_assign_all_busses() 1
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 0a3f4f95c555..11463489fec6 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -8,6 +8,7 @@
#include <linux/jump_label.h>
#include <linux/sched/task_stack.h>
+#include <asm/hwcap.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/csr.h>
@@ -56,10 +57,9 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
}
-extern struct static_key_false cpu_hwcap_fpu;
static __always_inline bool has_fpu(void)
{
- return static_branch_likely(&cpu_hwcap_fpu);
+ return static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_FPU]);
}
#else
static __always_inline bool has_fpu(void) { return false; }
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index c9d0d3c53223..a7d26a00beea 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -20,7 +20,7 @@ struct cpu_manufacturer_info_t {
unsigned long vendor_id;
unsigned long arch_id;
unsigned long imp_id;
- void (*vendor_patch_func)(struct alt_entry *begin, struct alt_entry *end,
+ void (*patch_func)(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage);
};
@@ -40,16 +40,16 @@ static void __init_or_module riscv_fill_cpu_mfr_info(struct cpu_manufacturer_inf
switch (cpu_mfr_info->vendor_id) {
#ifdef CONFIG_ERRATA_SIFIVE
case SIFIVE_VENDOR_ID:
- cpu_mfr_info->vendor_patch_func = sifive_errata_patch_func;
+ cpu_mfr_info->patch_func = sifive_errata_patch_func;
break;
#endif
#ifdef CONFIG_ERRATA_THEAD
case THEAD_VENDOR_ID:
- cpu_mfr_info->vendor_patch_func = thead_errata_patch_func;
+ cpu_mfr_info->patch_func = thead_errata_patch_func;
break;
#endif
default:
- cpu_mfr_info->vendor_patch_func = NULL;
+ cpu_mfr_info->patch_func = NULL;
}
}
@@ -68,13 +68,13 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin,
riscv_cpufeature_patch_func(begin, end, stage);
- if (!cpu_mfr_info.vendor_patch_func)
+ if (!cpu_mfr_info.patch_func)
return;
- cpu_mfr_info.vendor_patch_func(begin, end,
- cpu_mfr_info.arch_id,
- cpu_mfr_info.imp_id,
- stage);
+ cpu_mfr_info.patch_func(begin, end,
+ cpu_mfr_info.arch_id,
+ cpu_mfr_info.imp_id,
+ stage);
}
void __init apply_boot_alternatives(void)
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index a08a54136c7a..e233fe154c96 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -27,9 +27,8 @@ unsigned long elf_hwcap __read_mostly;
/* Host ISA bitmap */
static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
-#ifdef CONFIG_FPU
-__ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu);
-#endif
+__ro_after_init DEFINE_STATIC_KEY_ARRAY_FALSE(riscv_isa_ext_keys, RISCV_ISA_EXT_KEY_MAX);
+EXPORT_SYMBOL(riscv_isa_ext_keys);
/**
* riscv_isa_extension_base() - Get base extension word
@@ -240,19 +239,15 @@ void __init riscv_fill_hwcap(void)
print_str[j++] = (char)('a' + i);
pr_info("riscv: ELF capabilities %s\n", print_str);
-#ifdef CONFIG_FPU
- if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
- static_branch_enable(&cpu_hwcap_fpu);
-#endif
+ for_each_set_bit(i, riscv_isa, RISCV_ISA_EXT_MAX) {
+ j = riscv_isa_ext2key(i);
+ if (j >= 0)
+ static_branch_enable(&riscv_isa_ext_keys[j]);
+ }
}
#ifdef CONFIG_RISCV_ALTERNATIVE
-struct cpufeature_info {
- char name[ERRATA_STRING_LENGTH_MAX];
- bool (*check_func)(unsigned int stage);
-};
-
-static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
+static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
{
#ifdef CONFIG_RISCV_ISA_SVPBMT
switch (stage) {
@@ -266,26 +261,19 @@ static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
return false;
}
-static const struct cpufeature_info __initdata_or_module
-cpufeature_list[CPUFEATURE_NUMBER] = {
- {
- .name = "svpbmt",
- .check_func = cpufeature_svpbmt_check_func
- },
-};
-
+/*
+ * Probe presence of individual extensions.
+ *
+ * This code may also be executed before kernel relocation, so we cannot use
+ * addresses generated by the address-of operator as they won't be valid in
+ * this context.
+ */
static u32 __init_or_module cpufeature_probe(unsigned int stage)
{
- const struct cpufeature_info *info;
u32 cpu_req_feature = 0;
- int idx;
- for (idx = 0; idx < CPUFEATURE_NUMBER; idx++) {
- info = &cpufeature_list[idx];
-
- if (info->check_func(stage))
- cpu_req_feature |= (1U << idx);
- }
+ if (cpufeature_probe_svpbmt(stage))
+ cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
return cpu_req_feature;
}
@@ -295,7 +283,6 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
unsigned int stage)
{
u32 cpu_req_feature = cpufeature_probe(stage);
- u32 cpu_apply_feature = 0;
struct alt_entry *alt;
u32 tmp;
@@ -309,10 +296,8 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
}
tmp = (1U << alt->errata_id);
- if (cpu_req_feature & tmp) {
+ if (cpu_req_feature & tmp)
patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
- cpu_apply_feature |= tmp;
- }
}
}
#endif