riscv: add cpufeature handling via alternatives

A patch from »riscv: Implement svpbmt via alternatives« in state Mainline for linux-kernel

From: Heiko Stuebner <heiko@...> Date: Sun, 5 Dec 2021 12:01:49 +0100

Commit-Message

Some cpufeatures should be handled via the alternatives mechanism to not incur penalties on unsupporting variants. So add a mechanism to handle these similar to cpu erratas. Signed-off-by: Heiko Stuebner <heiko@...>

Patch-Comment

arch/riscv/errata/Makefile | 1 + arch/riscv/errata/alternative.c | 3 ++ arch/riscv/errata/cpufeatures.c | 55 ++++++++++++++++++++++++++++ arch/riscv/include/asm/alternative.h | 1 + arch/riscv/include/asm/errata_list.h | 2 + 5 files changed, 62 insertions(+) create mode 100644 arch/riscv/errata/cpufeatures.c

Statistics

  • 62 lines added
  • 0 lines removed

Changes

-------------------------- arch/riscv/errata/Makefile --------------------------
index b8f8740a3e44..c9ba91052643 100644
@@ -1,2 +1,3 @@
obj-y += alternative.o
+obj-y += cpufeatures.o
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
----------------------- arch/riscv/errata/alternative.c ------------------------
index 3b15885db70b..4b45731efe64 100644
@@ -64,6 +64,9 @@ void __init apply_boot_alternatives(void)
init_alternative();
+ riscv_apply_cpufeatures((struct alt_entry *)__alt_start,
+ (struct alt_entry *)__alt_end);
+
if (!vendor_patch_func)
return;
----------------------- arch/riscv/errata/cpufeatures.c ------------------------
new file mode 100644
index 000000000000..99b7c5fe8dd4
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cpufeatures runtime patching
+ *
+ * Copyright (C) 2021 ?????
+ */
+
+#include <linux/init.h>
+#include <linux/of.h>
+#include <asm/alternative.h>
+#include <asm/errata_list.h>
+#include <asm/patch.h>
+
+struct cpufeature_info_t {
+ char name[ERRATA_STRING_LENGTH_MAX];
+ bool (*check_func)(void);
+};
+
+static struct cpufeature_info_t cpufeature_list[CPUFEATURE_NUMBER] = {
+};
+
+static u32 __init cpufeature_probe(void)
+{
+ u32 cpu_req_feature = 0;
+ int idx;
+
+ for (idx = 0; idx < CPUFEATURE_NUMBER; idx++)
+ if (cpufeature_list[idx].check_func())
+ cpu_req_feature |= (1U << idx);
+
+ return cpu_req_feature;
+}
+
+void riscv_apply_cpufeatures(struct alt_entry *begin, struct alt_entry *end)
+{
+ u32 cpu_req_feature = cpufeature_probe();
+ u32 cpu_apply_feature = 0;
+ struct alt_entry *alt;
+ u32 tmp;
+
+ for (alt = begin; alt < end; alt++) {
+ if (alt->vendor_id != 0)
+ continue;
+ if (alt->errata_id >= CPUFEATURE_NUMBER) {
+ WARN(1, "This feature id:%d is not in kernel cpufeature list", alt->errata_id);
+ continue;
+ }
+
+ tmp = (1U << alt->errata_id);
+ if (cpu_req_feature & tmp) {
+ patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
+ cpu_apply_feature |= tmp;
+ }
+ }
+}
--------------------- arch/riscv/include/asm/alternative.h ---------------------
index e625d3cafbed..fa0280cd8340 100644
@@ -35,5 +35,6 @@ struct errata_checkfunc_id {
void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid);
+void riscv_apply_cpufeatures(struct alt_entry *begin, struct alt_entry *end);
#endif
#endif
--------------------- arch/riscv/include/asm/errata_list.h ---------------------
index 5f1046e82d9f..6b95bd9aee82 100644
@@ -14,6 +14,8 @@
#define ERRATA_SIFIVE_NUMBER 2
#endif
+#define CPUFEATURE_NUMBER 0
+
#ifdef __ASSEMBLY__
#define ALT_INSN_FAULT(x) \
 
 

Recent Patches

About Us

Sed lacus. Donec lectus. Nullam pretium nibh ut turpis. Nam bibendum. In nulla tortor, elementum vel, tempor at, varius non, purus. Mauris vitae nisl nec metus placerat consectetuer.

Read More...