diff --git a/sys/riscv/include/md_var.h b/sys/riscv/include/md_var.h --- a/sys/riscv/include/md_var.h +++ b/sys/riscv/include/md_var.h @@ -46,6 +46,9 @@ extern bool has_sscofpmf; extern bool has_svpbmt; +/* CPU errata presence */ +extern bool has_errata_thead_pbmt; + struct dumperinfo; struct minidumpstate; diff --git a/sys/riscv/include/pte.h b/sys/riscv/include/pte.h --- a/sys/riscv/include/pte.h +++ b/sys/riscv/include/pte.h @@ -102,6 +102,32 @@ #define PTE_MA_NC (1ul << PTE_MA_SHIFT) #define PTE_MA_IO (2ul << PTE_MA_SHIFT) +/* + * T-HEAD Custom Memory Attribute (MA) bits [63:59]. + * + * bit 59: Trustable (relating to TEE) + * bit 60: Shareable (among CPUs, not configurable) + * bit 61: Bufferable (writes to device memory) + * bit 62: Cacheable + * bit 63: Memory Ordering (1 = strongly ordered (device), 0 = default) + * + * +------+-------+------------------------------------------------------------+ + * | Mode | Value | Requested Memory Attributes | + * +------+-------+------------------------------------------------------------+ + * | NC | 00110 | Weakly-ordered, non-cacheable, bufferable, shareable, | + * | | | non-trustable | + * | PMA | 01110 | Weakly-ordered, cacheable, bufferable, shareable, | + * | | | non-trustable | + * | IO | 10010 | Strongly-ordered, non-cacheable, non-bufferable, | + * | | | shareable, non-trustable | + * +------+-------+------------------------------------------------------------+ + */ +#define PTE_THEAD_MA_SHIFT 59 +#define PTE_THEAD_MA_MASK (0xf800000000000000ul) +#define PTE_THEAD_MA_NC ((1ul << 61) | (1ul << 60)) +#define PTE_THEAD_MA_NONE ((1ul << 62) | (1ul << 61) | (1ul << 60)) +#define PTE_THEAD_MA_IO ((1ul << 63) | (1ul << 60)) + /* Bits 63 - 54 are reserved for future use. */ #define PTE_HI_MASK 0xFFC0000000000000ULL diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c --- a/sys/riscv/riscv/identcpu.c +++ b/sys/riscv/riscv/identcpu.c @@ -76,6 +76,9 @@ bool __read_frequently has_sscofpmf; bool __read_frequently has_svpbmt; +/* CPU errata */ +bool has_errata_thead_pbmt; + struct cpu_desc { const char *cpu_mvendor_name; const char *cpu_march_name; @@ -459,6 +462,22 @@ } } +static void +update_cpu_errata_thead(u_int cpu, struct cpu_desc *desc) +{ + has_errata_thead_pbmt = true; +} + +static void +update_cpu_errata(u_int cpu, struct cpu_desc *desc) +{ + switch (mvendorid) { + case MVENDORID_THEAD: + update_cpu_errata_thead(cpu, desc); + break; + } +} + void identify_cpu(u_int cpu) { @@ -467,6 +486,7 @@ identify_cpu_ids(desc); identify_cpu_features(cpu, desc); + update_cpu_errata(cpu, desc); update_global_capabilities(cpu, desc); } diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -866,6 +866,11 @@ memattr_bits[VM_MEMATTR_UNCACHEABLE] = PTE_MA_NC; memattr_bits[VM_MEMATTR_DEVICE] = PTE_MA_IO; memattr_mask = PTE_MA_MASK; + } else if (has_errata_thead_pbmt) { + memattr_bits[VM_MEMATTR_PMA] = PTE_THEAD_MA_NONE; + memattr_bits[VM_MEMATTR_UNCACHEABLE] = PTE_THEAD_MA_NC; + memattr_bits[VM_MEMATTR_DEVICE] = PTE_THEAD_MA_IO; + memattr_mask = PTE_THEAD_MA_MASK; } /* Create a new set of pagetables to run the kernel in. */