git: ccbe9a9f732e - main - riscv: T-HEAD PBMT support

From: Mitchell Horne <mhorne_at_FreeBSD.org>
Date: Mon, 25 Nov 2024 21:08:47 UTC
The branch main has been updated by mhorne:

URL: https://cgit.FreeBSD.org/src/commit/?id=ccbe9a9f732ee2f10f252a5586309a82e6ffd1e7

commit ccbe9a9f732ee2f10f252a5586309a82e6ffd1e7
Author:     Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2024-11-21 18:12:12 +0000
Commit:     Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2024-11-25 21:08:04 +0000

    riscv: T-HEAD PBMT support
    
    T-HEAD CPUs provide a spec-violating implementation of page-based memory
    types, using PTE bits [63:59]. Add basic support for this "errata",
    referred to in some places as an "extension".
    
    Note that this change is not enough on its own, but a workaround is
    needed for the bootstrap (locore) page tables as well.
    
    Reviewed by:    jhb
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D45472
---
 sys/riscv/include/pte.h    | 26 ++++++++++++++++++++++++++
 sys/riscv/include/thead.h  |  2 ++
 sys/riscv/riscv/identcpu.c |  1 +
 sys/riscv/riscv/pmap.c     |  6 ++++++
 sys/riscv/thead/thead.c    |  2 ++
 5 files changed, 37 insertions(+)

diff --git a/sys/riscv/include/pte.h b/sys/riscv/include/pte.h
index 34cd2a674627..77a7817fd27e 100644
--- a/sys/riscv/include/pte.h
+++ b/sys/riscv/include/pte.h
@@ -102,6 +102,32 @@ typedef	uint64_t	pn_t;			/* page number */
 #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	(0x1ful << PTE_THEAD_MA_SHIFT)
+#define	PTE_THEAD_MA_NC		(0x6ul  << PTE_THEAD_MA_SHIFT)
+#define	PTE_THEAD_MA_NONE	(0xeul  << PTE_THEAD_MA_SHIFT)
+#define	PTE_THEAD_MA_IO		(0x12ul << PTE_THEAD_MA_SHIFT)
+
 /* Bits 63 - 54 are reserved for future use. */
 #define PTE_HI_MASK	0xFFC0000000000000ULL
 
diff --git a/sys/riscv/include/thead.h b/sys/riscv/include/thead.h
index e11d5c37374c..7d845f6660e8 100644
--- a/sys/riscv/include/thead.h
+++ b/sys/riscv/include/thead.h
@@ -30,6 +30,8 @@
 #ifndef _RISCV_THEAD_H_
 #define	_RISCV_THEAD_H_
 
+extern bool has_errata_thead_pbmt;
+
 void thead_setup_cache(void);
 
 #endif /* _RISCV_THEAD_H_ */
diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c
index f85aed88d3b9..e02907092b56 100644
--- a/sys/riscv/riscv/identcpu.c
+++ b/sys/riscv/riscv/identcpu.c
@@ -470,6 +470,7 @@ handle_thead_quirks(u_int cpu, struct cpu_desc *desc)
 	if (cpu != 0)
 		return;
 
+	has_errata_thead_pbmt = true;
 	thead_setup_cache();
 }
 
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index e11adba0d832..c8a69f9674e9 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -156,6 +156,7 @@
 #include <machine/md_var.h>
 #include <machine/pcb.h>
 #include <machine/sbi.h>
+#include <machine/thead.h>
 
 /*
  * Boundary values for the page table page index space:
@@ -867,6 +868,11 @@ pmap_bootstrap(vm_paddr_t kernstart, vm_size_t kernlen)
 		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. */
diff --git a/sys/riscv/thead/thead.c b/sys/riscv/thead/thead.c
index f959d32cfed8..c72f4f1312e0 100644
--- a/sys/riscv/thead/thead.c
+++ b/sys/riscv/thead/thead.c
@@ -32,6 +32,8 @@
 
 #include <machine/thead.h>
 
+bool has_errata_thead_pbmt = false;
+
 /* ----------------- dcache ops --------------------- */