diff mbox series

[10/12] RISC-V: workaround Nuclei UX600 cores with broken SATP CSR

Message ID 20220127151647.2375449-11-icenowy@nucleisys.com
State New
Headers show
Series Initial support for Nuclei DemoSoC w/ UX600 | expand

Commit Message

Icenowy Zheng Jan. 27, 2022, 3:16 p.m. UTC
Current release of Nuclei UX600 CPU cores have two errata against RISC-V
Privledged Specification 1.10: one is left over mvendorid value (not the
JEDEC ID), the other, which is a more breaking one that needs to be
workaround in software, is that satp will accept written value with
MODE=9 (Sv48, which is not supported by UX600), and silently change it
to MODE=8 (Sv39). As current kernel MMU initialization code relies on
the behavior defined on the spec (reject write request with unsupported
MODE value and do not change the CSR's value at all) to detect the
existence of Sv48, the erratum breaks the Sv48 detection code.

As both two errata are to be fixed in the next revision, use the first
to detect the existence of the second at runtime, and force Sv39 when
these errata are detected.

Signed-off-by: Icenowy Zheng <icenowy@nucleisys.com>
---
 arch/riscv/include/asm/vendorid_list.h |  1 +
 arch/riscv/mm/init.c                   | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index 9d934215b3c8..47ff43795d70 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 NUCLEI_OLD_VENDOR_ID	0x2d33
 
 #endif
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index cf4d018b7d66..0085b14ae265 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -28,6 +28,8 @@ 
 #include <asm/io.h>
 #include <asm/ptdump.h>
 #include <asm/numa.h>
+#include <asm/sbi.h>
+#include <asm/vendorid_list.h>
 
 #include "../kernel/head.h"
 
@@ -591,6 +593,21 @@  static __init void set_satp_mode(void)
 	u64 identity_satp, hw_satp;
 	uintptr_t set_satp_mode_pmd;
 
+	if (sbi_get_mvendorid() == NUCLEI_OLD_VENDOR_ID) {
+		/*
+		 * Old Nuclei UX600 processor releases have broken
+		 * implementation of SATP register which prevents
+		 * proper runtime detection of Sv48 existence. In
+		 * addition these processor releases have an old
+		 * vendor id instead of proper JEDEC ID.
+		 *
+		 * As these releases do not support Sv48 at all,
+		 * force Sv39 on them.
+		 */
+		disable_pgtable_l4();
+		return;
+	}
+
 	set_satp_mode_pmd = ((unsigned long)set_satp_mode) & PMD_MASK;
 	create_pgd_mapping(early_pg_dir,
 			   set_satp_mode_pmd, (uintptr_t)early_pud,