Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
for things like non-cacheable pages or I/O memory pages.
So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
types) using the alternatives framework.
This includes a number of changes to the alternatives mechanism itself.
The biggest one being the move to a more central location, as I expect
in the future, nearly every chip needing some sort of patching, be it
either for erratas or for optional features (svpbmt or others).
The dt-binding for svpbmt itself is of course not finished and is still
using the binding introduced in previous versions, as where to put
a svpbmt-property in the devicetree is still under dicussion.
Atish seems to be working on a framework for extensions [0],
The series also introduces support for the memory types of the D1
which are implemented differently to svpbmt. But when patching anyway
it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
location.
The only slightly bigger difference is that the "normal" type is not 0
as with svpbmt, so kernel patches for this PMA type need to be applied
even before the MMU is brought up, so the series introduces a separate
stage for that.
In theory this series is 3 parts:
- sbi cache-flush / null-ptr
- alternatives improvements
- svpbmt+d1
So expecially patches from the first 2 areas could be applied when
deemed ready, I just thought to keep it together to show-case where
the end-goal is and not requiring jumping between different series.
The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
as it touches a similar area in mm/cacheflush.c
I picked the recipient list from the previous version, hopefully
I didn't forget anybody.
changes in v6:
- rebase onto 5.17-rc1
- handle sbi null-ptr differently
- improve commit messages
- use riscv,mmu as property name
changes in v5:
- move to use alternatives for runtime-patching
- add D1 variant
[0] https://lore.kernel.org/r/[email protected]
[1] https://lore.kernel.org/r/[email protected]
Heiko Stuebner (12):
riscv: prevent null-pointer dereference with sbi_remote_fence_i
riscv: integrate alternatives better into the main architecture
riscv: allow different stages with alternatives
riscv: implement module alternatives
riscv: implement ALTERNATIVE_2 macro
riscv: extend concatenated alternatives-lines to the same length
riscv: prevent compressed instructions in alternatives
riscv: move boot alternatives to a slightly earlier position
riscv: Fix accessing pfn bits in PTEs for non-32bit variants
riscv: add cpufeature handling via alternatives
riscv: remove FIXMAP_PAGE_IO and fall back to its default value
riscv: add memory-type errata for T-Head
Wei Fu (2):
dt-bindings: riscv: add MMU Standard Extensions support for Svpbmt
riscv: add RISC-V Svpbmt extension support
.../devicetree/bindings/riscv/cpus.yaml | 10 ++
arch/riscv/Kconfig.erratas | 29 ++--
arch/riscv/Kconfig.socs | 1 -
arch/riscv/Makefile | 2 +-
arch/riscv/errata/Makefile | 2 +-
arch/riscv/errata/sifive/errata.c | 10 +-
arch/riscv/errata/thead/Makefile | 1 +
arch/riscv/errata/thead/errata.c | 85 +++++++++++
arch/riscv/include/asm/alternative-macros.h | 114 ++++++++-------
arch/riscv/include/asm/alternative.h | 16 ++-
arch/riscv/include/asm/errata_list.h | 52 +++++++
arch/riscv/include/asm/fixmap.h | 2 -
arch/riscv/include/asm/pgtable-32.h | 17 +++
arch/riscv/include/asm/pgtable-64.h | 79 +++++++++-
arch/riscv/include/asm/pgtable-bits.h | 10 --
arch/riscv/include/asm/pgtable.h | 53 +++++--
arch/riscv/include/asm/vendorid_list.h | 1 +
arch/riscv/kernel/Makefile | 1 +
arch/riscv/{errata => kernel}/alternative.c | 48 ++++++-
arch/riscv/kernel/cpufeature.c | 136 +++++++++++++++++-
arch/riscv/kernel/head.S | 2 +
arch/riscv/kernel/module.c | 29 ++++
arch/riscv/kernel/sbi.c | 10 +-
arch/riscv/kernel/smpboot.c | 4 -
arch/riscv/kernel/traps.c | 2 +-
arch/riscv/mm/init.c | 1 +
26 files changed, 606 insertions(+), 111 deletions(-)
create mode 100644 arch/riscv/errata/thead/Makefile
create mode 100644 arch/riscv/errata/thead/errata.c
rename arch/riscv/{errata => kernel}/alternative.c (59%)
--
2.30.2
Instructions are opportunistically compressed by the RISC-V assembler
when possible, but in alternatives-blocks both the old and new content
need to be the same size, so having the toolchain do somewhat random
optimizations will cause strange side-effects like
"attempt to move .org backwards" compile-time errors.
Already a simple "and" used in alternatives assembly will cause these
mismatched code sizes.
So prevent compressed instructions to be generated in alternatives-
code and use option-push and -pop to only limit this to the relevant
code blocks
Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/include/asm/alternative-macros.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h
index c0fb11fad631..3a52884bf23d 100644
--- a/arch/riscv/include/asm/alternative-macros.h
+++ b/arch/riscv/include/asm/alternative-macros.h
@@ -19,7 +19,10 @@
.popsection
.subsection 1
888 :
+ .option push
+ .option norvc
\new_c
+ .option pop
889 :
.previous
.org . - (889b - 888b) + (887b - 886b)
@@ -29,7 +32,10 @@
.macro __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable
886 :
+ .option push
+ .option norvc
\old_c
+ .option pop
887 :
ALT_NEW_CONTENT \vendor_id, \errata_id, \enable, \new_c
.endm
@@ -40,7 +46,10 @@
.macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
new_c_2, vendor_id_2, errata_id_2, enable_2
886 :
+ .option push
+ .option norvc
\old_c
+ .option pop
887 :
ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1
ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2
@@ -70,7 +79,10 @@
".popsection\n" \
".subsection 1\n" \
"888 :\n" \
+ ".option push\n" \
+ ".option norvc\n" \
new_c "\n" \
+ ".option pop\n" \
"889 :\n" \
".previous\n" \
".org . - (887b - 886b) + (889b - 888b)\n" \
@@ -79,7 +91,10 @@
#define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, enable) \
"886 :\n" \
+ ".option push\n" \
+ ".option norvc\n" \
old_c "\n" \
+ ".option pop\n" \
"887 :\n" \
ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c)
@@ -89,7 +104,10 @@
#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
new_c_2, vendor_id_2, errata_id_2, enable_2) \
"886 :\n" \
+ ".option push\n" \
+ ".option norvc\n" \
old_c "\n" \
+ ".option pop\n" \
"887 :\n" \
ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \
ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2)
--
2.30.2
When the alternatives were added the commit already provided a template
on how to implement 2 different alternatives for one piece of code.
Make this usable.
Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/include/asm/alternative-macros.h | 52 +++++++++++++--------
1 file changed, 32 insertions(+), 20 deletions(-)
diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h
index 92da6b3920a3..baf649293288 100644
--- a/arch/riscv/include/asm/alternative-macros.h
+++ b/arch/riscv/include/asm/alternative-macros.h
@@ -37,6 +37,20 @@
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
__ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k)
+.macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
+ new_c_2, vendor_id_2, errata_id_2, enable_2
+886 :
+ \old_c
+887 :
+ ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1
+ ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2
+.endm
+
+#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
+ new_c_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
+ __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, IS_ENABLED(CONFIG_k_1), \
+ new_c_2, vendor_id_2, errata_id_2, IS_ENABLED(CONFIG_k_2)
+
#else /* !__ASSEMBLY__ */
#include <asm/asm.h>
@@ -72,6 +86,19 @@
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
__ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k))
+#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
+ new_c_2, vendor_id_2, errata_id_2, enable_2) \
+ "886 :\n" \
+ old_c "\n" \
+ "887 :\n" \
+ ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \
+ ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2)
+
+#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
+ new_c_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
+ __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, IS_ENABLED(CONFIG_k_1), \
+ new_c_2, vendor_id_2, errata_id_2, IS_ENABLED(CONFIG_k_2))
+
#endif /* __ASSEMBLY__ */
/*
@@ -96,25 +123,10 @@
* this case, this vendor can create a new macro ALTERNATIVE_2() based
* on the following sample code and then replace ALTERNATIVE() with
* ALTERNATIVE_2() to append its customized content.
- *
- * .macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
- * new_c_2, vendor_id_2, errata_id_2, enable_2
- * 886 :
- * \old_c
- * 887 :
- * ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1
- * ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2
- * .endm
- *
- * #define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
- * new_c_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
- * __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, IS_ENABLED(CONFIG_k_1), \
- * new_c_2, vendor_id_2, errata_id_2, IS_ENABLED(CONFIG_k_2) \
- *
- * #define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
- * new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
- * _ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
- * new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2)
- *
*/
+#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
+ new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
+ _ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
+ new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2)
+
#endif
--
2.30.2
Some current cpus based on T-Head cores implement memory-types
way different than described in the svpbmt spec even going
so far as using PTE bits marked as reserved.
Add the T-Head vendor-id and necessary errata code to
replace the affected instructions.
Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/Kconfig.erratas | 19 ++++++
arch/riscv/errata/Makefile | 1 +
arch/riscv/errata/sifive/errata.c | 7 ++-
arch/riscv/errata/thead/Makefile | 1 +
arch/riscv/errata/thead/errata.c | 85 ++++++++++++++++++++++++++
arch/riscv/include/asm/alternative.h | 5 ++
arch/riscv/include/asm/errata_list.h | 47 ++++++++++++--
arch/riscv/include/asm/pgtable-64.h | 18 +++++-
arch/riscv/include/asm/pgtable.h | 18 +++++-
arch/riscv/include/asm/vendorid_list.h | 1 +
arch/riscv/kernel/alternative.c | 14 +++++
arch/riscv/kernel/cpufeature.c | 2 +
arch/riscv/mm/init.c | 1 +
13 files changed, 210 insertions(+), 9 deletions(-)
create mode 100644 arch/riscv/errata/thead/Makefile
create mode 100644 arch/riscv/errata/thead/errata.c
diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
index d18be8ff0245..380ec039c3dc 100644
--- a/arch/riscv/Kconfig.erratas
+++ b/arch/riscv/Kconfig.erratas
@@ -31,4 +31,23 @@ config ERRATA_SIFIVE_CIP_1200
If you don't know what to do here, say "Y".
+config ERRATA_THEAD
+ bool "T-HEAD errata"
+ help
+ All T-HEAD errata Kconfig depend on this Kconfig. Disabling
+ this Kconfig will disable all T-HEAD errata. Please say "Y"
+ here if your platform uses T-HEAD CPU cores.
+
+ If you don't know what to do here, say "Y".
+
+config ERRATA_THEAD_PBMT
+ bool "Apply T-Head memory type errata"
+ depends on ERRATA_THEAD && 64BIT
+ default y
+ help
+ This will apply the memory type errata to handle the non-standard
+ memory type bits in page-table-entries on T-Head SoCs.
+
+ If you don't know what to do here, say "Y".
+
endmenu
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
index 0ca1c5281a2d..a1055965fbee 100644
--- a/arch/riscv/errata/Makefile
+++ b/arch/riscv/errata/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
+obj-$(CONFIG_ERRATA_THEAD) += thead/
diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
index 4fe03ac41fd7..f933d6cdf304 100644
--- a/arch/riscv/errata/sifive/errata.c
+++ b/arch/riscv/errata/sifive/errata.c
@@ -84,10 +84,15 @@ void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *
unsigned int stage)
{
struct alt_entry *alt;
- u32 cpu_req_errata = sifive_errata_probe(archid, impid);
+ u32 cpu_req_errata;
u32 cpu_apply_errata = 0;
u32 tmp;
+ if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
+ return;
+
+ cpu_req_errata = sifive_errata_probe(archid, impid);
+
for (alt = begin; alt < end; alt++) {
if (alt->vendor_id != SIFIVE_VENDOR_ID)
continue;
diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile
new file mode 100644
index 000000000000..2d644e19caef
--- /dev/null
+++ b/arch/riscv/errata/thead/Makefile
@@ -0,0 +1 @@
+obj-y += errata.o
diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
new file mode 100644
index 000000000000..fd8e0538a3f0
--- /dev/null
+++ b/arch/riscv/errata/thead/errata.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Heiko Stuebner <[email protected]>
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <asm/alternative.h>
+#include <asm/cacheflush.h>
+#include <asm/errata_list.h>
+#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)
+{
+ 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
+ },
+};
+
+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);
+ }
+
+ return cpu_req_errata;
+}
+
+void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+ unsigned long archid, unsigned long impid,
+ unsigned int stage)
+{
+ struct alt_entry *alt;
+ u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
+ u32 cpu_apply_errata = 0;
+ u32 tmp;
+
+ for (alt = begin; alt < end; alt++) {
+ if (alt->vendor_id != THEAD_VENDOR_ID)
+ continue;
+ if (alt->errata_id >= ERRATA_THEAD_NUMBER)
+ continue;
+
+ tmp = (1U << alt->errata_id);
+ if (cpu_req_errata & tmp) {
+ /* On vm-alternatives, the mmu isn't running yet */
+ if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
+ memcpy((void *)__pa_symbol(alt->old_ptr),
+ (void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
+ else
+ patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
+
+ cpu_apply_errata |= tmp;
+ }
+ }
+
+ if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
+ local_flush_icache_all();
+}
diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
index cf3b22173834..d1154c91ab03 100644
--- a/arch/riscv/include/asm/alternative.h
+++ b/arch/riscv/include/asm/alternative.h
@@ -19,8 +19,10 @@
#define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */
#define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */
+#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */
void __init apply_boot_alternatives(void);
+void __init apply_early_boot_alternatives(void);
void apply_module_alternatives(void *start, size_t length);
struct alt_entry {
@@ -39,6 +41,9 @@ struct errata_checkfunc_id {
void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage);
+void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+ unsigned long archid, unsigned long impid,
+ unsigned int stage);
void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage);
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index a4a9b0842922..4fac46b82c16 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -14,6 +14,11 @@
#define ERRATA_SIFIVE_NUMBER 2
#endif
+#ifdef CONFIG_ERRATA_THEAD
+#define ERRATA_THEAD_PBMT 0
+#define ERRATA_THEAD_NUMBER 1
+#endif
+
#define CPUFEATURE_SVPBMT 0
#define CPUFEATURE_NUMBER 1
@@ -42,10 +47,44 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
* in the default case.
*/
#define ALT_SVPBMT_SHIFT 61
-#define ALT_SVPBMT(_val, prot) \
-asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,%2", 0, \
- CPUFEATURE_SVPBMT, CONFIG_64BIT) \
- : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), "I"(ALT_SVPBMT_SHIFT))
+#define ALT_THEAD_PBMT_SHIFT 59
+#define ALT_SVPBMT(_val, prot) \
+asm(ALTERNATIVE_2("li %0, 0\t\nnop", \
+ "li %0, %1\t\nslli %0,%0,%3", 0, CPUFEATURE_SVPBMT, CONFIG_64BIT, \
+ "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, \
+ CONFIG_ERRATA_THEAD_PBMT) \
+ : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \
+ "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \
+ "I"(ALT_SVPBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
+
+#ifdef CONFIG_ERRATA_THEAD_PBMT
+/*
+ * IO/NOCACHE memory types are handled together with svpbmt,
+ * so on T-Head chips, check if no other memory type is set,
+ * and set the non-0 PMA type if applicable.
+ */
+#define ALT_THEAD_PMA(_val) \
+asm volatile(ALTERNATIVE( \
+ "nop\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ "nop", \
+ "li t3, %2\n\t" \
+ "slli t3, t3, %4\n\t" \
+ "and t3, %0, t3\n\t" \
+ "bne t3, zero, 2f\n\t" \
+ "li t3, %3\n\t" \
+ "slli t3, t3, %4\n\t" \
+ "or %0, %0, t3\n\t" \
+ "2:", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
+ : "+r"(_val) : "0"(_val), "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \
+ "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
+#else
+#define ALT_THEAD_PMA(_val)
+#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
index 07ba3416cb19..6d59e4695200 100644
--- a/arch/riscv/include/asm/pgtable-64.h
+++ b/arch/riscv/include/asm/pgtable-64.h
@@ -69,6 +69,18 @@ typedef struct {
#define _PAGE_IO_SVPBMT (1UL << 62)
#define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
+/*
+ * [63:59] T-Head Memory Type definitions:
+ *
+ * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
+ * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
+ * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
+ */
+#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
+#define _PAGE_NOCACHE_THEAD 0UL
+#define _PAGE_IO_THEAD (1UL << 63)
+#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
+
static inline u64 riscv_page_mtmask(void)
{
u64 val;
@@ -167,7 +179,11 @@ static inline bool mm_pud_folded(struct mm_struct *mm)
static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
{
- return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
+ unsigned long prot_val = pgprot_val(prot);
+
+ ALT_THEAD_PMA(prot_val);
+
+ return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val);
}
static inline unsigned long _pmd_pfn(pmd_t pmd)
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index b8abc75dfe01..3d0c4c144093 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -245,7 +245,11 @@ static inline void pmd_clear(pmd_t *pmdp)
static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot)
{
- return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
+ unsigned long prot_val = pgprot_val(prot);
+
+ ALT_THEAD_PMA(prot_val);
+
+ return __pgd((pfn << _PAGE_PFN_SHIFT) | prot_val);
}
static inline unsigned long _pgd_pfn(pgd_t pgd)
@@ -284,7 +288,11 @@ static inline unsigned long pte_pfn(pte_t pte)
/* Constructs a page table entry */
static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
{
- return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
+ unsigned long prot_val = pgprot_val(prot);
+
+ ALT_THEAD_PMA(prot_val);
+
+ return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val);
}
#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
@@ -393,7 +401,11 @@ static inline int pmd_protnone(pmd_t pmd)
/* Modify page protection bits */
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
- return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+ unsigned long newprot_val = pgprot_val(newprot);
+
+ ALT_THEAD_PMA(newprot_val);
+
+ return __pte((pte_val(pte) & _PAGE_CHG_MASK) | newprot_val);
}
#define pgd_ERROR(e) \
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index 9d934215b3c8..cb89af3f0704 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -6,5 +6,6 @@
#define ASM_VENDOR_LIST_H
#define SIFIVE_VENDOR_ID 0x489
+#define THEAD_VENDOR_ID 0x5b7
#endif
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index e6c9de9f9ba6..3f6ad91f524c 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -48,6 +48,11 @@ static void __init init_alternative(void)
case SIFIVE_VENDOR_ID:
vendor_patch_func = sifive_errata_patch_func;
break;
+#endif
+#ifdef CONFIG_ERRATA_THEAD
+ case THEAD_VENDOR_ID:
+ vendor_patch_func = thead_errata_patch_func;
+ break;
#endif
default:
vendor_patch_func = NULL;
@@ -85,6 +90,15 @@ void __init apply_boot_alternatives(void)
RISCV_ALTERNATIVES_BOOT);
}
+void __init apply_early_boot_alternatives(void)
+{
+ init_alternative();
+
+ _apply_alternatives((struct alt_entry *)__alt_start,
+ (struct alt_entry *)__alt_end,
+ RISCV_ALTERNATIVES_EARLY_BOOT);
+}
+
#ifdef CONFIG_MODULES
void apply_module_alternatives(void *start, size_t length)
{
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 7bce66ee7ce7..ecc248e5dab7 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -224,6 +224,8 @@ static bool cpufeature_svpbmt_check_func(unsigned int stage)
#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
switch (stage) {
+ case RISCV_ALTERNATIVES_EARLY_BOOT:
+ return false;
case RISCV_ALTERNATIVES_BOOT:
return cpufeature_svpbmt_check_fdt();
default:
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index cf4d018b7d66..7216db5d6a2c 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -819,6 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K);
#endif
+ apply_early_boot_alternatives();
pt_ops_set_early();
/* Setup early PGD for fixmap */
--
2.30.2
ALT_NEW_CONTENT already uses same-length assembler lines, so
extend this to the other elements as well.
This makes it more readable when these elements need to be extended
in the future.
Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/include/asm/alternative-macros.h | 30 ++++++++++-----------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h
index baf649293288..c0fb11fad631 100644
--- a/arch/riscv/include/asm/alternative-macros.h
+++ b/arch/riscv/include/asm/alternative-macros.h
@@ -56,14 +56,14 @@
#include <asm/asm.h>
#include <linux/stringify.h>
-#define ALT_ENTRY(oldptr, newptr, vendor_id, errata_id, newlen) \
- RISCV_PTR " " oldptr "\n" \
- RISCV_PTR " " newptr "\n" \
- REG_ASM " " vendor_id "\n" \
- REG_ASM " " newlen "\n" \
+#define ALT_ENTRY(oldptr, newptr, vendor_id, errata_id, newlen) \
+ RISCV_PTR " " oldptr "\n" \
+ RISCV_PTR " " newptr "\n" \
+ REG_ASM " " vendor_id "\n" \
+ REG_ASM " " newlen "\n" \
".word " errata_id "\n"
-#define ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c) \
+#define ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c) \
".if " __stringify(enable) " == 1\n" \
".pushsection .alternative, \"a\"\n" \
ALT_ENTRY("886b", "888f", __stringify(vendor_id), __stringify(errata_id), "889f - 888f") \
@@ -77,21 +77,21 @@
".org . - (889b - 888b) + (887b - 886b)\n" \
".endif\n"
-#define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, enable) \
- "886 :\n" \
- old_c "\n" \
- "887 :\n" \
+#define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, enable) \
+ "886 :\n" \
+ old_c "\n" \
+ "887 :\n" \
ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c)
-#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
+#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
__ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k))
#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
new_c_2, vendor_id_2, errata_id_2, enable_2) \
- "886 :\n" \
- old_c "\n" \
- "887 :\n" \
- ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \
+ "886 :\n" \
+ old_c "\n" \
+ "887 :\n" \
+ ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \
ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2)
#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
--
2.30.2
The callback used inside sbi_remote_fence_i is set at sbi probe time
to the needed variant. Before that it is a NULL pointer.
Some users like the flush_icache_*() functions suggest a generic
functionality, that doesn't depend on a specific boot-stage but
uses sbi_remote_fence_i as one option to flush other cpu cores.
So they definitly shouldn't run into null-pointer dereference
issues when called "too early" during boot.
So introduce an empty function to be the standard for the __sbi_rfence
function pointer until sbi_init has run.
Users of sbi_remote_fence_i will have separate code for the local
cpu and sbi_init() is called before other cpus are brought up.
So there are no other cpus present at the time when the issue
might happen.
Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/kernel/sbi.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index f72527fcb347..c839acd668d3 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -15,11 +15,19 @@
unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
EXPORT_SYMBOL(sbi_spec_version);
+static int __sbi_rfence_none(int fid, const struct cpumask *cpu_mask,
+ unsigned long start, unsigned long size,
+ unsigned long arg4, unsigned long arg5)
+{
+ return -EOPNOTSUPP;
+}
+
static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
static int (*__sbi_send_ipi)(const struct cpumask *cpu_mask) __ro_after_init;
static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
unsigned long start, unsigned long size,
- unsigned long arg4, unsigned long arg5) __ro_after_init;
+ unsigned long arg4, unsigned long arg5)
+ __ro_after_init = __sbi_rfence_none;
struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
unsigned long arg1, unsigned long arg2,
--
2.30.2
On Wed, Feb 09, 2022 at 01:37:46PM +0100, Heiko Stuebner wrote:
> Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> for things like non-cacheable pages or I/O memory pages.
>
>
> So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> types) using the alternatives framework.
>
> This includes a number of changes to the alternatives mechanism itself.
> The biggest one being the move to a more central location, as I expect
> in the future, nearly every chip needing some sort of patching, be it
> either for erratas or for optional features (svpbmt or others).
>
> The dt-binding for svpbmt itself is of course not finished and is still
> using the binding introduced in previous versions, as where to put
> a svpbmt-property in the devicetree is still under dicussion.
> Atish seems to be working on a framework for extensions [0],
>
> The series also introduces support for the memory types of the D1
> which are implemented differently to svpbmt. But when patching anyway
> it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> location.
>
> The only slightly bigger difference is that the "normal" type is not 0
> as with svpbmt, so kernel patches for this PMA type need to be applied
> even before the MMU is brought up, so the series introduces a separate
> stage for that.
>
>
> In theory this series is 3 parts:
> - sbi cache-flush / null-ptr
> - alternatives improvements
> - svpbmt+d1
>
> So expecially patches from the first 2 areas could be applied when
> deemed ready, I just thought to keep it together to show-case where
> the end-goal is and not requiring jumping between different series.
>
>
> The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> as it touches a similar area in mm/cacheflush.c
>
>
> I picked the recipient list from the previous version, hopefully
> I didn't forget anybody.
>
> changes in v6:
> - rebase onto 5.17-rc1
> - handle sbi null-ptr differently
> - improve commit messages
> - use riscv,mmu as property name
>
> changes in v5:
> - move to use alternatives for runtime-patching
Hi,
another choice is using static key mechanism. Pros: no need to coding
in asm, all in c.
To support new arch features, I see other arch sometimes use static
key, sometimes use alternative mechanism, so one question here would
be which mechanism is better? Any guide?
Thanks in advance
If not defined in the arch, FIXMAP_PAGE_IO defaults to PAGE_KERNEL_IO,
which we defined when adding the svpbmt implementation.
So drop the FIXMAP_PAGE_IO riscv define.
Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/include/asm/fixmap.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
index 58a718573ad6..692e25e56d8e 100644
--- a/arch/riscv/include/asm/fixmap.h
+++ b/arch/riscv/include/asm/fixmap.h
@@ -44,8 +44,6 @@ enum fixed_addresses {
__end_of_fixed_addresses
};
-#define FIXMAP_PAGE_IO PAGE_KERNEL
-
#define __early_set_fixmap __set_fixmap
#define __late_set_fixmap __set_fixmap
--
2.30.2
Hi,
Am Mittwoch, 9. Februar 2022, 18:49:19 CET schrieb Jisheng Zhang:
> On Wed, Feb 09, 2022 at 01:37:46PM +0100, Heiko Stuebner wrote:
> > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > for things like non-cacheable pages or I/O memory pages.
> >
> >
> > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > types) using the alternatives framework.
> >
> > This includes a number of changes to the alternatives mechanism itself.
> > The biggest one being the move to a more central location, as I expect
> > in the future, nearly every chip needing some sort of patching, be it
> > either for erratas or for optional features (svpbmt or others).
> >
> > The dt-binding for svpbmt itself is of course not finished and is still
> > using the binding introduced in previous versions, as where to put
> > a svpbmt-property in the devicetree is still under dicussion.
> > Atish seems to be working on a framework for extensions [0],
> >
> > The series also introduces support for the memory types of the D1
> > which are implemented differently to svpbmt. But when patching anyway
> > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > location.
> >
> > The only slightly bigger difference is that the "normal" type is not 0
> > as with svpbmt, so kernel patches for this PMA type need to be applied
> > even before the MMU is brought up, so the series introduces a separate
> > stage for that.
> >
> >
> > In theory this series is 3 parts:
> > - sbi cache-flush / null-ptr
> > - alternatives improvements
> > - svpbmt+d1
> >
> > So expecially patches from the first 2 areas could be applied when
> > deemed ready, I just thought to keep it together to show-case where
> > the end-goal is and not requiring jumping between different series.
> >
> >
> > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > as it touches a similar area in mm/cacheflush.c
> >
> >
> > I picked the recipient list from the previous version, hopefully
> > I didn't forget anybody.
> >
> > changes in v6:
> > - rebase onto 5.17-rc1
> > - handle sbi null-ptr differently
> > - improve commit messages
> > - use riscv,mmu as property name
> >
> > changes in v5:
> > - move to use alternatives for runtime-patching
>
> another choice is using static key mechanism. Pros: no need to coding
> in asm, all in c.
>
> To support new arch features, I see other arch sometimes use static
> key, sometimes use alternative mechanism, so one question here would
> be which mechanism is better? Any guide?
For me it's also a bit of a learn-as-you-go experience, but I do see some
advantages in using alternatives:
- Static keys need the jump-label infrastructure, which the RiscV kernel
only seems to provide on non-XIP kernels [0]
- the amount of asm here is somewhat minimal for the core no-cache and io
types (load immediate + shift)
- using the static key mechanism still does incur more overhead for the
conditional
- and if we want to support the strange family-members like the D1,
(and it seems we do want that) this would create more conditionals
as we have to test for svpbmt, d1 and maybe future special cases,
where alternatives-patching on the other hand simply replaces the
relevant code with the appropriate variant.
Heiko
[0] https://elixir.bootlin.com/linux/latest/source/arch/riscv/Kconfig#L67
On Thu, Feb 10, 2022 at 12:44:04AM +0100, Heiko Stübner wrote:
> Hi,
>
> Am Mittwoch, 9. Februar 2022, 18:49:19 CET schrieb Jisheng Zhang:
> > On Wed, Feb 09, 2022 at 01:37:46PM +0100, Heiko Stuebner wrote:
> > > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > > for things like non-cacheable pages or I/O memory pages.
> > >
> > >
> > > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > > types) using the alternatives framework.
> > >
> > > This includes a number of changes to the alternatives mechanism itself.
> > > The biggest one being the move to a more central location, as I expect
> > > in the future, nearly every chip needing some sort of patching, be it
> > > either for erratas or for optional features (svpbmt or others).
> > >
> > > The dt-binding for svpbmt itself is of course not finished and is still
> > > using the binding introduced in previous versions, as where to put
> > > a svpbmt-property in the devicetree is still under dicussion.
> > > Atish seems to be working on a framework for extensions [0],
> > >
> > > The series also introduces support for the memory types of the D1
> > > which are implemented differently to svpbmt. But when patching anyway
> > > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > > location.
> > >
> > > The only slightly bigger difference is that the "normal" type is not 0
> > > as with svpbmt, so kernel patches for this PMA type need to be applied
> > > even before the MMU is brought up, so the series introduces a separate
> > > stage for that.
> > >
> > >
> > > In theory this series is 3 parts:
> > > - sbi cache-flush / null-ptr
> > > - alternatives improvements
> > > - svpbmt+d1
> > >
> > > So expecially patches from the first 2 areas could be applied when
> > > deemed ready, I just thought to keep it together to show-case where
> > > the end-goal is and not requiring jumping between different series.
> > >
> > >
> > > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > > as it touches a similar area in mm/cacheflush.c
> > >
> > >
> > > I picked the recipient list from the previous version, hopefully
> > > I didn't forget anybody.
> > >
> > > changes in v6:
> > > - rebase onto 5.17-rc1
> > > - handle sbi null-ptr differently
> > > - improve commit messages
> > > - use riscv,mmu as property name
> > >
> > > changes in v5:
> > > - move to use alternatives for runtime-patching
> >
> > another choice is using static key mechanism. Pros: no need to coding
> > in asm, all in c.
> >
> > To support new arch features, I see other arch sometimes use static
> > key, sometimes use alternative mechanism, so one question here would
> > be which mechanism is better? Any guide?
>
> For me it's also a bit of a learn-as-you-go experience, but I do see some
I hope old hands can give some suggestions here about static key VS.
alternative ;). When to use which mechanism, and why.
> advantages in using alternatives:
>
> - Static keys need the jump-label infrastructure, which the RiscV kernel
> only seems to provide on non-XIP kernels [0]
I think you found one bug here.
I believe alternative mechanism also doesn't work for XIP kernel. I will
submit a patch for this case.
> - the amount of asm here is somewhat minimal for the core no-cache and io
> types (load immediate + shift)
> - using the static key mechanism still does incur more overhead for the
> conditional
do you mean the icache overhead due to the other disabled branch of
static key? It deserves a check.
> - and if we want to support the strange family-members like the D1,
> (and it seems we do want that) this would create more conditionals
Maybe implement the standard svpbmt via. static key and cope with D1 as
errata alternative.
> as we have to test for svpbmt, d1 and maybe future special cases,
From Documentation/riscv/patch-acceptance.rst, the "Submit Checklist
Addendum" section, "we'll only to accept patches for extensions that
have been officially frozen or ratified by the RISC-V Foundation."
This rule hasn't been changed.
Per my understanding of history of the svpbmt patch set, no future
special cases any more.
> where alternatives-patching on the other hand simply replaces the
> relevant code with the appropriate variant.
>
On Wed, Feb 9, 2022 at 4:41 AM Heiko Stuebner <[email protected]> wrote:
>
> Some current cpus based on T-Head cores implement memory-types
> way different than described in the svpbmt spec even going
> so far as using PTE bits marked as reserved.
>
> Add the T-Head vendor-id and necessary errata code to
> replace the affected instructions.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/Kconfig.erratas | 19 ++++++
> arch/riscv/errata/Makefile | 1 +
> arch/riscv/errata/sifive/errata.c | 7 ++-
> arch/riscv/errata/thead/Makefile | 1 +
> arch/riscv/errata/thead/errata.c | 85 ++++++++++++++++++++++++++
> arch/riscv/include/asm/alternative.h | 5 ++
> arch/riscv/include/asm/errata_list.h | 47 ++++++++++++--
> arch/riscv/include/asm/pgtable-64.h | 18 +++++-
> arch/riscv/include/asm/pgtable.h | 18 +++++-
> arch/riscv/include/asm/vendorid_list.h | 1 +
> arch/riscv/kernel/alternative.c | 14 +++++
> arch/riscv/kernel/cpufeature.c | 2 +
> arch/riscv/mm/init.c | 1 +
> 13 files changed, 210 insertions(+), 9 deletions(-)
> create mode 100644 arch/riscv/errata/thead/Makefile
> create mode 100644 arch/riscv/errata/thead/errata.c
>
> diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> index d18be8ff0245..380ec039c3dc 100644
> --- a/arch/riscv/Kconfig.erratas
> +++ b/arch/riscv/Kconfig.erratas
> @@ -31,4 +31,23 @@ config ERRATA_SIFIVE_CIP_1200
>
> If you don't know what to do here, say "Y".
>
> +config ERRATA_THEAD
> + bool "T-HEAD errata"
> + help
> + All T-HEAD errata Kconfig depend on this Kconfig. Disabling
> + this Kconfig will disable all T-HEAD errata. Please say "Y"
> + here if your platform uses T-HEAD CPU cores.
> +
> + If you don't know what to do here, say "Y".
> +
> +config ERRATA_THEAD_PBMT
> + bool "Apply T-Head memory type errata"
> + depends on ERRATA_THEAD && 64BIT
> + default y
> + help
> + This will apply the memory type errata to handle the non-standard
> + memory type bits in page-table-entries on T-Head SoCs.
> +
> + If you don't know what to do here, say "Y".
> +
> endmenu
> diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> index 0ca1c5281a2d..a1055965fbee 100644
> --- a/arch/riscv/errata/Makefile
> +++ b/arch/riscv/errata/Makefile
> @@ -1 +1,2 @@
> obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> +obj-$(CONFIG_ERRATA_THEAD) += thead/
> diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> index 4fe03ac41fd7..f933d6cdf304 100644
> --- a/arch/riscv/errata/sifive/errata.c
> +++ b/arch/riscv/errata/sifive/errata.c
> @@ -84,10 +84,15 @@ void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *
> unsigned int stage)
> {
> struct alt_entry *alt;
> - u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> + u32 cpu_req_errata;
> u32 cpu_apply_errata = 0;
> u32 tmp;
>
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + return;
> +
> + cpu_req_errata = sifive_errata_probe(archid, impid);
> +
> for (alt = begin; alt < end; alt++) {
> if (alt->vendor_id != SIFIVE_VENDOR_ID)
> continue;
> diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile
> new file mode 100644
> index 000000000000..2d644e19caef
> --- /dev/null
> +++ b/arch/riscv/errata/thead/Makefile
> @@ -0,0 +1 @@
> +obj-y += errata.o
> diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
> new file mode 100644
> index 000000000000..fd8e0538a3f0
> --- /dev/null
> +++ b/arch/riscv/errata/thead/errata.c
> @@ -0,0 +1,85 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2021 Heiko Stuebner <[email protected]>
> + */
> +
> +#include <linux/bug.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/string.h>
> +#include <linux/uaccess.h>
> +#include <asm/alternative.h>
> +#include <asm/cacheflush.h>
> +#include <asm/errata_list.h>
> +#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)
> +{
> + 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
> + },
> +};
> +
> +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);
> + }
> +
> + return cpu_req_errata;
> +}
> +
> +void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> + unsigned long archid, unsigned long impid,
> + unsigned int stage)
> +{
> + struct alt_entry *alt;
> + u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
> + u32 cpu_apply_errata = 0;
> + u32 tmp;
> +
> + for (alt = begin; alt < end; alt++) {
> + if (alt->vendor_id != THEAD_VENDOR_ID)
> + continue;
> + if (alt->errata_id >= ERRATA_THEAD_NUMBER)
> + continue;
> +
> + tmp = (1U << alt->errata_id);
> + if (cpu_req_errata & tmp) {
> + /* On vm-alternatives, the mmu isn't running yet */
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + memcpy((void *)__pa_symbol(alt->old_ptr),
> + (void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
> + else
> + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> +
> + cpu_apply_errata |= tmp;
> + }
> + }
> +
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + local_flush_icache_all();
> +}
> diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> index cf3b22173834..d1154c91ab03 100644
> --- a/arch/riscv/include/asm/alternative.h
> +++ b/arch/riscv/include/asm/alternative.h
> @@ -19,8 +19,10 @@
>
> #define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */
> #define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */
> +#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */
>
But this stage invoked is used after RISCV_ALTERNATIVES_BOOT
> void __init apply_boot_alternatives(void);
> +void __init apply_early_boot_alternatives(void);
> void apply_module_alternatives(void *start, size_t length);
>
> struct alt_entry {
> @@ -39,6 +41,9 @@ struct errata_checkfunc_id {
> void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned long archid, unsigned long impid,
> unsigned int stage);
> +void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> + unsigned long archid, unsigned long impid,
> + unsigned int stage);
>
> void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned int stage);
> diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> index a4a9b0842922..4fac46b82c16 100644
> --- a/arch/riscv/include/asm/errata_list.h
> +++ b/arch/riscv/include/asm/errata_list.h
> @@ -14,6 +14,11 @@
> #define ERRATA_SIFIVE_NUMBER 2
> #endif
>
> +#ifdef CONFIG_ERRATA_THEAD
> +#define ERRATA_THEAD_PBMT 0
> +#define ERRATA_THEAD_NUMBER 1
> +#endif
> +
> #define CPUFEATURE_SVPBMT 0
> #define CPUFEATURE_NUMBER 1
>
> @@ -42,10 +47,44 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
> * in the default case.
> */
> #define ALT_SVPBMT_SHIFT 61
> -#define ALT_SVPBMT(_val, prot) \
> -asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,%2", 0, \
> - CPUFEATURE_SVPBMT, CONFIG_64BIT) \
> - : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), "I"(ALT_SVPBMT_SHIFT))
> +#define ALT_THEAD_PBMT_SHIFT 59
> +#define ALT_SVPBMT(_val, prot) \
> +asm(ALTERNATIVE_2("li %0, 0\t\nnop", \
> + "li %0, %1\t\nslli %0,%0,%3", 0, CPUFEATURE_SVPBMT, CONFIG_64BIT, \
> + "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, \
> + CONFIG_ERRATA_THEAD_PBMT) \
> + : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \
> + "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> + "I"(ALT_SVPBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> +
> +#ifdef CONFIG_ERRATA_THEAD_PBMT
> +/*
> + * IO/NOCACHE memory types are handled together with svpbmt,
> + * so on T-Head chips, check if no other memory type is set,
> + * and set the non-0 PMA type if applicable.
> + */
> +#define ALT_THEAD_PMA(_val) \
> +asm volatile(ALTERNATIVE( \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop", \
> + "li t3, %2\n\t" \
> + "slli t3, t3, %4\n\t" \
> + "and t3, %0, t3\n\t" \
> + "bne t3, zero, 2f\n\t" \
> + "li t3, %3\n\t" \
> + "slli t3, t3, %4\n\t" \
> + "or %0, %0, t3\n\t" \
> + "2:", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
> + : "+r"(_val) : "0"(_val), "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> + "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> +#else
> +#define ALT_THEAD_PMA(_val)
> +#endif
>
> #endif /* __ASSEMBLY__ */
>
> diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> index 07ba3416cb19..6d59e4695200 100644
> --- a/arch/riscv/include/asm/pgtable-64.h
> +++ b/arch/riscv/include/asm/pgtable-64.h
> @@ -69,6 +69,18 @@ typedef struct {
> #define _PAGE_IO_SVPBMT (1UL << 62)
> #define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
>
> +/*
> + * [63:59] T-Head Memory Type definitions:
> + *
> + * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> + * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
> + * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> + */
> +#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
> +#define _PAGE_NOCACHE_THEAD 0UL
> +#define _PAGE_IO_THEAD (1UL << 63)
> +#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
> +
> static inline u64 riscv_page_mtmask(void)
> {
> u64 val;
> @@ -167,7 +179,11 @@ static inline bool mm_pud_folded(struct mm_struct *mm)
>
> static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
> {
> - return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> + unsigned long prot_val = pgprot_val(prot);
> +
> + ALT_THEAD_PMA(prot_val);
> +
> + return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> }
>
> static inline unsigned long _pmd_pfn(pmd_t pmd)
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index b8abc75dfe01..3d0c4c144093 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -245,7 +245,11 @@ static inline void pmd_clear(pmd_t *pmdp)
>
> static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot)
> {
> - return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> + unsigned long prot_val = pgprot_val(prot);
> +
> + ALT_THEAD_PMA(prot_val);
> +
> + return __pgd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> }
>
> static inline unsigned long _pgd_pfn(pgd_t pgd)
> @@ -284,7 +288,11 @@ static inline unsigned long pte_pfn(pte_t pte)
> /* Constructs a page table entry */
> static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
> {
> - return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> + unsigned long prot_val = pgprot_val(prot);
> +
> + ALT_THEAD_PMA(prot_val);
> +
> + return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val);
> }
>
> #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
> @@ -393,7 +401,11 @@ static inline int pmd_protnone(pmd_t pmd)
> /* Modify page protection bits */
> static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> {
> - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
> + unsigned long newprot_val = pgprot_val(newprot);
> +
> + ALT_THEAD_PMA(newprot_val);
> +
> + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | newprot_val);
> }
>
> #define pgd_ERROR(e) \
> diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
> index 9d934215b3c8..cb89af3f0704 100644
> --- a/arch/riscv/include/asm/vendorid_list.h
> +++ b/arch/riscv/include/asm/vendorid_list.h
> @@ -6,5 +6,6 @@
> #define ASM_VENDOR_LIST_H
>
> #define SIFIVE_VENDOR_ID 0x489
> +#define THEAD_VENDOR_ID 0x5b7
>
> #endif
> diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> index e6c9de9f9ba6..3f6ad91f524c 100644
> --- a/arch/riscv/kernel/alternative.c
> +++ b/arch/riscv/kernel/alternative.c
> @@ -48,6 +48,11 @@ static void __init init_alternative(void)
> case SIFIVE_VENDOR_ID:
> vendor_patch_func = sifive_errata_patch_func;
> break;
> +#endif
> +#ifdef CONFIG_ERRATA_THEAD
> + case THEAD_VENDOR_ID:
> + vendor_patch_func = thead_errata_patch_func;
> + break;
> #endif
> default:
> vendor_patch_func = NULL;
> @@ -85,6 +90,15 @@ void __init apply_boot_alternatives(void)
> RISCV_ALTERNATIVES_BOOT);
> }
>
> +void __init apply_early_boot_alternatives(void)
> +{
> + init_alternative();
> +
> + _apply_alternatives((struct alt_entry *)__alt_start,
> + (struct alt_entry *)__alt_end,
> + RISCV_ALTERNATIVES_EARLY_BOOT);
> +}
> +
The name is a bit confusing as there is another "apply_boot_alternatives"
which was called earlier than "apply_early_boot_alternatives".
> #ifdef CONFIG_MODULES
> void apply_module_alternatives(void *start, size_t length)
> {
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 7bce66ee7ce7..ecc248e5dab7 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -224,6 +224,8 @@ static bool cpufeature_svpbmt_check_func(unsigned int stage)
>
> #if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> switch (stage) {
> + case RISCV_ALTERNATIVES_EARLY_BOOT:
> + return false;
> case RISCV_ALTERNATIVES_BOOT:
> return cpufeature_svpbmt_check_fdt();
> default:
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index cf4d018b7d66..7216db5d6a2c 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -819,6 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K);
> #endif
>
> + apply_early_boot_alternatives();
> pt_ops_set_early();
>
> /* Setup early PGD for fixmap */
> --
> 2.30.2
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
--
Regards,
Atish
On Thu, Feb 10, 2022 at 4:25 PM Atish Patra <[email protected]> wrote:
>
> On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
> >
> > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > for things like non-cacheable pages or I/O memory pages.
> >
> >
> > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > types) using the alternatives framework.
> >
> > This includes a number of changes to the alternatives mechanism itself.
> > The biggest one being the move to a more central location, as I expect
> > in the future, nearly every chip needing some sort of patching, be it
> > either for erratas or for optional features (svpbmt or others).
> >
> > The dt-binding for svpbmt itself is of course not finished and is still
> > using the binding introduced in previous versions, as where to put
> > a svpbmt-property in the devicetree is still under dicussion.
> > Atish seems to be working on a framework for extensions [0],
> >
>
> Here is the patch series
> https://lore.kernel.org/lkml/[email protected]/
>
> I think we can simplify the cpu feature probing in PATCH 10 with the
> above series
> which simply relies on the existing riscv_isa bitmap.
>
> We also don't need the separate svpbmt property in DT mmu node.
> Let me know what you think.
>
> > The series also introduces support for the memory types of the D1
> > which are implemented differently to svpbmt. But when patching anyway
> > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > location.
> >
> > The only slightly bigger difference is that the "normal" type is not 0
> > as with svpbmt, so kernel patches for this PMA type need to be applied
> > even before the MMU is brought up, so the series introduces a separate
> > stage for that.
> >
> >
> > In theory this series is 3 parts:
> > - sbi cache-flush / null-ptr
> > - alternatives improvements
> > - svpbmt+d1
> >
> > So expecially patches from the first 2 areas could be applied when
> > deemed ready, I just thought to keep it together to show-case where
> > the end-goal is and not requiring jumping between different series.
> >
> >
> > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > as it touches a similar area in mm/cacheflush.c
> >
> >
> > I picked the recipient list from the previous version, hopefully
> > I didn't forget anybody.
> >
I am also getting a load access fault while booting this series in Qemu.
<with additional debug message when before sbi_trap_redirect in OpenSBI>
sbi_trap_error_debug: hart1: trap handler failed (error -2)
sbi_trap_error_debug: hart1: mcause=0x0000000000000005 mtval=0x0000000080046468
sbi_trap_error_debug: hart1: mtval2=0x0000000000000000 mtinst=0x0000000000000000
sbi_trap_error_debug: hart1: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
sbi_trap_error_debug: hart1: ra=0x0000000080202b06 sp=0x0000000081203f00
sbi_trap_error_debug: hart1: gp=0x00000000812d9db8 tp=0x0000000080046000
sbi_trap_error_debug: hart1: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
sbi_trap_error_debug: hart1: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
sbi_trap_error_debug: hart1: a2=0x0000000000000002 a3=0x0000000000000000
sbi_trap_error_debug: hart1: a4=0x00000000812da902 a5=0x0000000000000000
sbi_trap_error_debug: hart1: a6=0x0000000000000006 a7=0x0000000000000010
sbi_trap_error_debug: hart1: s2=0x0000000080c1b0d0 s3=0x0000000000000002
sbi_trap_error_debug: hart1: s4=0x00000000bf000000 s5=0x0000000000000000
sbi_trap_error_debug: hart1: s6=0x8000000a00006800 s7=0x000000000000007f
sbi_trap_error_debug: hart1: s8=0x0000000080018038 s9=0x0000000080039eac
sbi_trap_error_debug: hart1: s10=0x0000000000000000 s11=0x0000000000000000
sbi_trap_error_debug: hart1: t0=0x0000000080c04000 t1=0x0000000000000002
sbi_trap_error_debug: hart1: t2=0x0000000000001000 t3=0x0000000000000010
sbi_trap_error_debug: hart1: t4=0x00000000800168be t5=0x0000000000000027
sbi_trap_error_debug: hart1: t6=0x0000000000000001
mepc : 0x000000008080a8b8 - call_function_init (kernel/smp.c)
Kernel - 5.17-rc2 + my patches
Qemu - Alistairs next tree + my patches
I do have some out-of-tree patches but that shouldn't be an issue as I
am able to boot without your patches.
Commenting the *_boot_alternatives at both the places works fine as well.
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index 0e1bb97f9749..bdeb7ab3e719 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -342,7 +342,7 @@ clear_bss_done:
call kasan_early_init
#endif
/* Start the kernel */
- call apply_boot_alternatives
+ //call apply_boot_alternatives
call soc_early_init
tail start_kernel
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 7216db5d6a2c..c6bf8f4d3d16 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -819,7 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
BUG_ON((kernel_map.virt_addr + kernel_map.size) >
ADDRESS_SPACE_END - SZ_4K);
#endif
- apply_early_boot_alternatives();
+ //apply_early_boot_alternatives();
pt_ops_set_early();
/* Setup early PGD for fixmap */
I am currently debugging it and will let you know if I find the root cause.
> > changes in v6:
> > - rebase onto 5.17-rc1
> > - handle sbi null-ptr differently
> > - improve commit messages
> > - use riscv,mmu as property name
> >
> > changes in v5:
> > - move to use alternatives for runtime-patching
> > - add D1 variant
> >
> >
> > [0] https://lore.kernel.org/r/[email protected]
> > [1] https://lore.kernel.org/r/[email protected]
> >
> >
> > Heiko Stuebner (12):
> > riscv: prevent null-pointer dereference with sbi_remote_fence_i
> > riscv: integrate alternatives better into the main architecture
> > riscv: allow different stages with alternatives
> > riscv: implement module alternatives
> > riscv: implement ALTERNATIVE_2 macro
> > riscv: extend concatenated alternatives-lines to the same length
> > riscv: prevent compressed instructions in alternatives
> > riscv: move boot alternatives to a slightly earlier position
> > riscv: Fix accessing pfn bits in PTEs for non-32bit variants
> > riscv: add cpufeature handling via alternatives
> > riscv: remove FIXMAP_PAGE_IO and fall back to its default value
> > riscv: add memory-type errata for T-Head
> >
> > Wei Fu (2):
> > dt-bindings: riscv: add MMU Standard Extensions support for Svpbmt
> > riscv: add RISC-V Svpbmt extension support
> >
> > .../devicetree/bindings/riscv/cpus.yaml | 10 ++
> > arch/riscv/Kconfig.erratas | 29 ++--
> > arch/riscv/Kconfig.socs | 1 -
> > arch/riscv/Makefile | 2 +-
> > arch/riscv/errata/Makefile | 2 +-
> > arch/riscv/errata/sifive/errata.c | 10 +-
> > arch/riscv/errata/thead/Makefile | 1 +
> > arch/riscv/errata/thead/errata.c | 85 +++++++++++
> > arch/riscv/include/asm/alternative-macros.h | 114 ++++++++-------
> > arch/riscv/include/asm/alternative.h | 16 ++-
> > arch/riscv/include/asm/errata_list.h | 52 +++++++
> > arch/riscv/include/asm/fixmap.h | 2 -
> > arch/riscv/include/asm/pgtable-32.h | 17 +++
> > arch/riscv/include/asm/pgtable-64.h | 79 +++++++++-
> > arch/riscv/include/asm/pgtable-bits.h | 10 --
> > arch/riscv/include/asm/pgtable.h | 53 +++++--
> > arch/riscv/include/asm/vendorid_list.h | 1 +
> > arch/riscv/kernel/Makefile | 1 +
> > arch/riscv/{errata => kernel}/alternative.c | 48 ++++++-
> > arch/riscv/kernel/cpufeature.c | 136 +++++++++++++++++-
> > arch/riscv/kernel/head.S | 2 +
> > arch/riscv/kernel/module.c | 29 ++++
> > arch/riscv/kernel/sbi.c | 10 +-
> > arch/riscv/kernel/smpboot.c | 4 -
> > arch/riscv/kernel/traps.c | 2 +-
> > arch/riscv/mm/init.c | 1 +
> > 26 files changed, 606 insertions(+), 111 deletions(-)
> > create mode 100644 arch/riscv/errata/thead/Makefile
> > create mode 100644 arch/riscv/errata/thead/errata.c
> > rename arch/riscv/{errata => kernel}/alternative.c (59%)
> >
> > --
> > 2.30.2
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
>
>
>
> --
> Regards,
> Atish
--
Regards,
Atish
On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
>
> Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> for things like non-cacheable pages or I/O memory pages.
>
>
> So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> types) using the alternatives framework.
>
> This includes a number of changes to the alternatives mechanism itself.
> The biggest one being the move to a more central location, as I expect
> in the future, nearly every chip needing some sort of patching, be it
> either for erratas or for optional features (svpbmt or others).
>
> The dt-binding for svpbmt itself is of course not finished and is still
> using the binding introduced in previous versions, as where to put
> a svpbmt-property in the devicetree is still under dicussion.
> Atish seems to be working on a framework for extensions [0],
>
Here is the patch series
https://lore.kernel.org/lkml/[email protected]/
I think we can simplify the cpu feature probing in PATCH 10 with the
above series
which simply relies on the existing riscv_isa bitmap.
We also don't need the separate svpbmt property in DT mmu node.
Let me know what you think.
> The series also introduces support for the memory types of the D1
> which are implemented differently to svpbmt. But when patching anyway
> it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> location.
>
> The only slightly bigger difference is that the "normal" type is not 0
> as with svpbmt, so kernel patches for this PMA type need to be applied
> even before the MMU is brought up, so the series introduces a separate
> stage for that.
>
>
> In theory this series is 3 parts:
> - sbi cache-flush / null-ptr
> - alternatives improvements
> - svpbmt+d1
>
> So expecially patches from the first 2 areas could be applied when
> deemed ready, I just thought to keep it together to show-case where
> the end-goal is and not requiring jumping between different series.
>
>
> The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> as it touches a similar area in mm/cacheflush.c
>
>
> I picked the recipient list from the previous version, hopefully
> I didn't forget anybody.
>
> changes in v6:
> - rebase onto 5.17-rc1
> - handle sbi null-ptr differently
> - improve commit messages
> - use riscv,mmu as property name
>
> changes in v5:
> - move to use alternatives for runtime-patching
> - add D1 variant
>
>
> [0] https://lore.kernel.org/r/[email protected]
> [1] https://lore.kernel.org/r/[email protected]
>
>
> Heiko Stuebner (12):
> riscv: prevent null-pointer dereference with sbi_remote_fence_i
> riscv: integrate alternatives better into the main architecture
> riscv: allow different stages with alternatives
> riscv: implement module alternatives
> riscv: implement ALTERNATIVE_2 macro
> riscv: extend concatenated alternatives-lines to the same length
> riscv: prevent compressed instructions in alternatives
> riscv: move boot alternatives to a slightly earlier position
> riscv: Fix accessing pfn bits in PTEs for non-32bit variants
> riscv: add cpufeature handling via alternatives
> riscv: remove FIXMAP_PAGE_IO and fall back to its default value
> riscv: add memory-type errata for T-Head
>
> Wei Fu (2):
> dt-bindings: riscv: add MMU Standard Extensions support for Svpbmt
> riscv: add RISC-V Svpbmt extension support
>
> .../devicetree/bindings/riscv/cpus.yaml | 10 ++
> arch/riscv/Kconfig.erratas | 29 ++--
> arch/riscv/Kconfig.socs | 1 -
> arch/riscv/Makefile | 2 +-
> arch/riscv/errata/Makefile | 2 +-
> arch/riscv/errata/sifive/errata.c | 10 +-
> arch/riscv/errata/thead/Makefile | 1 +
> arch/riscv/errata/thead/errata.c | 85 +++++++++++
> arch/riscv/include/asm/alternative-macros.h | 114 ++++++++-------
> arch/riscv/include/asm/alternative.h | 16 ++-
> arch/riscv/include/asm/errata_list.h | 52 +++++++
> arch/riscv/include/asm/fixmap.h | 2 -
> arch/riscv/include/asm/pgtable-32.h | 17 +++
> arch/riscv/include/asm/pgtable-64.h | 79 +++++++++-
> arch/riscv/include/asm/pgtable-bits.h | 10 --
> arch/riscv/include/asm/pgtable.h | 53 +++++--
> arch/riscv/include/asm/vendorid_list.h | 1 +
> arch/riscv/kernel/Makefile | 1 +
> arch/riscv/{errata => kernel}/alternative.c | 48 ++++++-
> arch/riscv/kernel/cpufeature.c | 136 +++++++++++++++++-
> arch/riscv/kernel/head.S | 2 +
> arch/riscv/kernel/module.c | 29 ++++
> arch/riscv/kernel/sbi.c | 10 +-
> arch/riscv/kernel/smpboot.c | 4 -
> arch/riscv/kernel/traps.c | 2 +-
> arch/riscv/mm/init.c | 1 +
> 26 files changed, 606 insertions(+), 111 deletions(-)
> create mode 100644 arch/riscv/errata/thead/Makefile
> create mode 100644 arch/riscv/errata/thead/errata.c
> rename arch/riscv/{errata => kernel}/alternative.c (59%)
>
> --
> 2.30.2
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
--
Regards,
Atish
On Wed, Feb 9, 2022 at 4:41 AM Heiko Stuebner <[email protected]> wrote:
>
> Some current cpus based on T-Head cores implement memory-types
> way different than described in the svpbmt spec even going
> so far as using PTE bits marked as reserved.
>
> Add the T-Head vendor-id and necessary errata code to
> replace the affected instructions.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/Kconfig.erratas | 19 ++++++
> arch/riscv/errata/Makefile | 1 +
> arch/riscv/errata/sifive/errata.c | 7 ++-
> arch/riscv/errata/thead/Makefile | 1 +
> arch/riscv/errata/thead/errata.c | 85 ++++++++++++++++++++++++++
> arch/riscv/include/asm/alternative.h | 5 ++
> arch/riscv/include/asm/errata_list.h | 47 ++++++++++++--
> arch/riscv/include/asm/pgtable-64.h | 18 +++++-
> arch/riscv/include/asm/pgtable.h | 18 +++++-
> arch/riscv/include/asm/vendorid_list.h | 1 +
> arch/riscv/kernel/alternative.c | 14 +++++
> arch/riscv/kernel/cpufeature.c | 2 +
> arch/riscv/mm/init.c | 1 +
> 13 files changed, 210 insertions(+), 9 deletions(-)
> create mode 100644 arch/riscv/errata/thead/Makefile
> create mode 100644 arch/riscv/errata/thead/errata.c
>
> diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> index d18be8ff0245..380ec039c3dc 100644
> --- a/arch/riscv/Kconfig.erratas
> +++ b/arch/riscv/Kconfig.erratas
> @@ -31,4 +31,23 @@ config ERRATA_SIFIVE_CIP_1200
>
> If you don't know what to do here, say "Y".
>
> +config ERRATA_THEAD
> + bool "T-HEAD errata"
> + help
> + All T-HEAD errata Kconfig depend on this Kconfig. Disabling
> + this Kconfig will disable all T-HEAD errata. Please say "Y"
> + here if your platform uses T-HEAD CPU cores.
> +
> + If you don't know what to do here, say "Y".
> +
Shouldn't it say otherwise similar to ERRATA_SIFIVE
"Otherwise, please say "N" here to avoid unnecessary overhead."
> +config ERRATA_THEAD_PBMT
> + bool "Apply T-Head memory type errata"
> + depends on ERRATA_THEAD && 64BIT
> + default y
> + help
> + This will apply the memory type errata to handle the non-standard
> + memory type bits in page-table-entries on T-Head SoCs.
> +
> + If you don't know what to do here, say "Y".
> +
> endmenu
> diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> index 0ca1c5281a2d..a1055965fbee 100644
> --- a/arch/riscv/errata/Makefile
> +++ b/arch/riscv/errata/Makefile
> @@ -1 +1,2 @@
> obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> +obj-$(CONFIG_ERRATA_THEAD) += thead/
> diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> index 4fe03ac41fd7..f933d6cdf304 100644
> --- a/arch/riscv/errata/sifive/errata.c
> +++ b/arch/riscv/errata/sifive/errata.c
> @@ -84,10 +84,15 @@ void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *
> unsigned int stage)
> {
> struct alt_entry *alt;
> - u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> + u32 cpu_req_errata;
> u32 cpu_apply_errata = 0;
> u32 tmp;
>
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + return;
> +
> + cpu_req_errata = sifive_errata_probe(archid, impid);
> +
> for (alt = begin; alt < end; alt++) {
> if (alt->vendor_id != SIFIVE_VENDOR_ID)
> continue;
> diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile
> new file mode 100644
> index 000000000000..2d644e19caef
> --- /dev/null
> +++ b/arch/riscv/errata/thead/Makefile
> @@ -0,0 +1 @@
> +obj-y += errata.o
> diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
> new file mode 100644
> index 000000000000..fd8e0538a3f0
> --- /dev/null
> +++ b/arch/riscv/errata/thead/errata.c
> @@ -0,0 +1,85 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2021 Heiko Stuebner <[email protected]>
> + */
> +
> +#include <linux/bug.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/string.h>
> +#include <linux/uaccess.h>
> +#include <asm/alternative.h>
> +#include <asm/cacheflush.h>
> +#include <asm/errata_list.h>
> +#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)
> +{
> + 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
> + },
> +};
> +
> +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);
> + }
> +
> + return cpu_req_errata;
> +}
> +
> +void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> + unsigned long archid, unsigned long impid,
> + unsigned int stage)
> +{
> + struct alt_entry *alt;
> + u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
> + u32 cpu_apply_errata = 0;
> + u32 tmp;
> +
> + for (alt = begin; alt < end; alt++) {
> + if (alt->vendor_id != THEAD_VENDOR_ID)
> + continue;
> + if (alt->errata_id >= ERRATA_THEAD_NUMBER)
> + continue;
> +
> + tmp = (1U << alt->errata_id);
> + if (cpu_req_errata & tmp) {
> + /* On vm-alternatives, the mmu isn't running yet */
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + memcpy((void *)__pa_symbol(alt->old_ptr),
> + (void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
> + else
> + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> +
> + cpu_apply_errata |= tmp;
> + }
> + }
> +
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + local_flush_icache_all();
> +}
> diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> index cf3b22173834..d1154c91ab03 100644
> --- a/arch/riscv/include/asm/alternative.h
> +++ b/arch/riscv/include/asm/alternative.h
> @@ -19,8 +19,10 @@
>
> #define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */
> #define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */
> +#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */
>
> void __init apply_boot_alternatives(void);
> +void __init apply_early_boot_alternatives(void);
> void apply_module_alternatives(void *start, size_t length);
>
> struct alt_entry {
> @@ -39,6 +41,9 @@ struct errata_checkfunc_id {
> void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned long archid, unsigned long impid,
> unsigned int stage);
> +void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> + unsigned long archid, unsigned long impid,
> + unsigned int stage);
>
> void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned int stage);
> diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> index a4a9b0842922..4fac46b82c16 100644
> --- a/arch/riscv/include/asm/errata_list.h
> +++ b/arch/riscv/include/asm/errata_list.h
> @@ -14,6 +14,11 @@
> #define ERRATA_SIFIVE_NUMBER 2
> #endif
>
> +#ifdef CONFIG_ERRATA_THEAD
> +#define ERRATA_THEAD_PBMT 0
> +#define ERRATA_THEAD_NUMBER 1
> +#endif
> +
> #define CPUFEATURE_SVPBMT 0
> #define CPUFEATURE_NUMBER 1
>
> @@ -42,10 +47,44 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
> * in the default case.
> */
> #define ALT_SVPBMT_SHIFT 61
> -#define ALT_SVPBMT(_val, prot) \
> -asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,%2", 0, \
> - CPUFEATURE_SVPBMT, CONFIG_64BIT) \
> - : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), "I"(ALT_SVPBMT_SHIFT))
> +#define ALT_THEAD_PBMT_SHIFT 59
> +#define ALT_SVPBMT(_val, prot) \
> +asm(ALTERNATIVE_2("li %0, 0\t\nnop", \
> + "li %0, %1\t\nslli %0,%0,%3", 0, CPUFEATURE_SVPBMT, CONFIG_64BIT, \
> + "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, \
> + CONFIG_ERRATA_THEAD_PBMT) \
> + : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \
> + "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> + "I"(ALT_SVPBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> +
> +#ifdef CONFIG_ERRATA_THEAD_PBMT
> +/*
> + * IO/NOCACHE memory types are handled together with svpbmt,
> + * so on T-Head chips, check if no other memory type is set,
> + * and set the non-0 PMA type if applicable.
> + */
> +#define ALT_THEAD_PMA(_val) \
> +asm volatile(ALTERNATIVE( \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop\n\t" \
> + "nop", \
> + "li t3, %2\n\t" \
> + "slli t3, t3, %4\n\t" \
> + "and t3, %0, t3\n\t" \
> + "bne t3, zero, 2f\n\t" \
> + "li t3, %3\n\t" \
> + "slli t3, t3, %4\n\t" \
> + "or %0, %0, t3\n\t" \
> + "2:", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
> + : "+r"(_val) : "0"(_val), "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> + "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> +#else
> +#define ALT_THEAD_PMA(_val)
> +#endif
>
> #endif /* __ASSEMBLY__ */
>
> diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> index 07ba3416cb19..6d59e4695200 100644
> --- a/arch/riscv/include/asm/pgtable-64.h
> +++ b/arch/riscv/include/asm/pgtable-64.h
> @@ -69,6 +69,18 @@ typedef struct {
> #define _PAGE_IO_SVPBMT (1UL << 62)
> #define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
>
> +/*
> + * [63:59] T-Head Memory Type definitions:
> + *
> + * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> + * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
> + * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> + */
> +#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
> +#define _PAGE_NOCACHE_THEAD 0UL
> +#define _PAGE_IO_THEAD (1UL << 63)
> +#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
> +
> static inline u64 riscv_page_mtmask(void)
> {
> u64 val;
> @@ -167,7 +179,11 @@ static inline bool mm_pud_folded(struct mm_struct *mm)
>
> static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
> {
> - return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> + unsigned long prot_val = pgprot_val(prot);
> +
> + ALT_THEAD_PMA(prot_val);
> +
> + return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> }
>
> static inline unsigned long _pmd_pfn(pmd_t pmd)
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index b8abc75dfe01..3d0c4c144093 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -245,7 +245,11 @@ static inline void pmd_clear(pmd_t *pmdp)
>
> static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot)
> {
> - return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> + unsigned long prot_val = pgprot_val(prot);
> +
> + ALT_THEAD_PMA(prot_val);
> +
> + return __pgd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> }
>
> static inline unsigned long _pgd_pfn(pgd_t pgd)
> @@ -284,7 +288,11 @@ static inline unsigned long pte_pfn(pte_t pte)
> /* Constructs a page table entry */
> static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
> {
> - return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> + unsigned long prot_val = pgprot_val(prot);
> +
> + ALT_THEAD_PMA(prot_val);
> +
> + return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val);
> }
>
> #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
> @@ -393,7 +401,11 @@ static inline int pmd_protnone(pmd_t pmd)
> /* Modify page protection bits */
> static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> {
> - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
> + unsigned long newprot_val = pgprot_val(newprot);
> +
> + ALT_THEAD_PMA(newprot_val);
> +
> + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | newprot_val);
> }
>
> #define pgd_ERROR(e) \
> diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
> index 9d934215b3c8..cb89af3f0704 100644
> --- a/arch/riscv/include/asm/vendorid_list.h
> +++ b/arch/riscv/include/asm/vendorid_list.h
> @@ -6,5 +6,6 @@
> #define ASM_VENDOR_LIST_H
>
> #define SIFIVE_VENDOR_ID 0x489
> +#define THEAD_VENDOR_ID 0x5b7
>
> #endif
> diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> index e6c9de9f9ba6..3f6ad91f524c 100644
> --- a/arch/riscv/kernel/alternative.c
> +++ b/arch/riscv/kernel/alternative.c
> @@ -48,6 +48,11 @@ static void __init init_alternative(void)
> case SIFIVE_VENDOR_ID:
> vendor_patch_func = sifive_errata_patch_func;
> break;
> +#endif
> +#ifdef CONFIG_ERRATA_THEAD
> + case THEAD_VENDOR_ID:
> + vendor_patch_func = thead_errata_patch_func;
> + break;
> #endif
> default:
> vendor_patch_func = NULL;
> @@ -85,6 +90,15 @@ void __init apply_boot_alternatives(void)
> RISCV_ALTERNATIVES_BOOT);
> }
>
> +void __init apply_early_boot_alternatives(void)
> +{
> + init_alternative();
> +
> + _apply_alternatives((struct alt_entry *)__alt_start,
> + (struct alt_entry *)__alt_end,
> + RISCV_ALTERNATIVES_EARLY_BOOT);
> +}
> +
> #ifdef CONFIG_MODULES
> void apply_module_alternatives(void *start, size_t length)
> {
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 7bce66ee7ce7..ecc248e5dab7 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -224,6 +224,8 @@ static bool cpufeature_svpbmt_check_func(unsigned int stage)
>
> #if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> switch (stage) {
> + case RISCV_ALTERNATIVES_EARLY_BOOT:
> + return false;
> case RISCV_ALTERNATIVES_BOOT:
> return cpufeature_svpbmt_check_fdt();
> default:
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index cf4d018b7d66..7216db5d6a2c 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -819,6 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K);
> #endif
>
> + apply_early_boot_alternatives();
> pt_ops_set_early();
>
> /* Setup early PGD for fixmap */
> --
> 2.30.2
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
--
Regards,
Atish
Hi Atish,
Am Freitag, 11. Februar 2022, 01:12:55 CET schrieb Atish Patra:
> On Wed, Feb 9, 2022 at 4:41 AM Heiko Stuebner <[email protected]> wrote:
> >
> > Some current cpus based on T-Head cores implement memory-types
> > way different than described in the svpbmt spec even going
> > so far as using PTE bits marked as reserved.
> >
> > Add the T-Head vendor-id and necessary errata code to
> > replace the affected instructions.
> >
> > Signed-off-by: Heiko Stuebner <[email protected]>
> > ---
> > arch/riscv/Kconfig.erratas | 19 ++++++
> > arch/riscv/errata/Makefile | 1 +
> > arch/riscv/errata/sifive/errata.c | 7 ++-
> > arch/riscv/errata/thead/Makefile | 1 +
> > arch/riscv/errata/thead/errata.c | 85 ++++++++++++++++++++++++++
> > arch/riscv/include/asm/alternative.h | 5 ++
> > arch/riscv/include/asm/errata_list.h | 47 ++++++++++++--
> > arch/riscv/include/asm/pgtable-64.h | 18 +++++-
> > arch/riscv/include/asm/pgtable.h | 18 +++++-
> > arch/riscv/include/asm/vendorid_list.h | 1 +
> > arch/riscv/kernel/alternative.c | 14 +++++
> > arch/riscv/kernel/cpufeature.c | 2 +
> > arch/riscv/mm/init.c | 1 +
> > 13 files changed, 210 insertions(+), 9 deletions(-)
> > create mode 100644 arch/riscv/errata/thead/Makefile
> > create mode 100644 arch/riscv/errata/thead/errata.c
> >
> > diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> > index d18be8ff0245..380ec039c3dc 100644
> > --- a/arch/riscv/Kconfig.erratas
> > +++ b/arch/riscv/Kconfig.erratas
> > @@ -31,4 +31,23 @@ config ERRATA_SIFIVE_CIP_1200
> >
> > If you don't know what to do here, say "Y".
> >
> > +config ERRATA_THEAD
> > + bool "T-HEAD errata"
> > + help
> > + All T-HEAD errata Kconfig depend on this Kconfig. Disabling
> > + this Kconfig will disable all T-HEAD errata. Please say "Y"
> > + here if your platform uses T-HEAD CPU cores.
> > +
> > + If you don't know what to do here, say "Y".
> > +
> > +config ERRATA_THEAD_PBMT
> > + bool "Apply T-Head memory type errata"
> > + depends on ERRATA_THEAD && 64BIT
> > + default y
> > + help
> > + This will apply the memory type errata to handle the non-standard
> > + memory type bits in page-table-entries on T-Head SoCs.
> > +
> > + If you don't know what to do here, say "Y".
> > +
> > endmenu
> > diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> > index 0ca1c5281a2d..a1055965fbee 100644
> > --- a/arch/riscv/errata/Makefile
> > +++ b/arch/riscv/errata/Makefile
> > @@ -1 +1,2 @@
> > obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> > +obj-$(CONFIG_ERRATA_THEAD) += thead/
> > diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> > index 4fe03ac41fd7..f933d6cdf304 100644
> > --- a/arch/riscv/errata/sifive/errata.c
> > +++ b/arch/riscv/errata/sifive/errata.c
> > @@ -84,10 +84,15 @@ void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *
> > unsigned int stage)
> > {
> > struct alt_entry *alt;
> > - u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> > + u32 cpu_req_errata;
> > u32 cpu_apply_errata = 0;
> > u32 tmp;
> >
> > + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> > + return;
> > +
> > + cpu_req_errata = sifive_errata_probe(archid, impid);
> > +
> > for (alt = begin; alt < end; alt++) {
> > if (alt->vendor_id != SIFIVE_VENDOR_ID)
> > continue;
> > diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile
> > new file mode 100644
> > index 000000000000..2d644e19caef
> > --- /dev/null
> > +++ b/arch/riscv/errata/thead/Makefile
> > @@ -0,0 +1 @@
> > +obj-y += errata.o
> > diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
> > new file mode 100644
> > index 000000000000..fd8e0538a3f0
> > --- /dev/null
> > +++ b/arch/riscv/errata/thead/errata.c
> > @@ -0,0 +1,85 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (C) 2021 Heiko Stuebner <[email protected]>
> > + */
> > +
> > +#include <linux/bug.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/string.h>
> > +#include <linux/uaccess.h>
> > +#include <asm/alternative.h>
> > +#include <asm/cacheflush.h>
> > +#include <asm/errata_list.h>
> > +#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)
> > +{
> > + 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
> > + },
> > +};
> > +
> > +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);
> > + }
> > +
> > + return cpu_req_errata;
> > +}
> > +
> > +void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > + unsigned long archid, unsigned long impid,
> > + unsigned int stage)
> > +{
> > + struct alt_entry *alt;
> > + u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
> > + u32 cpu_apply_errata = 0;
> > + u32 tmp;
> > +
> > + for (alt = begin; alt < end; alt++) {
> > + if (alt->vendor_id != THEAD_VENDOR_ID)
> > + continue;
> > + if (alt->errata_id >= ERRATA_THEAD_NUMBER)
> > + continue;
> > +
> > + tmp = (1U << alt->errata_id);
> > + if (cpu_req_errata & tmp) {
> > + /* On vm-alternatives, the mmu isn't running yet */
> > + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> > + memcpy((void *)__pa_symbol(alt->old_ptr),
> > + (void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
> > + else
> > + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> > +
> > + cpu_apply_errata |= tmp;
> > + }
> > + }
> > +
> > + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> > + local_flush_icache_all();
> > +}
> > diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> > index cf3b22173834..d1154c91ab03 100644
> > --- a/arch/riscv/include/asm/alternative.h
> > +++ b/arch/riscv/include/asm/alternative.h
> > @@ -19,8 +19,10 @@
> >
> > #define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */
> > #define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */
> > +#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */
> >
>
> But this stage invoked is used after RISCV_ALTERNATIVES_BOOT
No it isn't.
the "boot" alternative is applied right now directly before soc_early_init,
while the "early-boot" alternative is already applied during setup_vm()
even before page-tables are set up.
Right now the numbering doesn't reflect the order and just
makes it distinct, but I guess we can adjust it to make that clear
(move early_boot to the top)
> > void __init apply_boot_alternatives(void);
> > +void __init apply_early_boot_alternatives(void);
> > void apply_module_alternatives(void *start, size_t length);
> >
> > struct alt_entry {
> > @@ -39,6 +41,9 @@ struct errata_checkfunc_id {
> > void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > unsigned long archid, unsigned long impid,
> > unsigned int stage);
> > +void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > + unsigned long archid, unsigned long impid,
> > + unsigned int stage);
> >
> > void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > unsigned int stage);
> > diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> > index a4a9b0842922..4fac46b82c16 100644
> > --- a/arch/riscv/include/asm/errata_list.h
> > +++ b/arch/riscv/include/asm/errata_list.h
> > @@ -14,6 +14,11 @@
> > #define ERRATA_SIFIVE_NUMBER 2
> > #endif
> >
> > +#ifdef CONFIG_ERRATA_THEAD
> > +#define ERRATA_THEAD_PBMT 0
> > +#define ERRATA_THEAD_NUMBER 1
> > +#endif
> > +
> > #define CPUFEATURE_SVPBMT 0
> > #define CPUFEATURE_NUMBER 1
> >
> > @@ -42,10 +47,44 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
> > * in the default case.
> > */
> > #define ALT_SVPBMT_SHIFT 61
> > -#define ALT_SVPBMT(_val, prot) \
> > -asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,%2", 0, \
> > - CPUFEATURE_SVPBMT, CONFIG_64BIT) \
> > - : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), "I"(ALT_SVPBMT_SHIFT))
> > +#define ALT_THEAD_PBMT_SHIFT 59
> > +#define ALT_SVPBMT(_val, prot) \
> > +asm(ALTERNATIVE_2("li %0, 0\t\nnop", \
> > + "li %0, %1\t\nslli %0,%0,%3", 0, CPUFEATURE_SVPBMT, CONFIG_64BIT, \
> > + "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, \
> > + CONFIG_ERRATA_THEAD_PBMT) \
> > + : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \
> > + "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> > + "I"(ALT_SVPBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> > +
> > +#ifdef CONFIG_ERRATA_THEAD_PBMT
> > +/*
> > + * IO/NOCACHE memory types are handled together with svpbmt,
> > + * so on T-Head chips, check if no other memory type is set,
> > + * and set the non-0 PMA type if applicable.
> > + */
> > +#define ALT_THEAD_PMA(_val) \
> > +asm volatile(ALTERNATIVE( \
> > + "nop\n\t" \
> > + "nop\n\t" \
> > + "nop\n\t" \
> > + "nop\n\t" \
> > + "nop\n\t" \
> > + "nop\n\t" \
> > + "nop", \
> > + "li t3, %2\n\t" \
> > + "slli t3, t3, %4\n\t" \
> > + "and t3, %0, t3\n\t" \
> > + "bne t3, zero, 2f\n\t" \
> > + "li t3, %3\n\t" \
> > + "slli t3, t3, %4\n\t" \
> > + "or %0, %0, t3\n\t" \
> > + "2:", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
> > + : "+r"(_val) : "0"(_val), "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> > + "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> > +#else
> > +#define ALT_THEAD_PMA(_val)
> > +#endif
> >
> > #endif /* __ASSEMBLY__ */
> >
> > diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> > index 07ba3416cb19..6d59e4695200 100644
> > --- a/arch/riscv/include/asm/pgtable-64.h
> > +++ b/arch/riscv/include/asm/pgtable-64.h
> > @@ -69,6 +69,18 @@ typedef struct {
> > #define _PAGE_IO_SVPBMT (1UL << 62)
> > #define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
> >
> > +/*
> > + * [63:59] T-Head Memory Type definitions:
> > + *
> > + * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> > + * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
> > + * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> > + */
> > +#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
> > +#define _PAGE_NOCACHE_THEAD 0UL
> > +#define _PAGE_IO_THEAD (1UL << 63)
> > +#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
> > +
> > static inline u64 riscv_page_mtmask(void)
> > {
> > u64 val;
> > @@ -167,7 +179,11 @@ static inline bool mm_pud_folded(struct mm_struct *mm)
> >
> > static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
> > {
> > - return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> > + unsigned long prot_val = pgprot_val(prot);
> > +
> > + ALT_THEAD_PMA(prot_val);
> > +
> > + return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> > }
> >
> > static inline unsigned long _pmd_pfn(pmd_t pmd)
> > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > index b8abc75dfe01..3d0c4c144093 100644
> > --- a/arch/riscv/include/asm/pgtable.h
> > +++ b/arch/riscv/include/asm/pgtable.h
> > @@ -245,7 +245,11 @@ static inline void pmd_clear(pmd_t *pmdp)
> >
> > static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot)
> > {
> > - return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> > + unsigned long prot_val = pgprot_val(prot);
> > +
> > + ALT_THEAD_PMA(prot_val);
> > +
> > + return __pgd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> > }
> >
> > static inline unsigned long _pgd_pfn(pgd_t pgd)
> > @@ -284,7 +288,11 @@ static inline unsigned long pte_pfn(pte_t pte)
> > /* Constructs a page table entry */
> > static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
> > {
> > - return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> > + unsigned long prot_val = pgprot_val(prot);
> > +
> > + ALT_THEAD_PMA(prot_val);
> > +
> > + return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val);
> > }
> >
> > #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
> > @@ -393,7 +401,11 @@ static inline int pmd_protnone(pmd_t pmd)
> > /* Modify page protection bits */
> > static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> > {
> > - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
> > + unsigned long newprot_val = pgprot_val(newprot);
> > +
> > + ALT_THEAD_PMA(newprot_val);
> > +
> > + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | newprot_val);
> > }
> >
> > #define pgd_ERROR(e) \
> > diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
> > index 9d934215b3c8..cb89af3f0704 100644
> > --- a/arch/riscv/include/asm/vendorid_list.h
> > +++ b/arch/riscv/include/asm/vendorid_list.h
> > @@ -6,5 +6,6 @@
> > #define ASM_VENDOR_LIST_H
> >
> > #define SIFIVE_VENDOR_ID 0x489
> > +#define THEAD_VENDOR_ID 0x5b7
> >
> > #endif
> > diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> > index e6c9de9f9ba6..3f6ad91f524c 100644
> > --- a/arch/riscv/kernel/alternative.c
> > +++ b/arch/riscv/kernel/alternative.c
> > @@ -48,6 +48,11 @@ static void __init init_alternative(void)
> > case SIFIVE_VENDOR_ID:
> > vendor_patch_func = sifive_errata_patch_func;
> > break;
> > +#endif
> > +#ifdef CONFIG_ERRATA_THEAD
> > + case THEAD_VENDOR_ID:
> > + vendor_patch_func = thead_errata_patch_func;
> > + break;
> > #endif
> > default:
> > vendor_patch_func = NULL;
> > @@ -85,6 +90,15 @@ void __init apply_boot_alternatives(void)
> > RISCV_ALTERNATIVES_BOOT);
> > }
> >
> > +void __init apply_early_boot_alternatives(void)
> > +{
> > + init_alternative();
> > +
> > + _apply_alternatives((struct alt_entry *)__alt_start,
> > + (struct alt_entry *)__alt_end,
> > + RISCV_ALTERNATIVES_EARLY_BOOT);
> > +}
> > +
>
> The name is a bit confusing as there is another "apply_boot_alternatives"
> which was called earlier than "apply_early_boot_alternatives".
I'm not that much attached to early-boot, so if you have other naming-
suggestions we can of course change that.
As explained above, the early-boot stage runs before page-table setup,
so that things like the D1 can hook into it with their setting for the base
page-type.
Heiko
> > #ifdef CONFIG_MODULES
> > void apply_module_alternatives(void *start, size_t length)
> > {
> > diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> > index 7bce66ee7ce7..ecc248e5dab7 100644
> > --- a/arch/riscv/kernel/cpufeature.c
> > +++ b/arch/riscv/kernel/cpufeature.c
> > @@ -224,6 +224,8 @@ static bool cpufeature_svpbmt_check_func(unsigned int stage)
> >
> > #if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> > switch (stage) {
> > + case RISCV_ALTERNATIVES_EARLY_BOOT:
> > + return false;
> > case RISCV_ALTERNATIVES_BOOT:
> > return cpufeature_svpbmt_check_fdt();
> > default:
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index cf4d018b7d66..7216db5d6a2c 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -819,6 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> > BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K);
> > #endif
> >
> > + apply_early_boot_alternatives();
> > pt_ops_set_early();
> >
> > /* Setup early PGD for fixmap */
> > --
> > 2.30.2
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
>
>
>
> --
> Regards,
> Atish
>
On Thu, Feb 10, 2022 at 6:04 PM Heiko Stübner <[email protected]> wrote:
>
> Am Freitag, 11. Februar 2022, 02:48:38 CET schrieb Atish Patra:
> > On Thu, Feb 10, 2022 at 4:25 PM Atish Patra <[email protected]> wrote:
> > >
> > > On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
> > > >
> > > > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > > > for things like non-cacheable pages or I/O memory pages.
> > > >
> > > >
> > > > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > > > types) using the alternatives framework.
> > > >
> > > > This includes a number of changes to the alternatives mechanism itself.
> > > > The biggest one being the move to a more central location, as I expect
> > > > in the future, nearly every chip needing some sort of patching, be it
> > > > either for erratas or for optional features (svpbmt or others).
> > > >
> > > > The dt-binding for svpbmt itself is of course not finished and is still
> > > > using the binding introduced in previous versions, as where to put
> > > > a svpbmt-property in the devicetree is still under dicussion.
> > > > Atish seems to be working on a framework for extensions [0],
> > > >
> > >
> > > Here is the patch series
> > > https://lore.kernel.org/lkml/[email protected]/
> > >
> > > I think we can simplify the cpu feature probing in PATCH 10 with the
> > > above series
> > > which simply relies on the existing riscv_isa bitmap.
> > >
> > > We also don't need the separate svpbmt property in DT mmu node.
> > > Let me know what you think.
> > >
> > > > The series also introduces support for the memory types of the D1
> > > > which are implemented differently to svpbmt. But when patching anyway
> > > > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > > > location.
> > > >
> > > > The only slightly bigger difference is that the "normal" type is not 0
> > > > as with svpbmt, so kernel patches for this PMA type need to be applied
> > > > even before the MMU is brought up, so the series introduces a separate
> > > > stage for that.
> > > >
> > > >
> > > > In theory this series is 3 parts:
> > > > - sbi cache-flush / null-ptr
> > > > - alternatives improvements
> > > > - svpbmt+d1
> > > >
> > > > So expecially patches from the first 2 areas could be applied when
> > > > deemed ready, I just thought to keep it together to show-case where
> > > > the end-goal is and not requiring jumping between different series.
> > > >
> > > >
> > > > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > > > as it touches a similar area in mm/cacheflush.c
> > > >
> > > >
> > > > I picked the recipient list from the previous version, hopefully
> > > > I didn't forget anybody.
> > > >
> >
> > I am also getting a load access fault while booting this series in Qemu.
> >
> > <with additional debug message when before sbi_trap_redirect in OpenSBI>
> > sbi_trap_error_debug: hart1: trap handler failed (error -2)
> > sbi_trap_error_debug: hart1: mcause=0x0000000000000005 mtval=0x0000000080046468
> > sbi_trap_error_debug: hart1: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> > sbi_trap_error_debug: hart1: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> > sbi_trap_error_debug: hart1: ra=0x0000000080202b06 sp=0x0000000081203f00
> > sbi_trap_error_debug: hart1: gp=0x00000000812d9db8 tp=0x0000000080046000
> > sbi_trap_error_debug: hart1: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> > sbi_trap_error_debug: hart1: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> > sbi_trap_error_debug: hart1: a2=0x0000000000000002 a3=0x0000000000000000
> > sbi_trap_error_debug: hart1: a4=0x00000000812da902 a5=0x0000000000000000
> > sbi_trap_error_debug: hart1: a6=0x0000000000000006 a7=0x0000000000000010
> > sbi_trap_error_debug: hart1: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> > sbi_trap_error_debug: hart1: s4=0x00000000bf000000 s5=0x0000000000000000
> > sbi_trap_error_debug: hart1: s6=0x8000000a00006800 s7=0x000000000000007f
> > sbi_trap_error_debug: hart1: s8=0x0000000080018038 s9=0x0000000080039eac
> > sbi_trap_error_debug: hart1: s10=0x0000000000000000 s11=0x0000000000000000
> > sbi_trap_error_debug: hart1: t0=0x0000000080c04000 t1=0x0000000000000002
> > sbi_trap_error_debug: hart1: t2=0x0000000000001000 t3=0x0000000000000010
> > sbi_trap_error_debug: hart1: t4=0x00000000800168be t5=0x0000000000000027
> > sbi_trap_error_debug: hart1: t6=0x0000000000000001
> >
> > mepc : 0x000000008080a8b8 - call_function_init (kernel/smp.c)
> >
> > Kernel - 5.17-rc2 + my patches
> > Qemu - Alistairs next tree + my patches
>
> very strange. I was testing of course with Qemu as well, though never saw
> anything like this.
>
> But of course it was Qemu master + the then still pending svpbmt patchset [0]
> [looks like Alistair applied this today] + a patch that made qemu insert the
> svpbmt dt-property for the virt machine.
>
> Oh ... just to make sure, did you enable the svpbmt parameter when starting
> Qemu? (-cpu ...,svpbmt=true)
>
Yeah. I tried with or without. It's failing in both cases. I found a
fix but that may be unrelated and hiding the real issue.
Marking the cpufeature_svpbmt_check_of functions inline allows me to boot.
Here is my analysis:
Here is the trace of the trap:
sbi_trap_error_debug: hart0: trap handler failed (error -2)
sbi_trap_error_debug: hart0: mcause=0x0000000000000005 mtval=0x0000000080048468
sbi_trap_error_debug: hart0: mtval2=0x0000000000000000 mtinst=0x0000000000000000
sbi_trap_error_debug: hart0: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
sbi_trap_error_debug: hart0: ra=0x0000000080202b06 sp=0x0000000081203f00
sbi_trap_error_debug: hart0: gp=0x00000000812d9db8 tp=0x0000000080048000
sbi_trap_error_debug: hart0: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
sbi_trap_error_debug: hart0: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
sbi_trap_error_debug: hart0: a2=0x0000000000000002 a3=0x0000000000000000
sbi_trap_error_debug: hart0: a4=0x00000000812da902 a5=0x0000000000000000
sbi_trap_error_debug: hart0: a6=0x0000000000000006 a7=0x0000000000000010
sbi_trap_error_debug: hart0: s2=0x0000000080c1b0d0 s3=0x0000000000000002
sbi_trap_error_debug: hart0: s4=0x00000000bf000000 s5=0x0000000000000000
sbi_trap_error_debug: hart0: s6=0x8000000a00006800 s7=0x000000000000007f
sbi_trap_error_debug: hart0: s8=0x0000000080018038 s9=0x0000000080039ea8
sbi_trap_error_debug: hart0: s10=0x0000000000000000 s11=0x0000000000000000
sbi_trap_error_debug: hart0: t0=0x0000000080c04000 t1=0x0000000000000002
sbi_trap_error_debug: hart0: t2=0x0000000000001000 t3=0x0000000000000010
sbi_trap_error_debug: hart0: t4=0x00000000800168be t5=0x0000000000000027
sbi_trap_error_debug: hart0: t6=0x0000000000000001
mepc : 0x000000008080a8b8 - should be ffffffff8060a8b8 in objdump
output after offset
Here is the snippet of the objdump output for riscv_cpufeature_patch_func
========================================================================
inline output: (booting fails with above dump)
void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage)
{
ffffffff8060a89a: 7119 addi sp,sp,-128
ffffffff8060a89c: f8a2 sd s0,112(sp)
ffffffff8060a89e: f4a6 sd s1,104(sp)
ffffffff8060a8a0: f0ca sd s2,96(sp)
ffffffff8060a8a2: e4d6 sd s5,72(sp)
ffffffff8060a8a4: fc86 sd ra,120(sp)
ffffffff8060a8a6: ecce sd s3,88(sp)
ffffffff8060a8a8: e8d2 sd s4,80(sp)
ffffffff8060a8aa: e0da sd s6,64(sp)
ffffffff8060a8ac: fc5e sd s7,56(sp)
ffffffff8060a8ae: f862 sd s8,48(sp)
ffffffff8060a8b0: f466 sd s9,40(sp)
ffffffff8060a8b2: f06a sd s10,32(sp)
ffffffff8060a8b4: ec6e sd s11,24(sp)
ffffffff8060a8b6: 0100 addi s0,sp,128
ffffffff8060a8b8: 46823783 ld a5,1128(tp) #
468 <__efistub_.L0 +0x5> --------> Faulting instruction
ffffffff8060a8bc: f8f43423 sd a5,-120(s0)
ffffffff8060a8c0: 4781 li a5,0
ffffffff8060a8c2: 8932 mv s2,a2
ffffffff8060a8c4: 84aa mv s1,a0
ffffffff8060a8c6: 8aae mv s5,a1
switch (stage) {
ffffffff8060a8c8: ca1d beqz
a2,ffffffff8060a8fe <riscv_cpufeature_patch_func+0x64>
ffffffff8060a8ca: 4789 li a5,2
ffffffff8060a8cc: 18f60363 beq
a2,a5,ffffffff8060aa52 <riscv_cpufeature_patch_func+0x1b8>
for_each_of_cpu_node(node) {
ffffffff8060a8d0: 4501 li a0,0
========================================================================
noinline output (boots fine)
========================================================================
void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage)
{
ffffffff8060a968: 7159 addi sp,sp,-112
ffffffff8060a96a: f0a2 sd s0,96(sp)
ffffffff8060a96c: eca6 sd s1,88(sp)
ffffffff8060a96e: e8ca sd s2,80(sp)
ffffffff8060a970: fc56 sd s5,56(sp)
ffffffff8060a972: f486 sd ra,104(sp)
ffffffff8060a974: e4ce sd s3,72(sp)
ffffffff8060a976: e0d2 sd s4,64(sp)
ffffffff8060a978: f85a sd s6,48(sp)
ffffffff8060a97a: f45e sd s7,40(sp)
ffffffff8060a97c: f062 sd s8,32(sp)
ffffffff8060a97e: ec66 sd s9,24(sp)
ffffffff8060a980: e86a sd s10,16(sp)
ffffffff8060a982: e46e sd s11,8(sp)
ffffffff8060a984: 1880 addi s0,sp,112
ffffffff8060a986: 8932 mv s2,a2
ffffffff8060a988: 84aa mv s1,a0
ffffffff8060a98a: 8aae mv s5,a1
switch (stage) {
ffffffff8060a98c: ca09 beqz
a2,ffffffff8060a99e <riscv_cpufeature_patch_func+0x36>
ffffffff8060a98e: 4789 li a5,2
ffffffff8060a990: 0ef60f63 beq
a2,a5,ffffffff8060aa8e <riscv_cpufeature_patch_func+0x126>
return cpufeature_svpbmt_check_of();
ffffffff8060a994: f07ff0ef jal
ra,ffffffff8060a89a <cpufeature_svpbmt_check_of>
cpu_req_feature |= (1U << idx);
ffffffff8060a998: 0005091b sext.w s2,a0
ffffffff8060a99c: a8d5 j
ffffffff8060aa90 <riscv_cpufeature_patch_func+0x128>
const void *fdt = dtb_early_va;
Any thoughts ? It looks like it may related to "tp"
>
> Heiko
>
> [0] http://lore.kernel.org/r/[email protected]
>
>
> > I do have some out-of-tree patches but that shouldn't be an issue as I
> > am able to boot without your patches.
> > Commenting the *_boot_alternatives at both the places works fine as well.
> >
> > diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> > index 0e1bb97f9749..bdeb7ab3e719 100644
> > --- a/arch/riscv/kernel/head.S
> > +++ b/arch/riscv/kernel/head.S
> > @@ -342,7 +342,7 @@ clear_bss_done:
> > call kasan_early_init
> > #endif
> > /* Start the kernel */
> > - call apply_boot_alternatives
> > + //call apply_boot_alternatives
> > call soc_early_init
> > tail start_kernel
> >
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index 7216db5d6a2c..c6bf8f4d3d16 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -819,7 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> > BUG_ON((kernel_map.virt_addr + kernel_map.size) >
> > ADDRESS_SPACE_END - SZ_4K);
> > #endif
> >
> > - apply_early_boot_alternatives();
> > + //apply_early_boot_alternatives();
> > pt_ops_set_early();
> >
> > /* Setup early PGD for fixmap */
> >
> > I am currently debugging it and will let you know if I find the root cause.
> >
> > > > changes in v6:
> > > > - rebase onto 5.17-rc1
> > > > - handle sbi null-ptr differently
> > > > - improve commit messages
> > > > - use riscv,mmu as property name
> > > >
> > > > changes in v5:
> > > > - move to use alternatives for runtime-patching
> > > > - add D1 variant
> > > >
> > > >
> > > > [0] https://lore.kernel.org/r/[email protected]
> > > > [1] https://lore.kernel.org/r/[email protected]
> > > >
> > > >
> > > > Heiko Stuebner (12):
> > > > riscv: prevent null-pointer dereference with sbi_remote_fence_i
> > > > riscv: integrate alternatives better into the main architecture
> > > > riscv: allow different stages with alternatives
> > > > riscv: implement module alternatives
> > > > riscv: implement ALTERNATIVE_2 macro
> > > > riscv: extend concatenated alternatives-lines to the same length
> > > > riscv: prevent compressed instructions in alternatives
> > > > riscv: move boot alternatives to a slightly earlier position
> > > > riscv: Fix accessing pfn bits in PTEs for non-32bit variants
> > > > riscv: add cpufeature handling via alternatives
> > > > riscv: remove FIXMAP_PAGE_IO and fall back to its default value
> > > > riscv: add memory-type errata for T-Head
> > > >
> > > > Wei Fu (2):
> > > > dt-bindings: riscv: add MMU Standard Extensions support for Svpbmt
> > > > riscv: add RISC-V Svpbmt extension support
> > > >
> > > > .../devicetree/bindings/riscv/cpus.yaml | 10 ++
> > > > arch/riscv/Kconfig.erratas | 29 ++--
> > > > arch/riscv/Kconfig.socs | 1 -
> > > > arch/riscv/Makefile | 2 +-
> > > > arch/riscv/errata/Makefile | 2 +-
> > > > arch/riscv/errata/sifive/errata.c | 10 +-
> > > > arch/riscv/errata/thead/Makefile | 1 +
> > > > arch/riscv/errata/thead/errata.c | 85 +++++++++++
> > > > arch/riscv/include/asm/alternative-macros.h | 114 ++++++++-------
> > > > arch/riscv/include/asm/alternative.h | 16 ++-
> > > > arch/riscv/include/asm/errata_list.h | 52 +++++++
> > > > arch/riscv/include/asm/fixmap.h | 2 -
> > > > arch/riscv/include/asm/pgtable-32.h | 17 +++
> > > > arch/riscv/include/asm/pgtable-64.h | 79 +++++++++-
> > > > arch/riscv/include/asm/pgtable-bits.h | 10 --
> > > > arch/riscv/include/asm/pgtable.h | 53 +++++--
> > > > arch/riscv/include/asm/vendorid_list.h | 1 +
> > > > arch/riscv/kernel/Makefile | 1 +
> > > > arch/riscv/{errata => kernel}/alternative.c | 48 ++++++-
> > > > arch/riscv/kernel/cpufeature.c | 136 +++++++++++++++++-
> > > > arch/riscv/kernel/head.S | 2 +
> > > > arch/riscv/kernel/module.c | 29 ++++
> > > > arch/riscv/kernel/sbi.c | 10 +-
> > > > arch/riscv/kernel/smpboot.c | 4 -
> > > > arch/riscv/kernel/traps.c | 2 +-
> > > > arch/riscv/mm/init.c | 1 +
> > > > 26 files changed, 606 insertions(+), 111 deletions(-)
> > > > create mode 100644 arch/riscv/errata/thead/Makefile
> > > > create mode 100644 arch/riscv/errata/thead/errata.c
> > > > rename arch/riscv/{errata => kernel}/alternative.c (59%)
> > > >
> > > > --
> > > > 2.30.2
> > > >
> > > >
> > > > _______________________________________________
> > > > linux-riscv mailing list
> > > > [email protected]
> > > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> > >
> > >
> > >
> > > --
> > > Regards,
> > > Atish
> >
> >
> >
> >
>
>
>
>
--
Regards,
Atish
On Fri, Feb 11, 2022 at 1:25 AM Heiko Stübner <[email protected]> wrote:
>
> Hi Atish,
>
> Am Freitag, 11. Februar 2022, 01:12:55 CET schrieb Atish Patra:
> > On Wed, Feb 9, 2022 at 4:41 AM Heiko Stuebner <[email protected]> wrote:
> > >
> > > Some current cpus based on T-Head cores implement memory-types
> > > way different than described in the svpbmt spec even going
> > > so far as using PTE bits marked as reserved.
> > >
> > > Add the T-Head vendor-id and necessary errata code to
> > > replace the affected instructions.
> > >
> > > Signed-off-by: Heiko Stuebner <[email protected]>
> > > ---
> > > arch/riscv/Kconfig.erratas | 19 ++++++
> > > arch/riscv/errata/Makefile | 1 +
> > > arch/riscv/errata/sifive/errata.c | 7 ++-
> > > arch/riscv/errata/thead/Makefile | 1 +
> > > arch/riscv/errata/thead/errata.c | 85 ++++++++++++++++++++++++++
> > > arch/riscv/include/asm/alternative.h | 5 ++
> > > arch/riscv/include/asm/errata_list.h | 47 ++++++++++++--
> > > arch/riscv/include/asm/pgtable-64.h | 18 +++++-
> > > arch/riscv/include/asm/pgtable.h | 18 +++++-
> > > arch/riscv/include/asm/vendorid_list.h | 1 +
> > > arch/riscv/kernel/alternative.c | 14 +++++
> > > arch/riscv/kernel/cpufeature.c | 2 +
> > > arch/riscv/mm/init.c | 1 +
> > > 13 files changed, 210 insertions(+), 9 deletions(-)
> > > create mode 100644 arch/riscv/errata/thead/Makefile
> > > create mode 100644 arch/riscv/errata/thead/errata.c
> > >
> > > diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> > > index d18be8ff0245..380ec039c3dc 100644
> > > --- a/arch/riscv/Kconfig.erratas
> > > +++ b/arch/riscv/Kconfig.erratas
> > > @@ -31,4 +31,23 @@ config ERRATA_SIFIVE_CIP_1200
> > >
> > > If you don't know what to do here, say "Y".
> > >
> > > +config ERRATA_THEAD
> > > + bool "T-HEAD errata"
> > > + help
> > > + All T-HEAD errata Kconfig depend on this Kconfig. Disabling
> > > + this Kconfig will disable all T-HEAD errata. Please say "Y"
> > > + here if your platform uses T-HEAD CPU cores.
> > > +
> > > + If you don't know what to do here, say "Y".
> > > +
> > > +config ERRATA_THEAD_PBMT
> > > + bool "Apply T-Head memory type errata"
> > > + depends on ERRATA_THEAD && 64BIT
> > > + default y
> > > + help
> > > + This will apply the memory type errata to handle the non-standard
> > > + memory type bits in page-table-entries on T-Head SoCs.
> > > +
> > > + If you don't know what to do here, say "Y".
> > > +
> > > endmenu
> > > diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> > > index 0ca1c5281a2d..a1055965fbee 100644
> > > --- a/arch/riscv/errata/Makefile
> > > +++ b/arch/riscv/errata/Makefile
> > > @@ -1 +1,2 @@
> > > obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> > > +obj-$(CONFIG_ERRATA_THEAD) += thead/
> > > diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> > > index 4fe03ac41fd7..f933d6cdf304 100644
> > > --- a/arch/riscv/errata/sifive/errata.c
> > > +++ b/arch/riscv/errata/sifive/errata.c
> > > @@ -84,10 +84,15 @@ void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *
> > > unsigned int stage)
> > > {
> > > struct alt_entry *alt;
> > > - u32 cpu_req_errata = sifive_errata_probe(archid, impid);
> > > + u32 cpu_req_errata;
> > > u32 cpu_apply_errata = 0;
> > > u32 tmp;
> > >
> > > + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> > > + return;
> > > +
> > > + cpu_req_errata = sifive_errata_probe(archid, impid);
> > > +
> > > for (alt = begin; alt < end; alt++) {
> > > if (alt->vendor_id != SIFIVE_VENDOR_ID)
> > > continue;
> > > diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile
> > > new file mode 100644
> > > index 000000000000..2d644e19caef
> > > --- /dev/null
> > > +++ b/arch/riscv/errata/thead/Makefile
> > > @@ -0,0 +1 @@
> > > +obj-y += errata.o
> > > diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
> > > new file mode 100644
> > > index 000000000000..fd8e0538a3f0
> > > --- /dev/null
> > > +++ b/arch/riscv/errata/thead/errata.c
> > > @@ -0,0 +1,85 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * Copyright (C) 2021 Heiko Stuebner <[email protected]>
> > > + */
> > > +
> > > +#include <linux/bug.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/module.h>
> > > +#include <linux/string.h>
> > > +#include <linux/uaccess.h>
> > > +#include <asm/alternative.h>
> > > +#include <asm/cacheflush.h>
> > > +#include <asm/errata_list.h>
> > > +#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)
> > > +{
> > > + 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
> > > + },
> > > +};
> > > +
> > > +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);
> > > + }
> > > +
> > > + return cpu_req_errata;
> > > +}
> > > +
> > > +void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > + unsigned long archid, unsigned long impid,
> > > + unsigned int stage)
> > > +{
> > > + struct alt_entry *alt;
> > > + u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
> > > + u32 cpu_apply_errata = 0;
> > > + u32 tmp;
> > > +
> > > + for (alt = begin; alt < end; alt++) {
> > > + if (alt->vendor_id != THEAD_VENDOR_ID)
> > > + continue;
> > > + if (alt->errata_id >= ERRATA_THEAD_NUMBER)
> > > + continue;
> > > +
> > > + tmp = (1U << alt->errata_id);
> > > + if (cpu_req_errata & tmp) {
> > > + /* On vm-alternatives, the mmu isn't running yet */
> > > + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> > > + memcpy((void *)__pa_symbol(alt->old_ptr),
> > > + (void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
> > > + else
> > > + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> > > +
> > > + cpu_apply_errata |= tmp;
> > > + }
> > > + }
> > > +
> > > + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> > > + local_flush_icache_all();
> > > +}
> > > diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> > > index cf3b22173834..d1154c91ab03 100644
> > > --- a/arch/riscv/include/asm/alternative.h
> > > +++ b/arch/riscv/include/asm/alternative.h
> > > @@ -19,8 +19,10 @@
> > >
> > > #define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */
> > > #define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */
> > > +#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */
> > >
> >
> > But this stage invoked is used after RISCV_ALTERNATIVES_BOOT
>
> No it isn't.
>
> the "boot" alternative is applied right now directly before soc_early_init,
> while the "early-boot" alternative is already applied during setup_vm()
Yeah you are right. I got confused with the name and numbering.
> even before page-tables are set up.
>
> Right now the numbering doesn't reflect the order and just
> makes it distinct, but I guess we can adjust it to make that clear
> (move early_boot to the top)
>
>
> > > void __init apply_boot_alternatives(void);
> > > +void __init apply_early_boot_alternatives(void);
> > > void apply_module_alternatives(void *start, size_t length);
> > >
> > > struct alt_entry {
> > > @@ -39,6 +41,9 @@ struct errata_checkfunc_id {
> > > void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > unsigned long archid, unsigned long impid,
> > > unsigned int stage);
> > > +void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > + unsigned long archid, unsigned long impid,
> > > + unsigned int stage);
> > >
> > > void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > unsigned int stage);
> > > diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> > > index a4a9b0842922..4fac46b82c16 100644
> > > --- a/arch/riscv/include/asm/errata_list.h
> > > +++ b/arch/riscv/include/asm/errata_list.h
> > > @@ -14,6 +14,11 @@
> > > #define ERRATA_SIFIVE_NUMBER 2
> > > #endif
> > >
> > > +#ifdef CONFIG_ERRATA_THEAD
> > > +#define ERRATA_THEAD_PBMT 0
> > > +#define ERRATA_THEAD_NUMBER 1
> > > +#endif
> > > +
> > > #define CPUFEATURE_SVPBMT 0
> > > #define CPUFEATURE_NUMBER 1
> > >
> > > @@ -42,10 +47,44 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
> > > * in the default case.
> > > */
> > > #define ALT_SVPBMT_SHIFT 61
> > > -#define ALT_SVPBMT(_val, prot) \
> > > -asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,%2", 0, \
> > > - CPUFEATURE_SVPBMT, CONFIG_64BIT) \
> > > - : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), "I"(ALT_SVPBMT_SHIFT))
> > > +#define ALT_THEAD_PBMT_SHIFT 59
> > > +#define ALT_SVPBMT(_val, prot) \
> > > +asm(ALTERNATIVE_2("li %0, 0\t\nnop", \
> > > + "li %0, %1\t\nslli %0,%0,%3", 0, CPUFEATURE_SVPBMT, CONFIG_64BIT, \
> > > + "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, \
> > > + CONFIG_ERRATA_THEAD_PBMT) \
> > > + : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \
> > > + "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> > > + "I"(ALT_SVPBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> > > +
> > > +#ifdef CONFIG_ERRATA_THEAD_PBMT
> > > +/*
> > > + * IO/NOCACHE memory types are handled together with svpbmt,
> > > + * so on T-Head chips, check if no other memory type is set,
> > > + * and set the non-0 PMA type if applicable.
> > > + */
> > > +#define ALT_THEAD_PMA(_val) \
> > > +asm volatile(ALTERNATIVE( \
> > > + "nop\n\t" \
> > > + "nop\n\t" \
> > > + "nop\n\t" \
> > > + "nop\n\t" \
> > > + "nop\n\t" \
> > > + "nop\n\t" \
> > > + "nop", \
> > > + "li t3, %2\n\t" \
> > > + "slli t3, t3, %4\n\t" \
> > > + "and t3, %0, t3\n\t" \
> > > + "bne t3, zero, 2f\n\t" \
> > > + "li t3, %3\n\t" \
> > > + "slli t3, t3, %4\n\t" \
> > > + "or %0, %0, t3\n\t" \
> > > + "2:", THEAD_VENDOR_ID, ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
> > > + : "+r"(_val) : "0"(_val), "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \
> > > + "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), "I"(ALT_THEAD_PBMT_SHIFT))
> > > +#else
> > > +#define ALT_THEAD_PMA(_val)
> > > +#endif
> > >
> > > #endif /* __ASSEMBLY__ */
> > >
> > > diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> > > index 07ba3416cb19..6d59e4695200 100644
> > > --- a/arch/riscv/include/asm/pgtable-64.h
> > > +++ b/arch/riscv/include/asm/pgtable-64.h
> > > @@ -69,6 +69,18 @@ typedef struct {
> > > #define _PAGE_IO_SVPBMT (1UL << 62)
> > > #define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
> > >
> > > +/*
> > > + * [63:59] T-Head Memory Type definitions:
> > > + *
> > > + * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> > > + * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
> > > + * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
> > > + */
> > > +#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
> > > +#define _PAGE_NOCACHE_THEAD 0UL
> > > +#define _PAGE_IO_THEAD (1UL << 63)
> > > +#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
> > > +
> > > static inline u64 riscv_page_mtmask(void)
> > > {
> > > u64 val;
> > > @@ -167,7 +179,11 @@ static inline bool mm_pud_folded(struct mm_struct *mm)
> > >
> > > static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
> > > {
> > > - return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> > > + unsigned long prot_val = pgprot_val(prot);
> > > +
> > > + ALT_THEAD_PMA(prot_val);
> > > +
> > > + return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> > > }
> > >
> > > static inline unsigned long _pmd_pfn(pmd_t pmd)
> > > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > > index b8abc75dfe01..3d0c4c144093 100644
> > > --- a/arch/riscv/include/asm/pgtable.h
> > > +++ b/arch/riscv/include/asm/pgtable.h
> > > @@ -245,7 +245,11 @@ static inline void pmd_clear(pmd_t *pmdp)
> > >
> > > static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot)
> > > {
> > > - return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> > > + unsigned long prot_val = pgprot_val(prot);
> > > +
> > > + ALT_THEAD_PMA(prot_val);
> > > +
> > > + return __pgd((pfn << _PAGE_PFN_SHIFT) | prot_val);
> > > }
> > >
> > > static inline unsigned long _pgd_pfn(pgd_t pgd)
> > > @@ -284,7 +288,11 @@ static inline unsigned long pte_pfn(pte_t pte)
> > > /* Constructs a page table entry */
> > > static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
> > > {
> > > - return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
> > > + unsigned long prot_val = pgprot_val(prot);
> > > +
> > > + ALT_THEAD_PMA(prot_val);
> > > +
> > > + return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val);
> > > }
> > >
> > > #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
> > > @@ -393,7 +401,11 @@ static inline int pmd_protnone(pmd_t pmd)
> > > /* Modify page protection bits */
> > > static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> > > {
> > > - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
> > > + unsigned long newprot_val = pgprot_val(newprot);
> > > +
> > > + ALT_THEAD_PMA(newprot_val);
> > > +
> > > + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | newprot_val);
> > > }
> > >
> > > #define pgd_ERROR(e) \
> > > diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
> > > index 9d934215b3c8..cb89af3f0704 100644
> > > --- a/arch/riscv/include/asm/vendorid_list.h
> > > +++ b/arch/riscv/include/asm/vendorid_list.h
> > > @@ -6,5 +6,6 @@
> > > #define ASM_VENDOR_LIST_H
> > >
> > > #define SIFIVE_VENDOR_ID 0x489
> > > +#define THEAD_VENDOR_ID 0x5b7
> > >
> > > #endif
> > > diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> > > index e6c9de9f9ba6..3f6ad91f524c 100644
> > > --- a/arch/riscv/kernel/alternative.c
> > > +++ b/arch/riscv/kernel/alternative.c
> > > @@ -48,6 +48,11 @@ static void __init init_alternative(void)
> > > case SIFIVE_VENDOR_ID:
> > > vendor_patch_func = sifive_errata_patch_func;
> > > break;
> > > +#endif
> > > +#ifdef CONFIG_ERRATA_THEAD
> > > + case THEAD_VENDOR_ID:
> > > + vendor_patch_func = thead_errata_patch_func;
> > > + break;
> > > #endif
> > > default:
> > > vendor_patch_func = NULL;
> > > @@ -85,6 +90,15 @@ void __init apply_boot_alternatives(void)
> > > RISCV_ALTERNATIVES_BOOT);
> > > }
> > >
> > > +void __init apply_early_boot_alternatives(void)
> > > +{
> > > + init_alternative();
> > > +
> > > + _apply_alternatives((struct alt_entry *)__alt_start,
> > > + (struct alt_entry *)__alt_end,
> > > + RISCV_ALTERNATIVES_EARLY_BOOT);
> > > +}
> > > +
> >
> > The name is a bit confusing as there is another "apply_boot_alternatives"
> > which was called earlier than "apply_early_boot_alternatives".
>
> I'm not that much attached to early-boot, so if you have other naming-
> suggestions we can of course change that.
>
Just a suggestion:
how about BEFORE_MMU and AFTER_MMU to indicate the purpose more clearly.
But I am okay with the current naming scheme as well.
> As explained above, the early-boot stage runs before page-table setup,
> so that things like the D1 can hook into it with their setting for the base
> page-type.
>
>
> Heiko
>
>
>
> > > #ifdef CONFIG_MODULES
> > > void apply_module_alternatives(void *start, size_t length)
> > > {
> > > diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> > > index 7bce66ee7ce7..ecc248e5dab7 100644
> > > --- a/arch/riscv/kernel/cpufeature.c
> > > +++ b/arch/riscv/kernel/cpufeature.c
> > > @@ -224,6 +224,8 @@ static bool cpufeature_svpbmt_check_func(unsigned int stage)
> > >
> > > #if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> > > switch (stage) {
> > > + case RISCV_ALTERNATIVES_EARLY_BOOT:
> > > + return false;
> > > case RISCV_ALTERNATIVES_BOOT:
> > > return cpufeature_svpbmt_check_fdt();
> > > default:
> > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > > index cf4d018b7d66..7216db5d6a2c 100644
> > > --- a/arch/riscv/mm/init.c
> > > +++ b/arch/riscv/mm/init.c
> > > @@ -819,6 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> > > BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K);
> > > #endif
> > >
> > > + apply_early_boot_alternatives();
> > > pt_ops_set_early();
> > >
> > > /* Setup early PGD for fixmap */
> > > --
> > > 2.30.2
> > >
> > >
> > > _______________________________________________
> > > linux-riscv mailing list
> > > [email protected]
> > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> >
> >
> >
> > --
> > Regards,
> > Atish
> >
>
>
>
>
--
Regards,
Atish
On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
>
> The callback used inside sbi_remote_fence_i is set at sbi probe time
> to the needed variant. Before that it is a NULL pointer.
>
> Some users like the flush_icache_*() functions suggest a generic
> functionality, that doesn't depend on a specific boot-stage but
> uses sbi_remote_fence_i as one option to flush other cpu cores.
>
> So they definitly shouldn't run into null-pointer dereference
/s/definitly/definitely
> issues when called "too early" during boot.
>
> So introduce an empty function to be the standard for the __sbi_rfence
> function pointer until sbi_init has run.
>
> Users of sbi_remote_fence_i will have separate code for the local
> cpu and sbi_init() is called before other cpus are brought up.
> So there are no other cpus present at the time when the issue
> might happen.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/kernel/sbi.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> index f72527fcb347..c839acd668d3 100644
> --- a/arch/riscv/kernel/sbi.c
> +++ b/arch/riscv/kernel/sbi.c
> @@ -15,11 +15,19 @@
> unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
> EXPORT_SYMBOL(sbi_spec_version);
>
> +static int __sbi_rfence_none(int fid, const struct cpumask *cpu_mask,
> + unsigned long start, unsigned long size,
> + unsigned long arg4, unsigned long arg5)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
> static int (*__sbi_send_ipi)(const struct cpumask *cpu_mask) __ro_after_init;
> static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
> unsigned long start, unsigned long size,
> - unsigned long arg4, unsigned long arg5) __ro_after_init;
> + unsigned long arg4, unsigned long arg5)
> + __ro_after_init = __sbi_rfence_none;
>
> struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
> unsigned long arg1, unsigned long arg2,
> --
> 2.30.2
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Otherwise, LGTM.
Reviewed-by: Atish Patra <[email protected]>
--
Regards,
Atish
On 2/9/22 6:38 AM, Heiko Stuebner wrote:
> Some current cpus based on T-Head cores implement memory-types
> way different than described in the svpbmt spec even going
> so far as using PTE bits marked as reserved.
>
> Add the T-Head vendor-id and necessary errata code to
> replace the affected instructions.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
Tested-by: Samuel Holland <[email protected]>
Am Freitag, 11. Februar 2022, 02:48:38 CET schrieb Atish Patra:
> On Thu, Feb 10, 2022 at 4:25 PM Atish Patra <[email protected]> wrote:
> >
> > On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
> > >
> > > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > > for things like non-cacheable pages or I/O memory pages.
> > >
> > >
> > > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > > types) using the alternatives framework.
> > >
> > > This includes a number of changes to the alternatives mechanism itself.
> > > The biggest one being the move to a more central location, as I expect
> > > in the future, nearly every chip needing some sort of patching, be it
> > > either for erratas or for optional features (svpbmt or others).
> > >
> > > The dt-binding for svpbmt itself is of course not finished and is still
> > > using the binding introduced in previous versions, as where to put
> > > a svpbmt-property in the devicetree is still under dicussion.
> > > Atish seems to be working on a framework for extensions [0],
> > >
> >
> > Here is the patch series
> > https://lore.kernel.org/lkml/[email protected]/
> >
> > I think we can simplify the cpu feature probing in PATCH 10 with the
> > above series
> > which simply relies on the existing riscv_isa bitmap.
> >
> > We also don't need the separate svpbmt property in DT mmu node.
> > Let me know what you think.
> >
> > > The series also introduces support for the memory types of the D1
> > > which are implemented differently to svpbmt. But when patching anyway
> > > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > > location.
> > >
> > > The only slightly bigger difference is that the "normal" type is not 0
> > > as with svpbmt, so kernel patches for this PMA type need to be applied
> > > even before the MMU is brought up, so the series introduces a separate
> > > stage for that.
> > >
> > >
> > > In theory this series is 3 parts:
> > > - sbi cache-flush / null-ptr
> > > - alternatives improvements
> > > - svpbmt+d1
> > >
> > > So expecially patches from the first 2 areas could be applied when
> > > deemed ready, I just thought to keep it together to show-case where
> > > the end-goal is and not requiring jumping between different series.
> > >
> > >
> > > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > > as it touches a similar area in mm/cacheflush.c
> > >
> > >
> > > I picked the recipient list from the previous version, hopefully
> > > I didn't forget anybody.
> > >
>
> I am also getting a load access fault while booting this series in Qemu.
>
> <with additional debug message when before sbi_trap_redirect in OpenSBI>
> sbi_trap_error_debug: hart1: trap handler failed (error -2)
> sbi_trap_error_debug: hart1: mcause=0x0000000000000005 mtval=0x0000000080046468
> sbi_trap_error_debug: hart1: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> sbi_trap_error_debug: hart1: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> sbi_trap_error_debug: hart1: ra=0x0000000080202b06 sp=0x0000000081203f00
> sbi_trap_error_debug: hart1: gp=0x00000000812d9db8 tp=0x0000000080046000
> sbi_trap_error_debug: hart1: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> sbi_trap_error_debug: hart1: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> sbi_trap_error_debug: hart1: a2=0x0000000000000002 a3=0x0000000000000000
> sbi_trap_error_debug: hart1: a4=0x00000000812da902 a5=0x0000000000000000
> sbi_trap_error_debug: hart1: a6=0x0000000000000006 a7=0x0000000000000010
> sbi_trap_error_debug: hart1: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> sbi_trap_error_debug: hart1: s4=0x00000000bf000000 s5=0x0000000000000000
> sbi_trap_error_debug: hart1: s6=0x8000000a00006800 s7=0x000000000000007f
> sbi_trap_error_debug: hart1: s8=0x0000000080018038 s9=0x0000000080039eac
> sbi_trap_error_debug: hart1: s10=0x0000000000000000 s11=0x0000000000000000
> sbi_trap_error_debug: hart1: t0=0x0000000080c04000 t1=0x0000000000000002
> sbi_trap_error_debug: hart1: t2=0x0000000000001000 t3=0x0000000000000010
> sbi_trap_error_debug: hart1: t4=0x00000000800168be t5=0x0000000000000027
> sbi_trap_error_debug: hart1: t6=0x0000000000000001
>
> mepc : 0x000000008080a8b8 - call_function_init (kernel/smp.c)
>
> Kernel - 5.17-rc2 + my patches
> Qemu - Alistairs next tree + my patches
very strange. I was testing of course with Qemu as well, though never saw
anything like this.
But of course it was Qemu master + the then still pending svpbmt patchset [0]
[looks like Alistair applied this today] + a patch that made qemu insert the
svpbmt dt-property for the virt machine.
Oh ... just to make sure, did you enable the svpbmt parameter when starting
Qemu? (-cpu ...,svpbmt=true)
Heiko
[0] http://lore.kernel.org/r/[email protected]
> I do have some out-of-tree patches but that shouldn't be an issue as I
> am able to boot without your patches.
> Commenting the *_boot_alternatives at both the places works fine as well.
>
> diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> index 0e1bb97f9749..bdeb7ab3e719 100644
> --- a/arch/riscv/kernel/head.S
> +++ b/arch/riscv/kernel/head.S
> @@ -342,7 +342,7 @@ clear_bss_done:
> call kasan_early_init
> #endif
> /* Start the kernel */
> - call apply_boot_alternatives
> + //call apply_boot_alternatives
> call soc_early_init
> tail start_kernel
>
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index 7216db5d6a2c..c6bf8f4d3d16 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -819,7 +819,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> BUG_ON((kernel_map.virt_addr + kernel_map.size) >
> ADDRESS_SPACE_END - SZ_4K);
> #endif
>
> - apply_early_boot_alternatives();
> + //apply_early_boot_alternatives();
> pt_ops_set_early();
>
> /* Setup early PGD for fixmap */
>
> I am currently debugging it and will let you know if I find the root cause.
>
> > > changes in v6:
> > > - rebase onto 5.17-rc1
> > > - handle sbi null-ptr differently
> > > - improve commit messages
> > > - use riscv,mmu as property name
> > >
> > > changes in v5:
> > > - move to use alternatives for runtime-patching
> > > - add D1 variant
> > >
> > >
> > > [0] https://lore.kernel.org/r/[email protected]
> > > [1] https://lore.kernel.org/r/[email protected]
> > >
> > >
> > > Heiko Stuebner (12):
> > > riscv: prevent null-pointer dereference with sbi_remote_fence_i
> > > riscv: integrate alternatives better into the main architecture
> > > riscv: allow different stages with alternatives
> > > riscv: implement module alternatives
> > > riscv: implement ALTERNATIVE_2 macro
> > > riscv: extend concatenated alternatives-lines to the same length
> > > riscv: prevent compressed instructions in alternatives
> > > riscv: move boot alternatives to a slightly earlier position
> > > riscv: Fix accessing pfn bits in PTEs for non-32bit variants
> > > riscv: add cpufeature handling via alternatives
> > > riscv: remove FIXMAP_PAGE_IO and fall back to its default value
> > > riscv: add memory-type errata for T-Head
> > >
> > > Wei Fu (2):
> > > dt-bindings: riscv: add MMU Standard Extensions support for Svpbmt
> > > riscv: add RISC-V Svpbmt extension support
> > >
> > > .../devicetree/bindings/riscv/cpus.yaml | 10 ++
> > > arch/riscv/Kconfig.erratas | 29 ++--
> > > arch/riscv/Kconfig.socs | 1 -
> > > arch/riscv/Makefile | 2 +-
> > > arch/riscv/errata/Makefile | 2 +-
> > > arch/riscv/errata/sifive/errata.c | 10 +-
> > > arch/riscv/errata/thead/Makefile | 1 +
> > > arch/riscv/errata/thead/errata.c | 85 +++++++++++
> > > arch/riscv/include/asm/alternative-macros.h | 114 ++++++++-------
> > > arch/riscv/include/asm/alternative.h | 16 ++-
> > > arch/riscv/include/asm/errata_list.h | 52 +++++++
> > > arch/riscv/include/asm/fixmap.h | 2 -
> > > arch/riscv/include/asm/pgtable-32.h | 17 +++
> > > arch/riscv/include/asm/pgtable-64.h | 79 +++++++++-
> > > arch/riscv/include/asm/pgtable-bits.h | 10 --
> > > arch/riscv/include/asm/pgtable.h | 53 +++++--
> > > arch/riscv/include/asm/vendorid_list.h | 1 +
> > > arch/riscv/kernel/Makefile | 1 +
> > > arch/riscv/{errata => kernel}/alternative.c | 48 ++++++-
> > > arch/riscv/kernel/cpufeature.c | 136 +++++++++++++++++-
> > > arch/riscv/kernel/head.S | 2 +
> > > arch/riscv/kernel/module.c | 29 ++++
> > > arch/riscv/kernel/sbi.c | 10 +-
> > > arch/riscv/kernel/smpboot.c | 4 -
> > > arch/riscv/kernel/traps.c | 2 +-
> > > arch/riscv/mm/init.c | 1 +
> > > 26 files changed, 606 insertions(+), 111 deletions(-)
> > > create mode 100644 arch/riscv/errata/thead/Makefile
> > > create mode 100644 arch/riscv/errata/thead/errata.c
> > > rename arch/riscv/{errata => kernel}/alternative.c (59%)
> > >
> > > --
> > > 2.30.2
> > >
> > >
> > > _______________________________________________
> > > linux-riscv mailing list
> > > [email protected]
> > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> >
> >
> >
> > --
> > Regards,
> > Atish
>
>
>
>
On Mon, Feb 14, 2022 at 12:02 PM Heiko Stübner <[email protected]> wrote:
>
> Hi Atish,
>
> Am Samstag, 12. Februar 2022, 01:25:53 CET schrieb Atish Patra:
> > On Thu, Feb 10, 2022 at 6:04 PM Heiko Stübner <[email protected]> wrote:
> > >
> > > Am Freitag, 11. Februar 2022, 02:48:38 CET schrieb Atish Patra:
> > > > On Thu, Feb 10, 2022 at 4:25 PM Atish Patra <[email protected]> wrote:
> > > > >
> > > > > On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
> > > > > >
> > > > > > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > > > > > for things like non-cacheable pages or I/O memory pages.
> > > > > >
> > > > > >
> > > > > > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > > > > > types) using the alternatives framework.
> > > > > >
> > > > > > This includes a number of changes to the alternatives mechanism itself.
> > > > > > The biggest one being the move to a more central location, as I expect
> > > > > > in the future, nearly every chip needing some sort of patching, be it
> > > > > > either for erratas or for optional features (svpbmt or others).
> > > > > >
> > > > > > The dt-binding for svpbmt itself is of course not finished and is still
> > > > > > using the binding introduced in previous versions, as where to put
> > > > > > a svpbmt-property in the devicetree is still under dicussion.
> > > > > > Atish seems to be working on a framework for extensions [0],
> > > > > >
> > > > >
> > > > > Here is the patch series
> > > > > https://lore.kernel.org/lkml/[email protected]/
> > > > >
> > > > > I think we can simplify the cpu feature probing in PATCH 10 with the
> > > > > above series
> > > > > which simply relies on the existing riscv_isa bitmap.
> > > > >
> > > > > We also don't need the separate svpbmt property in DT mmu node.
> > > > > Let me know what you think.
> > > > >
> > > > > > The series also introduces support for the memory types of the D1
> > > > > > which are implemented differently to svpbmt. But when patching anyway
> > > > > > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > > > > > location.
> > > > > >
> > > > > > The only slightly bigger difference is that the "normal" type is not 0
> > > > > > as with svpbmt, so kernel patches for this PMA type need to be applied
> > > > > > even before the MMU is brought up, so the series introduces a separate
> > > > > > stage for that.
> > > > > >
> > > > > >
> > > > > > In theory this series is 3 parts:
> > > > > > - sbi cache-flush / null-ptr
> > > > > > - alternatives improvements
> > > > > > - svpbmt+d1
> > > > > >
> > > > > > So expecially patches from the first 2 areas could be applied when
> > > > > > deemed ready, I just thought to keep it together to show-case where
> > > > > > the end-goal is and not requiring jumping between different series.
> > > > > >
> > > > > >
> > > > > > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > > > > > as it touches a similar area in mm/cacheflush.c
> > > > > >
> > > > > >
> > > > > > I picked the recipient list from the previous version, hopefully
> > > > > > I didn't forget anybody.
> > > > > >
> > > >
> > > > I am also getting a load access fault while booting this series in Qemu.
> > > >
> > > > <with additional debug message when before sbi_trap_redirect in OpenSBI>
> > > > sbi_trap_error_debug: hart1: trap handler failed (error -2)
> > > > sbi_trap_error_debug: hart1: mcause=0x0000000000000005 mtval=0x0000000080046468
> > > > sbi_trap_error_debug: hart1: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> > > > sbi_trap_error_debug: hart1: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> > > > sbi_trap_error_debug: hart1: ra=0x0000000080202b06 sp=0x0000000081203f00
> > > > sbi_trap_error_debug: hart1: gp=0x00000000812d9db8 tp=0x0000000080046000
> > > > sbi_trap_error_debug: hart1: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> > > > sbi_trap_error_debug: hart1: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> > > > sbi_trap_error_debug: hart1: a2=0x0000000000000002 a3=0x0000000000000000
> > > > sbi_trap_error_debug: hart1: a4=0x00000000812da902 a5=0x0000000000000000
> > > > sbi_trap_error_debug: hart1: a6=0x0000000000000006 a7=0x0000000000000010
> > > > sbi_trap_error_debug: hart1: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> > > > sbi_trap_error_debug: hart1: s4=0x00000000bf000000 s5=0x0000000000000000
> > > > sbi_trap_error_debug: hart1: s6=0x8000000a00006800 s7=0x000000000000007f
> > > > sbi_trap_error_debug: hart1: s8=0x0000000080018038 s9=0x0000000080039eac
> > > > sbi_trap_error_debug: hart1: s10=0x0000000000000000 s11=0x0000000000000000
> > > > sbi_trap_error_debug: hart1: t0=0x0000000080c04000 t1=0x0000000000000002
> > > > sbi_trap_error_debug: hart1: t2=0x0000000000001000 t3=0x0000000000000010
> > > > sbi_trap_error_debug: hart1: t4=0x00000000800168be t5=0x0000000000000027
> > > > sbi_trap_error_debug: hart1: t6=0x0000000000000001
> > > >
> > > > mepc : 0x000000008080a8b8 - call_function_init (kernel/smp.c)
> > > >
> > > > Kernel - 5.17-rc2 + my patches
> > > > Qemu - Alistairs next tree + my patches
> > >
> > > very strange. I was testing of course with Qemu as well, though never saw
> > > anything like this.
> > >
> > > But of course it was Qemu master + the then still pending svpbmt patchset [0]
> > > [looks like Alistair applied this today] + a patch that made qemu insert the
> > > svpbmt dt-property for the virt machine.
> > >
> > > Oh ... just to make sure, did you enable the svpbmt parameter when starting
> > > Qemu? (-cpu ...,svpbmt=true)
> > >
> >
> > Yeah. I tried with or without. It's failing in both cases. I found a
> > fix but that may be unrelated and hiding the real issue.
> > Marking the cpufeature_svpbmt_check_of functions inline allows me to boot.
> >
> > Here is my analysis:
> >
> > Here is the trace of the trap:
> > sbi_trap_error_debug: hart0: trap handler failed (error -2)
> > sbi_trap_error_debug: hart0: mcause=0x0000000000000005 mtval=0x0000000080048468
> > sbi_trap_error_debug: hart0: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> > sbi_trap_error_debug: hart0: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> > sbi_trap_error_debug: hart0: ra=0x0000000080202b06 sp=0x0000000081203f00
> > sbi_trap_error_debug: hart0: gp=0x00000000812d9db8 tp=0x0000000080048000
> > sbi_trap_error_debug: hart0: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> > sbi_trap_error_debug: hart0: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> > sbi_trap_error_debug: hart0: a2=0x0000000000000002 a3=0x0000000000000000
> > sbi_trap_error_debug: hart0: a4=0x00000000812da902 a5=0x0000000000000000
> > sbi_trap_error_debug: hart0: a6=0x0000000000000006 a7=0x0000000000000010
> > sbi_trap_error_debug: hart0: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> > sbi_trap_error_debug: hart0: s4=0x00000000bf000000 s5=0x0000000000000000
> > sbi_trap_error_debug: hart0: s6=0x8000000a00006800 s7=0x000000000000007f
> > sbi_trap_error_debug: hart0: s8=0x0000000080018038 s9=0x0000000080039ea8
> > sbi_trap_error_debug: hart0: s10=0x0000000000000000 s11=0x0000000000000000
> > sbi_trap_error_debug: hart0: t0=0x0000000080c04000 t1=0x0000000000000002
> > sbi_trap_error_debug: hart0: t2=0x0000000000001000 t3=0x0000000000000010
> > sbi_trap_error_debug: hart0: t4=0x00000000800168be t5=0x0000000000000027
> > sbi_trap_error_debug: hart0: t6=0x0000000000000001
> >
> > mepc : 0x000000008080a8b8 - should be ffffffff8060a8b8 in objdump
> > output after offset
> >
> > Here is the snippet of the objdump output for riscv_cpufeature_patch_func
> >
> > ========================================================================
> > inline output: (booting fails with above dump)
> >
> > void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > unsigned int stage)
> > {
> > ffffffff8060a89a: 7119 addi sp,sp,-128
> > ffffffff8060a89c: f8a2 sd s0,112(sp)
> > ffffffff8060a89e: f4a6 sd s1,104(sp)
> > ffffffff8060a8a0: f0ca sd s2,96(sp)
> > ffffffff8060a8a2: e4d6 sd s5,72(sp)
> > ffffffff8060a8a4: fc86 sd ra,120(sp)
> > ffffffff8060a8a6: ecce sd s3,88(sp)
> > ffffffff8060a8a8: e8d2 sd s4,80(sp)
> > ffffffff8060a8aa: e0da sd s6,64(sp)
> > ffffffff8060a8ac: fc5e sd s7,56(sp)
> > ffffffff8060a8ae: f862 sd s8,48(sp)
> > ffffffff8060a8b0: f466 sd s9,40(sp)
> > ffffffff8060a8b2: f06a sd s10,32(sp)
> > ffffffff8060a8b4: ec6e sd s11,24(sp)
> > ffffffff8060a8b6: 0100 addi s0,sp,128
> > ffffffff8060a8b8: 46823783 ld a5,1128(tp) #
> > 468 <__efistub_.L0 +0x5> --------> Faulting instruction
> > ffffffff8060a8bc: f8f43423 sd a5,-120(s0)
> > ffffffff8060a8c0: 4781 li a5,0
> > ffffffff8060a8c2: 8932 mv s2,a2
> > ffffffff8060a8c4: 84aa mv s1,a0
> > ffffffff8060a8c6: 8aae mv s5,a1
> > switch (stage) {
> > ffffffff8060a8c8: ca1d beqz
> > a2,ffffffff8060a8fe <riscv_cpufeature_patch_func+0x64>
> > ffffffff8060a8ca: 4789 li a5,2
> > ffffffff8060a8cc: 18f60363 beq
> > a2,a5,ffffffff8060aa52 <riscv_cpufeature_patch_func+0x1b8>
> > for_each_of_cpu_node(node) {
> > ffffffff8060a8d0: 4501 li a0,0
> > ========================================================================
> >
> > noinline output (boots fine)
> > ========================================================================
> > void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > unsigned int stage)
> > {
> > ffffffff8060a968: 7159 addi sp,sp,-112
> > ffffffff8060a96a: f0a2 sd s0,96(sp)
> > ffffffff8060a96c: eca6 sd s1,88(sp)
> > ffffffff8060a96e: e8ca sd s2,80(sp)
> > ffffffff8060a970: fc56 sd s5,56(sp)
> > ffffffff8060a972: f486 sd ra,104(sp)
> > ffffffff8060a974: e4ce sd s3,72(sp)
> > ffffffff8060a976: e0d2 sd s4,64(sp)
> > ffffffff8060a978: f85a sd s6,48(sp)
> > ffffffff8060a97a: f45e sd s7,40(sp)
> > ffffffff8060a97c: f062 sd s8,32(sp)
> > ffffffff8060a97e: ec66 sd s9,24(sp)
> > ffffffff8060a980: e86a sd s10,16(sp)
> > ffffffff8060a982: e46e sd s11,8(sp)
> > ffffffff8060a984: 1880 addi s0,sp,112
> > ffffffff8060a986: 8932 mv s2,a2
> > ffffffff8060a988: 84aa mv s1,a0
> > ffffffff8060a98a: 8aae mv s5,a1
> > switch (stage) {
> > ffffffff8060a98c: ca09 beqz
> > a2,ffffffff8060a99e <riscv_cpufeature_patch_func+0x36>
> > ffffffff8060a98e: 4789 li a5,2
> > ffffffff8060a990: 0ef60f63 beq
> > a2,a5,ffffffff8060aa8e <riscv_cpufeature_patch_func+0x126>
> > return cpufeature_svpbmt_check_of();
> > ffffffff8060a994: f07ff0ef jal
> > ra,ffffffff8060a89a <cpufeature_svpbmt_check_of>
> > cpu_req_feature |= (1U << idx);
> > ffffffff8060a998: 0005091b sext.w s2,a0
> > ffffffff8060a99c: a8d5 j
> > ffffffff8060aa90 <riscv_cpufeature_patch_func+0x128>
> > const void *fdt = dtb_early_va;
> >
> >
> > Any thoughts ? It looks like it may related to "tp"
>
> Faulting instruction "efistub", so maybe something between efi
> and the devicetree not agreeing?
>
I don't think they are related as the execution has not reached the
device tree parsing yet.
It crashes before executing anything inside the DT parsing code.
__efistub_ is just a prefix to make sure that there are no absolute
relocations in .init section.
It is also enabled in defconfig. So you should see that error as well.
> Though at least on my build I also have efistub enabled, so it
> should be the same. So it's very strange that you're seeing that
> trap, which I've never seen so far.
>
Maybe GCC has to do something with it. Because adding "nolnine" solves
it for me.
I am using v11.1.0.
>
> In any case, I tried your + Tsukasa's patches regarding the isa-extensions
> today, and obviously that works fine, so we will get rid of the devicetree-
> parts anyway I guess.
>
I will try those changes and update the thread.
> With the change below on top of that v2/v3 version-mix, I also get a
> working svpbmt of course. After hacking qemu to generate a
> suitable isa-string for me :-) .
I will send a patch to Qemu to append the extension strings to the device tree.
>
>
> Heiko
>
> -------------- 8< ------------------
> diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
> index 691fc9c8099b..656cd626eb1a 100644
> --- a/arch/riscv/include/asm/hwcap.h
> +++ b/arch/riscv/include/asm/hwcap.h
> @@ -51,6 +51,7 @@ extern unsigned long elf_hwcap;
> * available logical extension id.
> */
> enum riscv_isa_ext_id {
> + RISCV_ISA_EXT_SVPBMT = RISCV_ISA_EXT_BASE,
> RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
> };
>
> diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
> index ced7e5be8641..b5130b15ca8d 100644
> --- a/arch/riscv/kernel/cpu.c
> +++ b/arch/riscv/kernel/cpu.c
> @@ -71,6 +71,7 @@ int riscv_of_parent_hartid(struct device_node *node)
> }
>
> static struct riscv_isa_ext_data isa_ext_arr[] = {
> + __RISCV_ISA_EXT_DATA("svpbmt", RISCV_ISA_EXT_SVPBMT),
> __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
> };
>
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 2e4eaedbf7f5..d82033ece1fd 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -192,6 +192,8 @@ void __init riscv_fill_hwcap(void)
> if (!ext_long) {
> this_hwcap |= isa2hwcap[(unsigned char)(*ext)];
> this_isa |= (1UL << (*ext - 'a'));
> + } else {
> + SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
> }
> #undef SET_ISA_EXT_MAP
> }
> @@ -253,64 +255,6 @@ struct cpufeature_info {
> bool (*check_func)(unsigned int stage);
> };
>
> -#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> -static bool __init_or_module cpufeature_svpbmt_check_fdt(void)
> -{
> - const void *fdt = dtb_early_va;
> - const char *str;
> - int offset;
> -
> - offset = fdt_path_offset(fdt, "/cpus");
> - if (offset < 0)
> - return false;
> -
> - for (offset = fdt_next_node(fdt, offset, NULL); offset >= 0;
> - offset = fdt_next_node(fdt, offset, NULL)) {
> - str = fdt_getprop(fdt, offset, "device_type", NULL);
> - if (!str || strcmp(str, "cpu"))
> - break;
> -
> - str = fdt_getprop(fdt, offset, "mmu-type", NULL);
> - if (!str)
> - continue;
> -
> - if (!strncmp(str + 6, "none", 4))
> - continue;
> -
> - str = fdt_getprop(fdt, offset, "riscv,mmu", NULL);
> - if (!str)
> - continue;
> -
> - if (!strncmp(str + 6, "svpbmt", 6))
> - return true;
> - }
> -
> - return false;
> -}
> -
> -static bool __init_or_module cpufeature_svpbmt_check_of(void)
> -{
> - struct device_node *node;
> - const char *str;
> -
> - for_each_of_cpu_node(node) {
> - if (of_property_read_string(node, "mmu-type", &str))
> - continue;
> -
> - if (!strncmp(str + 6, "none", 4))
> - continue;
> -
> - if (of_property_read_string(node, "riscv,mmu", &str))
> - continue;
> -
> - if (!strncmp(str + 6, "svpbmt", 6))
> - return true;
> - }
> -
> - return false;
> -}
> -#endif
> -
> static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
> {
> bool ret = false;
> @@ -319,10 +263,8 @@ static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
> switch (stage) {
> case RISCV_ALTERNATIVES_EARLY_BOOT:
> return false;
> - case RISCV_ALTERNATIVES_BOOT:
> - return cpufeature_svpbmt_check_fdt();
> default:
> - return cpufeature_svpbmt_check_of();
> + return riscv_isa_extension_available(NULL, SVPBMT);
> }
> #endif
>
> diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> index c01012f3740d..ec07f991866a 100644
> --- a/arch/riscv/kernel/head.S
> +++ b/arch/riscv/kernel/head.S
> @@ -10,7 +10,6 @@
> #include <asm/thread_info.h>
> #include <asm/page.h>
> #include <asm/pgtable.h>
> -#include <asm/alternative.h>
> #include <asm/csr.h>
> #include <asm/cpu_ops_sbi.h>
> #include <asm/hwcap.h>
> @@ -341,7 +340,6 @@ clear_bss_done:
> call kasan_early_init
> #endif
> /* Start the kernel */
> - call apply_boot_alternatives
> call soc_early_init
> tail start_kernel
>
> diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
> index 339ceb595b38..b4879c942b42 100644
> --- a/arch/riscv/kernel/setup.c
> +++ b/arch/riscv/kernel/setup.c
> @@ -21,6 +21,7 @@
> #include <linux/efi.h>
> #include <linux/crash_dump.h>
>
> +#include <asm/alternative.h>
> #include <asm/cpu_ops.h>
> #include <asm/early_ioremap.h>
> #include <asm/pgtable.h>
> @@ -295,6 +296,7 @@ void __init setup_arch(char **cmdline_p)
> #endif
>
> riscv_fill_hwcap();
> + apply_boot_alternatives();
> }
>
> static int __init topology_init(void)
>
>
>
Looks good to me.
--
Regards,
Atish
Am Montag, 14. Februar 2022, 21:25:06 CET schrieb Atish Patra:
> On Mon, Feb 14, 2022 at 12:02 PM Heiko St?bner <[email protected]> wrote:
> >
> > Hi Atish,
> >
> > Am Samstag, 12. Februar 2022, 01:25:53 CET schrieb Atish Patra:
> > > On Thu, Feb 10, 2022 at 6:04 PM Heiko St?bner <[email protected]> wrote:
> > > >
> > > > Am Freitag, 11. Februar 2022, 02:48:38 CET schrieb Atish Patra:
> > > > > On Thu, Feb 10, 2022 at 4:25 PM Atish Patra <[email protected]> wrote:
> > > > > >
> > > > > > On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
> > > > > > >
> > > > > > > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > > > > > > for things like non-cacheable pages or I/O memory pages.
> > > > > > >
> > > > > > >
> > > > > > > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > > > > > > types) using the alternatives framework.
> > > > > > >
> > > > > > > This includes a number of changes to the alternatives mechanism itself.
> > > > > > > The biggest one being the move to a more central location, as I expect
> > > > > > > in the future, nearly every chip needing some sort of patching, be it
> > > > > > > either for erratas or for optional features (svpbmt or others).
> > > > > > >
> > > > > > > The dt-binding for svpbmt itself is of course not finished and is still
> > > > > > > using the binding introduced in previous versions, as where to put
> > > > > > > a svpbmt-property in the devicetree is still under dicussion.
> > > > > > > Atish seems to be working on a framework for extensions [0],
> > > > > > >
> > > > > >
> > > > > > Here is the patch series
> > > > > > https://lore.kernel.org/lkml/[email protected]/
> > > > > >
> > > > > > I think we can simplify the cpu feature probing in PATCH 10 with the
> > > > > > above series
> > > > > > which simply relies on the existing riscv_isa bitmap.
> > > > > >
> > > > > > We also don't need the separate svpbmt property in DT mmu node.
> > > > > > Let me know what you think.
> > > > > >
> > > > > > > The series also introduces support for the memory types of the D1
> > > > > > > which are implemented differently to svpbmt. But when patching anyway
> > > > > > > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > > > > > > location.
> > > > > > >
> > > > > > > The only slightly bigger difference is that the "normal" type is not 0
> > > > > > > as with svpbmt, so kernel patches for this PMA type need to be applied
> > > > > > > even before the MMU is brought up, so the series introduces a separate
> > > > > > > stage for that.
> > > > > > >
> > > > > > >
> > > > > > > In theory this series is 3 parts:
> > > > > > > - sbi cache-flush / null-ptr
> > > > > > > - alternatives improvements
> > > > > > > - svpbmt+d1
> > > > > > >
> > > > > > > So expecially patches from the first 2 areas could be applied when
> > > > > > > deemed ready, I just thought to keep it together to show-case where
> > > > > > > the end-goal is and not requiring jumping between different series.
> > > > > > >
> > > > > > >
> > > > > > > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > > > > > > as it touches a similar area in mm/cacheflush.c
> > > > > > >
> > > > > > >
> > > > > > > I picked the recipient list from the previous version, hopefully
> > > > > > > I didn't forget anybody.
> > > > > > >
> > > > >
> > > > > I am also getting a load access fault while booting this series in Qemu.
> > > > >
> > > > > <with additional debug message when before sbi_trap_redirect in OpenSBI>
> > > > > sbi_trap_error_debug: hart1: trap handler failed (error -2)
> > > > > sbi_trap_error_debug: hart1: mcause=0x0000000000000005 mtval=0x0000000080046468
> > > > > sbi_trap_error_debug: hart1: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> > > > > sbi_trap_error_debug: hart1: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> > > > > sbi_trap_error_debug: hart1: ra=0x0000000080202b06 sp=0x0000000081203f00
> > > > > sbi_trap_error_debug: hart1: gp=0x00000000812d9db8 tp=0x0000000080046000
> > > > > sbi_trap_error_debug: hart1: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> > > > > sbi_trap_error_debug: hart1: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> > > > > sbi_trap_error_debug: hart1: a2=0x0000000000000002 a3=0x0000000000000000
> > > > > sbi_trap_error_debug: hart1: a4=0x00000000812da902 a5=0x0000000000000000
> > > > > sbi_trap_error_debug: hart1: a6=0x0000000000000006 a7=0x0000000000000010
> > > > > sbi_trap_error_debug: hart1: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> > > > > sbi_trap_error_debug: hart1: s4=0x00000000bf000000 s5=0x0000000000000000
> > > > > sbi_trap_error_debug: hart1: s6=0x8000000a00006800 s7=0x000000000000007f
> > > > > sbi_trap_error_debug: hart1: s8=0x0000000080018038 s9=0x0000000080039eac
> > > > > sbi_trap_error_debug: hart1: s10=0x0000000000000000 s11=0x0000000000000000
> > > > > sbi_trap_error_debug: hart1: t0=0x0000000080c04000 t1=0x0000000000000002
> > > > > sbi_trap_error_debug: hart1: t2=0x0000000000001000 t3=0x0000000000000010
> > > > > sbi_trap_error_debug: hart1: t4=0x00000000800168be t5=0x0000000000000027
> > > > > sbi_trap_error_debug: hart1: t6=0x0000000000000001
> > > > >
> > > > > mepc : 0x000000008080a8b8 - call_function_init (kernel/smp.c)
> > > > >
> > > > > Kernel - 5.17-rc2 + my patches
> > > > > Qemu - Alistairs next tree + my patches
> > > >
> > > > very strange. I was testing of course with Qemu as well, though never saw
> > > > anything like this.
> > > >
> > > > But of course it was Qemu master + the then still pending svpbmt patchset [0]
> > > > [looks like Alistair applied this today] + a patch that made qemu insert the
> > > > svpbmt dt-property for the virt machine.
> > > >
> > > > Oh ... just to make sure, did you enable the svpbmt parameter when starting
> > > > Qemu? (-cpu ...,svpbmt=true)
> > > >
> > >
> > > Yeah. I tried with or without. It's failing in both cases. I found a
> > > fix but that may be unrelated and hiding the real issue.
> > > Marking the cpufeature_svpbmt_check_of functions inline allows me to boot.
> > >
> > > Here is my analysis:
> > >
> > > Here is the trace of the trap:
> > > sbi_trap_error_debug: hart0: trap handler failed (error -2)
> > > sbi_trap_error_debug: hart0: mcause=0x0000000000000005 mtval=0x0000000080048468
> > > sbi_trap_error_debug: hart0: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> > > sbi_trap_error_debug: hart0: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> > > sbi_trap_error_debug: hart0: ra=0x0000000080202b06 sp=0x0000000081203f00
> > > sbi_trap_error_debug: hart0: gp=0x00000000812d9db8 tp=0x0000000080048000
> > > sbi_trap_error_debug: hart0: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> > > sbi_trap_error_debug: hart0: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> > > sbi_trap_error_debug: hart0: a2=0x0000000000000002 a3=0x0000000000000000
> > > sbi_trap_error_debug: hart0: a4=0x00000000812da902 a5=0x0000000000000000
> > > sbi_trap_error_debug: hart0: a6=0x0000000000000006 a7=0x0000000000000010
> > > sbi_trap_error_debug: hart0: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> > > sbi_trap_error_debug: hart0: s4=0x00000000bf000000 s5=0x0000000000000000
> > > sbi_trap_error_debug: hart0: s6=0x8000000a00006800 s7=0x000000000000007f
> > > sbi_trap_error_debug: hart0: s8=0x0000000080018038 s9=0x0000000080039ea8
> > > sbi_trap_error_debug: hart0: s10=0x0000000000000000 s11=0x0000000000000000
> > > sbi_trap_error_debug: hart0: t0=0x0000000080c04000 t1=0x0000000000000002
> > > sbi_trap_error_debug: hart0: t2=0x0000000000001000 t3=0x0000000000000010
> > > sbi_trap_error_debug: hart0: t4=0x00000000800168be t5=0x0000000000000027
> > > sbi_trap_error_debug: hart0: t6=0x0000000000000001
> > >
> > > mepc : 0x000000008080a8b8 - should be ffffffff8060a8b8 in objdump
> > > output after offset
> > >
> > > Here is the snippet of the objdump output for riscv_cpufeature_patch_func
> > >
> > > ========================================================================
> > > inline output: (booting fails with above dump)
> > >
> > > void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > unsigned int stage)
> > > {
> > > ffffffff8060a89a: 7119 addi sp,sp,-128
> > > ffffffff8060a89c: f8a2 sd s0,112(sp)
> > > ffffffff8060a89e: f4a6 sd s1,104(sp)
> > > ffffffff8060a8a0: f0ca sd s2,96(sp)
> > > ffffffff8060a8a2: e4d6 sd s5,72(sp)
> > > ffffffff8060a8a4: fc86 sd ra,120(sp)
> > > ffffffff8060a8a6: ecce sd s3,88(sp)
> > > ffffffff8060a8a8: e8d2 sd s4,80(sp)
> > > ffffffff8060a8aa: e0da sd s6,64(sp)
> > > ffffffff8060a8ac: fc5e sd s7,56(sp)
> > > ffffffff8060a8ae: f862 sd s8,48(sp)
> > > ffffffff8060a8b0: f466 sd s9,40(sp)
> > > ffffffff8060a8b2: f06a sd s10,32(sp)
> > > ffffffff8060a8b4: ec6e sd s11,24(sp)
> > > ffffffff8060a8b6: 0100 addi s0,sp,128
> > > ffffffff8060a8b8: 46823783 ld a5,1128(tp) #
> > > 468 <__efistub_.L0 +0x5> --------> Faulting instruction
> > > ffffffff8060a8bc: f8f43423 sd a5,-120(s0)
> > > ffffffff8060a8c0: 4781 li a5,0
> > > ffffffff8060a8c2: 8932 mv s2,a2
> > > ffffffff8060a8c4: 84aa mv s1,a0
> > > ffffffff8060a8c6: 8aae mv s5,a1
> > > switch (stage) {
> > > ffffffff8060a8c8: ca1d beqz
> > > a2,ffffffff8060a8fe <riscv_cpufeature_patch_func+0x64>
> > > ffffffff8060a8ca: 4789 li a5,2
> > > ffffffff8060a8cc: 18f60363 beq
> > > a2,a5,ffffffff8060aa52 <riscv_cpufeature_patch_func+0x1b8>
> > > for_each_of_cpu_node(node) {
> > > ffffffff8060a8d0: 4501 li a0,0
> > > ========================================================================
> > >
> > > noinline output (boots fine)
> > > ========================================================================
> > > void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> > > unsigned int stage)
> > > {
> > > ffffffff8060a968: 7159 addi sp,sp,-112
> > > ffffffff8060a96a: f0a2 sd s0,96(sp)
> > > ffffffff8060a96c: eca6 sd s1,88(sp)
> > > ffffffff8060a96e: e8ca sd s2,80(sp)
> > > ffffffff8060a970: fc56 sd s5,56(sp)
> > > ffffffff8060a972: f486 sd ra,104(sp)
> > > ffffffff8060a974: e4ce sd s3,72(sp)
> > > ffffffff8060a976: e0d2 sd s4,64(sp)
> > > ffffffff8060a978: f85a sd s6,48(sp)
> > > ffffffff8060a97a: f45e sd s7,40(sp)
> > > ffffffff8060a97c: f062 sd s8,32(sp)
> > > ffffffff8060a97e: ec66 sd s9,24(sp)
> > > ffffffff8060a980: e86a sd s10,16(sp)
> > > ffffffff8060a982: e46e sd s11,8(sp)
> > > ffffffff8060a984: 1880 addi s0,sp,112
> > > ffffffff8060a986: 8932 mv s2,a2
> > > ffffffff8060a988: 84aa mv s1,a0
> > > ffffffff8060a98a: 8aae mv s5,a1
> > > switch (stage) {
> > > ffffffff8060a98c: ca09 beqz
> > > a2,ffffffff8060a99e <riscv_cpufeature_patch_func+0x36>
> > > ffffffff8060a98e: 4789 li a5,2
> > > ffffffff8060a990: 0ef60f63 beq
> > > a2,a5,ffffffff8060aa8e <riscv_cpufeature_patch_func+0x126>
> > > return cpufeature_svpbmt_check_of();
> > > ffffffff8060a994: f07ff0ef jal
> > > ra,ffffffff8060a89a <cpufeature_svpbmt_check_of>
> > > cpu_req_feature |= (1U << idx);
> > > ffffffff8060a998: 0005091b sext.w s2,a0
> > > ffffffff8060a99c: a8d5 j
> > > ffffffff8060aa90 <riscv_cpufeature_patch_func+0x128>
> > > const void *fdt = dtb_early_va;
> > >
> > >
> > > Any thoughts ? It looks like it may related to "tp"
> >
> > Faulting instruction "efistub", so maybe something between efi
> > and the devicetree not agreeing?
> >
>
> I don't think they are related as the execution has not reached the
> device tree parsing yet.
> It crashes before executing anything inside the DT parsing code.
>
> __efistub_ is just a prefix to make sure that there are no absolute
> relocations in .init section.
> It is also enabled in defconfig. So you should see that error as well.
>
> > Though at least on my build I also have efistub enabled, so it
> > should be the same. So it's very strange that you're seeing that
> > trap, which I've never seen so far.
> >
>
> Maybe GCC has to do something with it. Because adding "nolnine" solves
> it for me.
> I am using v11.1.0.
I'm currently with 10.2.1 .. so that really might be an issue.
I tried gcc-11 from Debian last week, but that didn't even seem
to build working stock images, so I've reverted back to 10 for the
time being.
> > In any case, I tried your + Tsukasa's patches regarding the isa-extensions
> > today, and obviously that works fine, so we will get rid of the devicetree-
> > parts anyway I guess.
> >
>
> I will try those changes and update the thread.
>
> > With the change below on top of that v2/v3 version-mix, I also get a
> > working svpbmt of course. After hacking qemu to generate a
> > suitable isa-string for me :-) .
>
> I will send a patch to Qemu to append the extension strings to the device tree.
thanks a lot :-)
Heiko
> > -------------- 8< ------------------
> > diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
> > index 691fc9c8099b..656cd626eb1a 100644
> > --- a/arch/riscv/include/asm/hwcap.h
> > +++ b/arch/riscv/include/asm/hwcap.h
> > @@ -51,6 +51,7 @@ extern unsigned long elf_hwcap;
> > * available logical extension id.
> > */
> > enum riscv_isa_ext_id {
> > + RISCV_ISA_EXT_SVPBMT = RISCV_ISA_EXT_BASE,
> > RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
> > };
> >
> > diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
> > index ced7e5be8641..b5130b15ca8d 100644
> > --- a/arch/riscv/kernel/cpu.c
> > +++ b/arch/riscv/kernel/cpu.c
> > @@ -71,6 +71,7 @@ int riscv_of_parent_hartid(struct device_node *node)
> > }
> >
> > static struct riscv_isa_ext_data isa_ext_arr[] = {
> > + __RISCV_ISA_EXT_DATA("svpbmt", RISCV_ISA_EXT_SVPBMT),
> > __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
> > };
> >
> > diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> > index 2e4eaedbf7f5..d82033ece1fd 100644
> > --- a/arch/riscv/kernel/cpufeature.c
> > +++ b/arch/riscv/kernel/cpufeature.c
> > @@ -192,6 +192,8 @@ void __init riscv_fill_hwcap(void)
> > if (!ext_long) {
> > this_hwcap |= isa2hwcap[(unsigned char)(*ext)];
> > this_isa |= (1UL << (*ext - 'a'));
> > + } else {
> > + SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
> > }
> > #undef SET_ISA_EXT_MAP
> > }
> > @@ -253,64 +255,6 @@ struct cpufeature_info {
> > bool (*check_func)(unsigned int stage);
> > };
> >
> > -#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> > -static bool __init_or_module cpufeature_svpbmt_check_fdt(void)
> > -{
> > - const void *fdt = dtb_early_va;
> > - const char *str;
> > - int offset;
> > -
> > - offset = fdt_path_offset(fdt, "/cpus");
> > - if (offset < 0)
> > - return false;
> > -
> > - for (offset = fdt_next_node(fdt, offset, NULL); offset >= 0;
> > - offset = fdt_next_node(fdt, offset, NULL)) {
> > - str = fdt_getprop(fdt, offset, "device_type", NULL);
> > - if (!str || strcmp(str, "cpu"))
> > - break;
> > -
> > - str = fdt_getprop(fdt, offset, "mmu-type", NULL);
> > - if (!str)
> > - continue;
> > -
> > - if (!strncmp(str + 6, "none", 4))
> > - continue;
> > -
> > - str = fdt_getprop(fdt, offset, "riscv,mmu", NULL);
> > - if (!str)
> > - continue;
> > -
> > - if (!strncmp(str + 6, "svpbmt", 6))
> > - return true;
> > - }
> > -
> > - return false;
> > -}
> > -
> > -static bool __init_or_module cpufeature_svpbmt_check_of(void)
> > -{
> > - struct device_node *node;
> > - const char *str;
> > -
> > - for_each_of_cpu_node(node) {
> > - if (of_property_read_string(node, "mmu-type", &str))
> > - continue;
> > -
> > - if (!strncmp(str + 6, "none", 4))
> > - continue;
> > -
> > - if (of_property_read_string(node, "riscv,mmu", &str))
> > - continue;
> > -
> > - if (!strncmp(str + 6, "svpbmt", 6))
> > - return true;
> > - }
> > -
> > - return false;
> > -}
> > -#endif
> > -
> > static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
> > {
> > bool ret = false;
> > @@ -319,10 +263,8 @@ static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
> > switch (stage) {
> > case RISCV_ALTERNATIVES_EARLY_BOOT:
> > return false;
> > - case RISCV_ALTERNATIVES_BOOT:
> > - return cpufeature_svpbmt_check_fdt();
> > default:
> > - return cpufeature_svpbmt_check_of();
> > + return riscv_isa_extension_available(NULL, SVPBMT);
> > }
> > #endif
> >
> > diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> > index c01012f3740d..ec07f991866a 100644
> > --- a/arch/riscv/kernel/head.S
> > +++ b/arch/riscv/kernel/head.S
> > @@ -10,7 +10,6 @@
> > #include <asm/thread_info.h>
> > #include <asm/page.h>
> > #include <asm/pgtable.h>
> > -#include <asm/alternative.h>
> > #include <asm/csr.h>
> > #include <asm/cpu_ops_sbi.h>
> > #include <asm/hwcap.h>
> > @@ -341,7 +340,6 @@ clear_bss_done:
> > call kasan_early_init
> > #endif
> > /* Start the kernel */
> > - call apply_boot_alternatives
> > call soc_early_init
> > tail start_kernel
> >
> > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
> > index 339ceb595b38..b4879c942b42 100644
> > --- a/arch/riscv/kernel/setup.c
> > +++ b/arch/riscv/kernel/setup.c
> > @@ -21,6 +21,7 @@
> > #include <linux/efi.h>
> > #include <linux/crash_dump.h>
> >
> > +#include <asm/alternative.h>
> > #include <asm/cpu_ops.h>
> > #include <asm/early_ioremap.h>
> > #include <asm/pgtable.h>
> > @@ -295,6 +296,7 @@ void __init setup_arch(char **cmdline_p)
> > #endif
> >
> > riscv_fill_hwcap();
> > + apply_boot_alternatives();
> > }
> >
> > static int __init topology_init(void)
> >
> >
> >
>
> Looks good to me.
>
>
Hi Atish,
Am Samstag, 12. Februar 2022, 01:25:53 CET schrieb Atish Patra:
> On Thu, Feb 10, 2022 at 6:04 PM Heiko St?bner <[email protected]> wrote:
> >
> > Am Freitag, 11. Februar 2022, 02:48:38 CET schrieb Atish Patra:
> > > On Thu, Feb 10, 2022 at 4:25 PM Atish Patra <[email protected]> wrote:
> > > >
> > > > On Wed, Feb 9, 2022 at 4:38 AM Heiko Stuebner <[email protected]> wrote:
> > > > >
> > > > > Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> > > > > for things like non-cacheable pages or I/O memory pages.
> > > > >
> > > > >
> > > > > So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> > > > > types) using the alternatives framework.
> > > > >
> > > > > This includes a number of changes to the alternatives mechanism itself.
> > > > > The biggest one being the move to a more central location, as I expect
> > > > > in the future, nearly every chip needing some sort of patching, be it
> > > > > either for erratas or for optional features (svpbmt or others).
> > > > >
> > > > > The dt-binding for svpbmt itself is of course not finished and is still
> > > > > using the binding introduced in previous versions, as where to put
> > > > > a svpbmt-property in the devicetree is still under dicussion.
> > > > > Atish seems to be working on a framework for extensions [0],
> > > > >
> > > >
> > > > Here is the patch series
> > > > https://lore.kernel.org/lkml/[email protected]/
> > > >
> > > > I think we can simplify the cpu feature probing in PATCH 10 with the
> > > > above series
> > > > which simply relies on the existing riscv_isa bitmap.
> > > >
> > > > We also don't need the separate svpbmt property in DT mmu node.
> > > > Let me know what you think.
> > > >
> > > > > The series also introduces support for the memory types of the D1
> > > > > which are implemented differently to svpbmt. But when patching anyway
> > > > > it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> > > > > location.
> > > > >
> > > > > The only slightly bigger difference is that the "normal" type is not 0
> > > > > as with svpbmt, so kernel patches for this PMA type need to be applied
> > > > > even before the MMU is brought up, so the series introduces a separate
> > > > > stage for that.
> > > > >
> > > > >
> > > > > In theory this series is 3 parts:
> > > > > - sbi cache-flush / null-ptr
> > > > > - alternatives improvements
> > > > > - svpbmt+d1
> > > > >
> > > > > So expecially patches from the first 2 areas could be applied when
> > > > > deemed ready, I just thought to keep it together to show-case where
> > > > > the end-goal is and not requiring jumping between different series.
> > > > >
> > > > >
> > > > > The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> > > > > as it touches a similar area in mm/cacheflush.c
> > > > >
> > > > >
> > > > > I picked the recipient list from the previous version, hopefully
> > > > > I didn't forget anybody.
> > > > >
> > >
> > > I am also getting a load access fault while booting this series in Qemu.
> > >
> > > <with additional debug message when before sbi_trap_redirect in OpenSBI>
> > > sbi_trap_error_debug: hart1: trap handler failed (error -2)
> > > sbi_trap_error_debug: hart1: mcause=0x0000000000000005 mtval=0x0000000080046468
> > > sbi_trap_error_debug: hart1: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> > > sbi_trap_error_debug: hart1: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> > > sbi_trap_error_debug: hart1: ra=0x0000000080202b06 sp=0x0000000081203f00
> > > sbi_trap_error_debug: hart1: gp=0x00000000812d9db8 tp=0x0000000080046000
> > > sbi_trap_error_debug: hart1: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> > > sbi_trap_error_debug: hart1: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> > > sbi_trap_error_debug: hart1: a2=0x0000000000000002 a3=0x0000000000000000
> > > sbi_trap_error_debug: hart1: a4=0x00000000812da902 a5=0x0000000000000000
> > > sbi_trap_error_debug: hart1: a6=0x0000000000000006 a7=0x0000000000000010
> > > sbi_trap_error_debug: hart1: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> > > sbi_trap_error_debug: hart1: s4=0x00000000bf000000 s5=0x0000000000000000
> > > sbi_trap_error_debug: hart1: s6=0x8000000a00006800 s7=0x000000000000007f
> > > sbi_trap_error_debug: hart1: s8=0x0000000080018038 s9=0x0000000080039eac
> > > sbi_trap_error_debug: hart1: s10=0x0000000000000000 s11=0x0000000000000000
> > > sbi_trap_error_debug: hart1: t0=0x0000000080c04000 t1=0x0000000000000002
> > > sbi_trap_error_debug: hart1: t2=0x0000000000001000 t3=0x0000000000000010
> > > sbi_trap_error_debug: hart1: t4=0x00000000800168be t5=0x0000000000000027
> > > sbi_trap_error_debug: hart1: t6=0x0000000000000001
> > >
> > > mepc : 0x000000008080a8b8 - call_function_init (kernel/smp.c)
> > >
> > > Kernel - 5.17-rc2 + my patches
> > > Qemu - Alistairs next tree + my patches
> >
> > very strange. I was testing of course with Qemu as well, though never saw
> > anything like this.
> >
> > But of course it was Qemu master + the then still pending svpbmt patchset [0]
> > [looks like Alistair applied this today] + a patch that made qemu insert the
> > svpbmt dt-property for the virt machine.
> >
> > Oh ... just to make sure, did you enable the svpbmt parameter when starting
> > Qemu? (-cpu ...,svpbmt=true)
> >
>
> Yeah. I tried with or without. It's failing in both cases. I found a
> fix but that may be unrelated and hiding the real issue.
> Marking the cpufeature_svpbmt_check_of functions inline allows me to boot.
>
> Here is my analysis:
>
> Here is the trace of the trap:
> sbi_trap_error_debug: hart0: trap handler failed (error -2)
> sbi_trap_error_debug: hart0: mcause=0x0000000000000005 mtval=0x0000000080048468
> sbi_trap_error_debug: hart0: mtval2=0x0000000000000000 mtinst=0x0000000000000000
> sbi_trap_error_debug: hart0: mepc=0x000000008080a8b8 mstatus=0x0000000a00000800
> sbi_trap_error_debug: hart0: ra=0x0000000080202b06 sp=0x0000000081203f00
> sbi_trap_error_debug: hart0: gp=0x00000000812d9db8 tp=0x0000000080048000
> sbi_trap_error_debug: hart0: s0=0x0000000081203f80 s1=0x0000000080c1a8a8
> sbi_trap_error_debug: hart0: a0=0x0000000080c1a8a8 a1=0x0000000080c1b0d0
> sbi_trap_error_debug: hart0: a2=0x0000000000000002 a3=0x0000000000000000
> sbi_trap_error_debug: hart0: a4=0x00000000812da902 a5=0x0000000000000000
> sbi_trap_error_debug: hart0: a6=0x0000000000000006 a7=0x0000000000000010
> sbi_trap_error_debug: hart0: s2=0x0000000080c1b0d0 s3=0x0000000000000002
> sbi_trap_error_debug: hart0: s4=0x00000000bf000000 s5=0x0000000000000000
> sbi_trap_error_debug: hart0: s6=0x8000000a00006800 s7=0x000000000000007f
> sbi_trap_error_debug: hart0: s8=0x0000000080018038 s9=0x0000000080039ea8
> sbi_trap_error_debug: hart0: s10=0x0000000000000000 s11=0x0000000000000000
> sbi_trap_error_debug: hart0: t0=0x0000000080c04000 t1=0x0000000000000002
> sbi_trap_error_debug: hart0: t2=0x0000000000001000 t3=0x0000000000000010
> sbi_trap_error_debug: hart0: t4=0x00000000800168be t5=0x0000000000000027
> sbi_trap_error_debug: hart0: t6=0x0000000000000001
>
> mepc : 0x000000008080a8b8 - should be ffffffff8060a8b8 in objdump
> output after offset
>
> Here is the snippet of the objdump output for riscv_cpufeature_patch_func
>
> ========================================================================
> inline output: (booting fails with above dump)
>
> void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned int stage)
> {
> ffffffff8060a89a: 7119 addi sp,sp,-128
> ffffffff8060a89c: f8a2 sd s0,112(sp)
> ffffffff8060a89e: f4a6 sd s1,104(sp)
> ffffffff8060a8a0: f0ca sd s2,96(sp)
> ffffffff8060a8a2: e4d6 sd s5,72(sp)
> ffffffff8060a8a4: fc86 sd ra,120(sp)
> ffffffff8060a8a6: ecce sd s3,88(sp)
> ffffffff8060a8a8: e8d2 sd s4,80(sp)
> ffffffff8060a8aa: e0da sd s6,64(sp)
> ffffffff8060a8ac: fc5e sd s7,56(sp)
> ffffffff8060a8ae: f862 sd s8,48(sp)
> ffffffff8060a8b0: f466 sd s9,40(sp)
> ffffffff8060a8b2: f06a sd s10,32(sp)
> ffffffff8060a8b4: ec6e sd s11,24(sp)
> ffffffff8060a8b6: 0100 addi s0,sp,128
> ffffffff8060a8b8: 46823783 ld a5,1128(tp) #
> 468 <__efistub_.L0 +0x5> --------> Faulting instruction
> ffffffff8060a8bc: f8f43423 sd a5,-120(s0)
> ffffffff8060a8c0: 4781 li a5,0
> ffffffff8060a8c2: 8932 mv s2,a2
> ffffffff8060a8c4: 84aa mv s1,a0
> ffffffff8060a8c6: 8aae mv s5,a1
> switch (stage) {
> ffffffff8060a8c8: ca1d beqz
> a2,ffffffff8060a8fe <riscv_cpufeature_patch_func+0x64>
> ffffffff8060a8ca: 4789 li a5,2
> ffffffff8060a8cc: 18f60363 beq
> a2,a5,ffffffff8060aa52 <riscv_cpufeature_patch_func+0x1b8>
> for_each_of_cpu_node(node) {
> ffffffff8060a8d0: 4501 li a0,0
> ========================================================================
>
> noinline output (boots fine)
> ========================================================================
> void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned int stage)
> {
> ffffffff8060a968: 7159 addi sp,sp,-112
> ffffffff8060a96a: f0a2 sd s0,96(sp)
> ffffffff8060a96c: eca6 sd s1,88(sp)
> ffffffff8060a96e: e8ca sd s2,80(sp)
> ffffffff8060a970: fc56 sd s5,56(sp)
> ffffffff8060a972: f486 sd ra,104(sp)
> ffffffff8060a974: e4ce sd s3,72(sp)
> ffffffff8060a976: e0d2 sd s4,64(sp)
> ffffffff8060a978: f85a sd s6,48(sp)
> ffffffff8060a97a: f45e sd s7,40(sp)
> ffffffff8060a97c: f062 sd s8,32(sp)
> ffffffff8060a97e: ec66 sd s9,24(sp)
> ffffffff8060a980: e86a sd s10,16(sp)
> ffffffff8060a982: e46e sd s11,8(sp)
> ffffffff8060a984: 1880 addi s0,sp,112
> ffffffff8060a986: 8932 mv s2,a2
> ffffffff8060a988: 84aa mv s1,a0
> ffffffff8060a98a: 8aae mv s5,a1
> switch (stage) {
> ffffffff8060a98c: ca09 beqz
> a2,ffffffff8060a99e <riscv_cpufeature_patch_func+0x36>
> ffffffff8060a98e: 4789 li a5,2
> ffffffff8060a990: 0ef60f63 beq
> a2,a5,ffffffff8060aa8e <riscv_cpufeature_patch_func+0x126>
> return cpufeature_svpbmt_check_of();
> ffffffff8060a994: f07ff0ef jal
> ra,ffffffff8060a89a <cpufeature_svpbmt_check_of>
> cpu_req_feature |= (1U << idx);
> ffffffff8060a998: 0005091b sext.w s2,a0
> ffffffff8060a99c: a8d5 j
> ffffffff8060aa90 <riscv_cpufeature_patch_func+0x128>
> const void *fdt = dtb_early_va;
>
>
> Any thoughts ? It looks like it may related to "tp"
Faulting instruction "efistub", so maybe something between efi
and the devicetree not agreeing?
Though at least on my build I also have efistub enabled, so it
should be the same. So it's very strange that you're seeing that
trap, which I've never seen so far.
In any case, I tried your + Tsukasa's patches regarding the isa-extensions
today, and obviously that works fine, so we wil get rid of the devicetree-
parts anyway I guess.
With the change below on top of that v2/v3 version-mix, I also get a
working svpbmt of course. After hacking qemu to generate a
suitable isa-string for me :-) .
Heiko
-------------- 8< ------------------
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 691fc9c8099b..656cd626eb1a 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -51,6 +51,7 @@ extern unsigned long elf_hwcap;
* available logical extension id.
*/
enum riscv_isa_ext_id {
+ RISCV_ISA_EXT_SVPBMT = RISCV_ISA_EXT_BASE,
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
};
diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
index ced7e5be8641..b5130b15ca8d 100644
--- a/arch/riscv/kernel/cpu.c
+++ b/arch/riscv/kernel/cpu.c
@@ -71,6 +71,7 @@ int riscv_of_parent_hartid(struct device_node *node)
}
static struct riscv_isa_ext_data isa_ext_arr[] = {
+ __RISCV_ISA_EXT_DATA("svpbmt", RISCV_ISA_EXT_SVPBMT),
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
};
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 2e4eaedbf7f5..d82033ece1fd 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -192,6 +192,8 @@ void __init riscv_fill_hwcap(void)
if (!ext_long) {
this_hwcap |= isa2hwcap[(unsigned char)(*ext)];
this_isa |= (1UL << (*ext - 'a'));
+ } else {
+ SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
}
#undef SET_ISA_EXT_MAP
}
@@ -253,64 +255,6 @@ struct cpufeature_info {
bool (*check_func)(unsigned int stage);
};
-#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
-static bool __init_or_module cpufeature_svpbmt_check_fdt(void)
-{
- const void *fdt = dtb_early_va;
- const char *str;
- int offset;
-
- offset = fdt_path_offset(fdt, "/cpus");
- if (offset < 0)
- return false;
-
- for (offset = fdt_next_node(fdt, offset, NULL); offset >= 0;
- offset = fdt_next_node(fdt, offset, NULL)) {
- str = fdt_getprop(fdt, offset, "device_type", NULL);
- if (!str || strcmp(str, "cpu"))
- break;
-
- str = fdt_getprop(fdt, offset, "mmu-type", NULL);
- if (!str)
- continue;
-
- if (!strncmp(str + 6, "none", 4))
- continue;
-
- str = fdt_getprop(fdt, offset, "riscv,mmu", NULL);
- if (!str)
- continue;
-
- if (!strncmp(str + 6, "svpbmt", 6))
- return true;
- }
-
- return false;
-}
-
-static bool __init_or_module cpufeature_svpbmt_check_of(void)
-{
- struct device_node *node;
- const char *str;
-
- for_each_of_cpu_node(node) {
- if (of_property_read_string(node, "mmu-type", &str))
- continue;
-
- if (!strncmp(str + 6, "none", 4))
- continue;
-
- if (of_property_read_string(node, "riscv,mmu", &str))
- continue;
-
- if (!strncmp(str + 6, "svpbmt", 6))
- return true;
- }
-
- return false;
-}
-#endif
-
static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
{
bool ret = false;
@@ -319,10 +263,8 @@ static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
switch (stage) {
case RISCV_ALTERNATIVES_EARLY_BOOT:
return false;
- case RISCV_ALTERNATIVES_BOOT:
- return cpufeature_svpbmt_check_fdt();
default:
- return cpufeature_svpbmt_check_of();
+ return riscv_isa_extension_available(NULL, SVPBMT);
}
#endif
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index c01012f3740d..ec07f991866a 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -10,7 +10,6 @@
#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/alternative.h>
#include <asm/csr.h>
#include <asm/cpu_ops_sbi.h>
#include <asm/hwcap.h>
@@ -341,7 +340,6 @@ clear_bss_done:
call kasan_early_init
#endif
/* Start the kernel */
- call apply_boot_alternatives
call soc_early_init
tail start_kernel
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 339ceb595b38..b4879c942b42 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -21,6 +21,7 @@
#include <linux/efi.h>
#include <linux/crash_dump.h>
+#include <asm/alternative.h>
#include <asm/cpu_ops.h>
#include <asm/early_ioremap.h>
#include <asm/pgtable.h>
@@ -295,6 +296,7 @@ void __init setup_arch(char **cmdline_p)
#endif
riscv_fill_hwcap();
+ apply_boot_alternatives();
}
static int __init topology_init(void)
On Wed, 09 Feb 2022 04:37:53 PST (-0800), [email protected] wrote:
> Instructions are opportunistically compressed by the RISC-V assembler
> when possible, but in alternatives-blocks both the old and new content
> need to be the same size, so having the toolchain do somewhat random
> optimizations will cause strange side-effects like
> "attempt to move .org backwards" compile-time errors.
>
> Already a simple "and" used in alternatives assembly will cause these
> mismatched code sizes.
There should probably be a ".option norelax" in here as well, as
relaxation will trigger exactly the same issues. That, or we could just
remove the constraint that these must be the same size (ie,
automatically pad the smaller one with NOP/jump-to-end).
> So prevent compressed instructions to be generated in alternatives-
> code and use option-push and -pop to only limit this to the relevant
> code blocks
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/include/asm/alternative-macros.h | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h
> index c0fb11fad631..3a52884bf23d 100644
> --- a/arch/riscv/include/asm/alternative-macros.h
> +++ b/arch/riscv/include/asm/alternative-macros.h
> @@ -19,7 +19,10 @@
> .popsection
> .subsection 1
> 888 :
> + .option push
> + .option norvc
> \new_c
> + .option pop
> 889 :
> .previous
> .org . - (889b - 888b) + (887b - 886b)
> @@ -29,7 +32,10 @@
>
> .macro __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable
> 886 :
> + .option push
> + .option norvc
> \old_c
> + .option pop
> 887 :
> ALT_NEW_CONTENT \vendor_id, \errata_id, \enable, \new_c
> .endm
> @@ -40,7 +46,10 @@
> .macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
> new_c_2, vendor_id_2, errata_id_2, enable_2
> 886 :
> + .option push
> + .option norvc
> \old_c
> + .option pop
> 887 :
> ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1
> ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2
> @@ -70,7 +79,10 @@
> ".popsection\n" \
> ".subsection 1\n" \
> "888 :\n" \
> + ".option push\n" \
> + ".option norvc\n" \
> new_c "\n" \
> + ".option pop\n" \
> "889 :\n" \
> ".previous\n" \
> ".org . - (887b - 886b) + (889b - 888b)\n" \
> @@ -79,7 +91,10 @@
>
> #define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, enable) \
> "886 :\n" \
> + ".option push\n" \
> + ".option norvc\n" \
> old_c "\n" \
> + ".option pop\n" \
> "887 :\n" \
> ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c)
>
> @@ -89,7 +104,10 @@
> #define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
> new_c_2, vendor_id_2, errata_id_2, enable_2) \
> "886 :\n" \
> + ".option push\n" \
> + ".option norvc\n" \
> old_c "\n" \
> + ".option pop\n" \
> "887 :\n" \
> ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \
> ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2)
After trying it on my SMP 4*910 platform, it could boot normally.
Tested-by: Guo Ren <[email protected]>
On Wed, Feb 9, 2022 at 8:38 PM Heiko Stuebner <[email protected]> wrote:
>
> Svpbmt is an extension defining "Supervisor-mode: page-based memory types"
> for things like non-cacheable pages or I/O memory pages.
>
>
> So this is my 2nd try at implementing Svpbmt (and the diverging D1 memory
> types) using the alternatives framework.
>
> This includes a number of changes to the alternatives mechanism itself.
> The biggest one being the move to a more central location, as I expect
> in the future, nearly every chip needing some sort of patching, be it
> either for erratas or for optional features (svpbmt or others).
>
> The dt-binding for svpbmt itself is of course not finished and is still
> using the binding introduced in previous versions, as where to put
> a svpbmt-property in the devicetree is still under dicussion.
> Atish seems to be working on a framework for extensions [0],
>
> The series also introduces support for the memory types of the D1
> which are implemented differently to svpbmt. But when patching anyway
> it's pretty clean to add the D1 variant via ALTERNATIVE_2 to the same
> location.
>
> The only slightly bigger difference is that the "normal" type is not 0
> as with svpbmt, so kernel patches for this PMA type need to be applied
> even before the MMU is brought up, so the series introduces a separate
> stage for that.
>
>
> In theory this series is 3 parts:
> - sbi cache-flush / null-ptr
> - alternatives improvements
> - svpbmt+d1
>
> So expecially patches from the first 2 areas could be applied when
> deemed ready, I just thought to keep it together to show-case where
> the end-goal is and not requiring jumping between different series.
>
>
> The sbi cache-flush patch is based on Atish's sparse-hartid patch [1],
> as it touches a similar area in mm/cacheflush.c
>
>
> I picked the recipient list from the previous version, hopefully
> I didn't forget anybody.
>
> changes in v6:
> - rebase onto 5.17-rc1
> - handle sbi null-ptr differently
> - improve commit messages
> - use riscv,mmu as property name
>
> changes in v5:
> - move to use alternatives for runtime-patching
> - add D1 variant
>
>
> [0] https://lore.kernel.org/r/[email protected]
> [1] https://lore.kernel.org/r/[email protected]
>
>
> Heiko Stuebner (12):
> riscv: prevent null-pointer dereference with sbi_remote_fence_i
> riscv: integrate alternatives better into the main architecture
> riscv: allow different stages with alternatives
> riscv: implement module alternatives
> riscv: implement ALTERNATIVE_2 macro
> riscv: extend concatenated alternatives-lines to the same length
> riscv: prevent compressed instructions in alternatives
> riscv: move boot alternatives to a slightly earlier position
> riscv: Fix accessing pfn bits in PTEs for non-32bit variants
> riscv: add cpufeature handling via alternatives
> riscv: remove FIXMAP_PAGE_IO and fall back to its default value
> riscv: add memory-type errata for T-Head
>
> Wei Fu (2):
> dt-bindings: riscv: add MMU Standard Extensions support for Svpbmt
> riscv: add RISC-V Svpbmt extension support
>
> .../devicetree/bindings/riscv/cpus.yaml | 10 ++
> arch/riscv/Kconfig.erratas | 29 ++--
> arch/riscv/Kconfig.socs | 1 -
> arch/riscv/Makefile | 2 +-
> arch/riscv/errata/Makefile | 2 +-
> arch/riscv/errata/sifive/errata.c | 10 +-
> arch/riscv/errata/thead/Makefile | 1 +
> arch/riscv/errata/thead/errata.c | 85 +++++++++++
> arch/riscv/include/asm/alternative-macros.h | 114 ++++++++-------
> arch/riscv/include/asm/alternative.h | 16 ++-
> arch/riscv/include/asm/errata_list.h | 52 +++++++
> arch/riscv/include/asm/fixmap.h | 2 -
> arch/riscv/include/asm/pgtable-32.h | 17 +++
> arch/riscv/include/asm/pgtable-64.h | 79 +++++++++-
> arch/riscv/include/asm/pgtable-bits.h | 10 --
> arch/riscv/include/asm/pgtable.h | 53 +++++--
> arch/riscv/include/asm/vendorid_list.h | 1 +
> arch/riscv/kernel/Makefile | 1 +
> arch/riscv/{errata => kernel}/alternative.c | 48 ++++++-
> arch/riscv/kernel/cpufeature.c | 136 +++++++++++++++++-
> arch/riscv/kernel/head.S | 2 +
> arch/riscv/kernel/module.c | 29 ++++
> arch/riscv/kernel/sbi.c | 10 +-
> arch/riscv/kernel/smpboot.c | 4 -
> arch/riscv/kernel/traps.c | 2 +-
> arch/riscv/mm/init.c | 1 +
> 26 files changed, 606 insertions(+), 111 deletions(-)
> create mode 100644 arch/riscv/errata/thead/Makefile
> create mode 100644 arch/riscv/errata/thead/errata.c
> rename arch/riscv/{errata => kernel}/alternative.c (59%)
>
> --
> 2.30.2
>
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/