Skip to content

Commit

Permalink
riscv: errata: pgtable: Add custom Svpbmt supported for Allwinner D1
Browse files Browse the repository at this point in the history
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 <guoren@linux.alibaba.com>
Signed-off-by: Liu Shaohua <liush@allwinnertech.com>
Signed-off-by: Wei Fu <wefu@redhat.com>
Cc: Palmer Dabbelt <palmerdabbelt@google.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Anup Patel <anup.patel@wdc.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Drew Fustini <drew@beagleboard.org>
Cc: Wei Fu <wefu@redhat.com>
Cc: Wei Wu <lazyparser@gmail.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Maxime Ripard <maxime@cerno.tech>
Cc: Daniel Lustig <dlustig@nvidia.com>
Cc: Greg Favor <gfavor@ventanamicro.com>
Cc: Andrea Mondelli <andrea.mondelli@huawei.com>
Cc: Jonathan Behrens <behrensj@mit.edu>
Cc: Xinhaoqu (Freddie) <xinhaoqu@huawei.com>
Cc: Bill Huffman <huffman@cadence.com>
Cc: Nick Kossifidis <mick@ics.forth.gr>
Cc: Allen Baum <allen.baum@esperantotech.com>
Cc: Josh Scheid <jscheid@ventanamicro.com>
Cc: Richard Trauben <rtrauben@gmail.com>
  • Loading branch information
guoren83 committed Dec 29, 2021
1 parent 86840aa commit ff10a70
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 0 deletions.
12 changes: 12 additions & 0 deletions arch/riscv/Kconfig.erratas
Expand Up @@ -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
1 change: 1 addition & 0 deletions arch/riscv/errata/Makefile
@@ -1,2 +1,3 @@
obj-y += alternative.o
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
obj-$(CONFIG_ERRATA_THEAD) += thead/
18 changes: 18 additions & 0 deletions arch/riscv/errata/alternative.c
Expand Up @@ -72,3 +72,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;
}
}
1 change: 1 addition & 0 deletions arch/riscv/errata/thead/Makefile
@@ -0,0 +1 @@
obj-y += errata.o
41 changes: 41 additions & 0 deletions arch/riscv/errata/thead/errata.c
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0-only

#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/bug.h>
#include <linux/mm.h>
#include <asm/patch.h>
#include <asm/alternative.h>
#include <asm/vendorid_list.h>
#include <asm/errata_list.h>
#include <asm/pgtable.h>

/*
* 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;
}
2 changes: 2 additions & 0 deletions arch/riscv/include/asm/alternative.h
Expand Up @@ -18,6 +18,7 @@
#include <asm/hwcap.h>

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 */
Expand All @@ -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
1 change: 1 addition & 0 deletions arch/riscv/include/asm/vendorid_list.h
Expand Up @@ -6,5 +6,6 @@
#define ASM_VENDOR_LIST_H

#define SIFIVE_VENDOR_ID 0x489
#define THEAD_VENDOR_ID 0x5b7

#endif
2 changes: 2 additions & 0 deletions arch/riscv/mm/init.c
Expand Up @@ -847,6 +847,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);

Expand Down

0 comments on commit ff10a70

Please sign in to comment.