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@xxxxxxxxxxxxx> --- arch/riscv/include/asm/vendorid_list.h | 1 + arch/riscv/mm/init.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) 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, -- 2.30.2