From 660358cf7b5b9fda72e619f37efe4c68af19dccb Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sat, 11 Sep 2021 17:21:35 +0800 Subject: [PATCH] riscv: errata: pgtable: Add custom Svpbmt supported for Allwinner D1 RISC-V Svpbmt is gradually maturing, the draft is: Svpbmt PTE format: | 63 | 62-61 | 60-8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 N MT RSW D A G U X W R V ^ Of the Reserved bits [63:54] in a leaf PTE, the high bit is already allocated (as the N bit), so bits [62:61] are used as the MT (aka MemType) field. This field specifies one of three memory types that are close equivalents (or equivalent in effect) to the three main x86 and ARMv8 memory types - as shown in the following table. RISC-V Encoding & MemType RISC-V Description ---------- ------------------------------------------------ 00 - PMA Normal Cacheable, No change to implied PMA memory type 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory 11 - Rsvd Reserved for future standard use But T-HEAD C906 in Allwinner D1 has defined a custom Svpbmt: T-HEAD C9xx PTE format: | 63 | 62 | 61 | 60 | 59-8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 SO C B SH RSW D A G U X W R V ^ ^ ^ ^ BIT(63): SO - Strong Order BIT(62): C - Cacheable BIT(61): B - Bufferable BIT(60): SH - Shareable MT_MASK : [63 - 59] MT_PMA : C + SH MT_NC : (none) MT_IO : SO The patch not only implements the D1's PBMT extension but also considers future scalability by errata framework. We are trying to keep both below work together: - "riscv spec acceptance policy" (Svpbmt extension in future) - "Linux Keep real hardware work" (Allwinner D1's custom Svpbmt) Signed-off-by: Guo Ren Signed-off-by: Liu Shaohua Signed-off-by: Wei Fu Cc: Palmer Dabbelt Cc: Christoph Hellwig Cc: Anup Patel Cc: Arnd Bergmann Cc: Drew Fustini Cc: Wei Fu Cc: Wei Wu Cc: Chen-Yu Tsai Cc: Maxime Ripard Cc: Daniel Lustig Cc: Greg Favor Cc: Andrea Mondelli Cc: Jonathan Behrens Cc: Xinhaoqu (Freddie) Cc: Bill Huffman Cc: Nick Kossifidis Cc: Allen Baum Cc: Josh Scheid Cc: Richard Trauben --- arch/riscv/Kconfig.erratas | 12 ++++++++ arch/riscv/errata/Makefile | 1 + arch/riscv/errata/alternative.c | 18 +++++++++++ arch/riscv/errata/thead/Makefile | 1 + arch/riscv/errata/thead/errata.c | 41 ++++++++++++++++++++++++++ arch/riscv/include/asm/alternative.h | 2 ++ arch/riscv/include/asm/vendorid_list.h | 1 + arch/riscv/mm/init.c | 2 ++ 8 files changed, 78 insertions(+) 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 b44d6ecdb46e5..7e92b4640122d 100644 --- a/arch/riscv/Kconfig.erratas +++ b/arch/riscv/Kconfig.erratas @@ -41,4 +41,16 @@ config ERRATA_SIFIVE_CIP_1200 If you don't know what to do here, say "Y". +config ERRATA_THEAD + bool "T-HEAD errata" + depends on RISCV_ERRATA_ALTERNATIVE + select SERIAL_8250_DW + default y + 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. + + Otherwise, please say "N" here to avoid unnecessary overhead. + endmenu diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile index b8f8740a3e442..f6db15055e737 100644 --- a/arch/riscv/errata/Makefile +++ b/arch/riscv/errata/Makefile @@ -1,2 +1,3 @@ obj-y += alternative.o obj-$(CONFIG_ERRATA_SIFIVE) += sifive/ +obj-$(CONFIG_ERRATA_THEAD) += thead/ diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c index e8b4a0fe488c1..4dc6a2dada264 100644 --- a/arch/riscv/errata/alternative.c +++ b/arch/riscv/errata/alternative.c @@ -73,3 +73,21 @@ void __init apply_boot_alternatives(void) cpu_mfr_info.arch_id, cpu_mfr_info.imp_id); } +/* + * This is called very early form setup_vm in the boot process. + */ +void __init apply_errata_setup_vm(void) +{ + riscv_fill_cpu_mfr_info(); + + switch (cpu_mfr_info.vendor_id) { +#ifdef CONFIG_ERRATA_THEAD + case THEAD_VENDOR_ID: + thead_errata_setup_vm(cpu_mfr_info.arch_id, + cpu_mfr_info.imp_id); + break; +#endif + default: + break; + } +} diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile new file mode 100644 index 0000000000000..2d644e19caefc --- /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 0000000000000..9b11074b1f9c2 --- /dev/null +++ b/arch/riscv/errata/thead/errata.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * T-HEAD C9xx PTE format: + * | 63 | 62 | 61 | 60 | 59-8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + * SO C B SH RSW D A G U X W R V + * ^ ^ ^ ^ ^ + * BIT(63): SO - Strong Order + * BIT(62): C - Cacheable + * BIT(61): B - Bufferable + * BIT(60): SH - Shareable + * + * MT_MASK : [63 - 59] + * MT_PMA : C + SH + * MT_NC : (none) + * MT_IO : SO + */ +void __init thead_errata_setup_vm(unsigned long archid, unsigned long impid) +{ + int i; + +#ifdef CONFIG_64BIT + __riscv_svpbmt.mask = 0xf800000000000000; + __riscv_svpbmt.mt_pma = 0x5000000000000000; + __riscv_svpbmt.mt_nc = 0x0; + __riscv_svpbmt.mt_io = 0x8000000000000000; +#endif + + for (i = 0; i < 16; i++) + pgprot_val(protection_map[i]) |= __riscv_svpbmt.mt_pma; +} diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h index e625d3cafbed5..3605894081a89 100644 --- a/arch/riscv/include/asm/alternative.h +++ b/arch/riscv/include/asm/alternative.h @@ -18,6 +18,7 @@ #include void __init apply_boot_alternatives(void); +void __init apply_errata_setup_vm(void); struct alt_entry { void *old_ptr; /* address of original instruciton or data */ @@ -35,5 +36,6 @@ struct errata_checkfunc_id { void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, unsigned long archid, unsigned long impid); +void thead_errata_setup_vm(unsigned long archid, unsigned long impid); #endif #endif diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h index 9d934215b3c85..bdfce1a4b42b5 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/mm/init.c b/arch/riscv/mm/init.c index b12ddcdd59d6e..bea0d71d723c1 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -773,6 +773,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) { pmd_t __maybe_unused fix_bmap_spmd, fix_bmap_epmd; + apply_errata_setup_vm(); + kernel_map.virt_addr = KERNEL_LINK_ADDR; kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL);