git: 709db7b67f1d - stable/13 - riscv: Add various pmap definitions needed to support SV48 mode

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 14 Mar 2022 14:46:08 UTC
The branch stable/13 has been updated by markj:

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

commit 709db7b67f1d2f96b15bf33d57ce37633792d6f3
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-03-01 14:04:01 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-03-14 14:45:32 +0000

    riscv: Add various pmap definitions needed to support SV48 mode
    
    No functional change intended.
    
    Reviewed by:    jhb
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 59f192c507c49990b603f774bbb824fab71ee4c3)
---
 sys/riscv/include/pmap.h    |  7 +++++++
 sys/riscv/include/pte.h     | 10 ++++++----
 sys/riscv/include/vmparam.h | 12 ++++++++----
 sys/riscv/riscv/pmap.c      | 18 +++++++++++++++++-
 4 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/sys/riscv/include/pmap.h b/sys/riscv/include/pmap.h
index 40f99befade1..8ba46f0d61ae 100644
--- a/sys/riscv/include/pmap.h
+++ b/sys/riscv/include/pmap.h
@@ -137,6 +137,13 @@ extern vm_offset_t virtual_end;
 #define	L1_MAPPABLE_P(va, pa, size)					\
 	((((va) | (pa)) & L1_OFFSET) == 0 && (size) >= L1_SIZE)
 
+enum pmap_mode {
+	PMAP_MODE_SV39,
+	PMAP_MODE_SV48,
+};
+
+extern enum pmap_mode pmap_mode;
+
 struct thread;
 
 #define	pmap_vm_page_alloc_check(m)
diff --git a/sys/riscv/include/pte.h b/sys/riscv/include/pte.h
index 965faa7eea9e..f066f821cf2a 100644
--- a/sys/riscv/include/pte.h
+++ b/sys/riscv/include/pte.h
@@ -44,22 +44,24 @@ typedef	uint64_t	pt_entry_t;		/* page table entry */
 typedef	uint64_t	pn_t;			/* page number */
 #endif
 
-/* Level 0 table, 512GiB per entry */
+/* Level 0 table, 512GiB per entry, SV48 only */
 #define	L0_SHIFT	39
+#define	L0_SIZE		(1UL << L0_SHIFT)
+#define	L0_OFFSET	(L0_SIZE - 1)
 
 /* Level 1 table, 1GiB per entry */
 #define	L1_SHIFT	30
-#define	L1_SIZE 	(1 << L1_SHIFT)
+#define	L1_SIZE 	(1UL << L1_SHIFT)
 #define	L1_OFFSET 	(L1_SIZE - 1)
 
 /* Level 2 table, 2MiB per entry */
 #define	L2_SHIFT	21
-#define	L2_SIZE 	(1 << L2_SHIFT)
+#define	L2_SIZE 	(1UL << L2_SHIFT)
 #define	L2_OFFSET 	(L2_SIZE - 1)
 
 /* Level 3 table, 4KiB per entry */
 #define	L3_SHIFT	12
-#define	L3_SIZE 	(1 << L3_SHIFT)
+#define	L3_SIZE 	(1UL << L3_SHIFT)
 #define	L3_OFFSET 	(L3_SIZE - 1)
 
 #define	Ln_ENTRIES_SHIFT 9
diff --git a/sys/riscv/include/vmparam.h b/sys/riscv/include/vmparam.h
index 4ed95def2caa..d65664eff94e 100644
--- a/sys/riscv/include/vmparam.h
+++ b/sys/riscv/include/vmparam.h
@@ -180,8 +180,10 @@
 	((va) - DMAP_MIN_ADDRESS) + dmap_phys_base;			\
 })
 
-#define	VM_MIN_USER_ADDRESS	(0x0000000000000000UL)
-#define	VM_MAX_USER_ADDRESS	(0x0000004000000000UL)
+#define	VM_MIN_USER_ADDRESS_SV39	(0x0000000000000000UL)
+#define	VM_MAX_USER_ADDRESS_SV39	(0x0000004000000000UL)
+#define	VM_MIN_USER_ADDRESS		VM_MIN_USER_ADDRESS_SV39
+#define	VM_MAX_USER_ADDRESS		VM_MAX_USER_ADDRESS_SV39
 
 #define	VM_MINUSER_ADDRESS	(VM_MIN_USER_ADDRESS)
 #define	VM_MAXUSER_ADDRESS	(VM_MAX_USER_ADDRESS)
@@ -191,8 +193,10 @@
     (((va) < VM_MAX_USER_ADDRESS) || ((va) >= VM_MIN_KERNEL_ADDRESS))
 
 #define	KERNBASE		(VM_MIN_KERNEL_ADDRESS)
-#define	SHAREDPAGE		(VM_MAXUSER_ADDRESS - PAGE_SIZE)
-#define	USRSTACK		SHAREDPAGE
+#define	SHAREDPAGE_SV39		(VM_MAX_USER_ADDRESS_SV39 - PAGE_SIZE)
+#define	SHAREDPAGE		SHAREDPAGE_SV39
+#define	USRSTACK		SHAREDPAGE_SV39
+#define	PS_STRINGS_SV39		(USRSTACK_SV39 - sizeof(struct ps_strings))
 
 #define	VM_EARLY_DTB_ADDRESS	(VM_MAX_KERNEL_ADDRESS - (2 * L2_SIZE))
 
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index 55f0c7f4a86e..ac6b854ac3c3 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -160,7 +160,19 @@ __FBSDID("$FreeBSD$");
 #include <machine/pcb.h>
 #include <machine/sbi.h>
 
-#define	NUL1E		(Ln_ENTRIES * Ln_ENTRIES)
+/*
+ * Boundary values for the page table page index space:
+ *
+ * L3 pages: [0, NUL2E)
+ * L2 pages: [NUL2E, NUL2E + NUL1E)
+ * L1 pages: [NUL2E + NUL1E, NUL2E + NUL1E + NUL0E)
+ *
+ * Note that these ranges are used in both SV39 and SV48 mode.  In SV39 mode the
+ * ranges are not fully populated since there are at most Ln_ENTRIES^2 L3 pages
+ * in a set of page tables.
+ */
+#define	NUL0E		Ln_ENTRIES
+#define	NUL1E		(Ln_ENTRIES * NUL0E)
 #define	NUL2E		(Ln_ENTRIES * NUL1E)
 
 #if !defined(DIAGNOSTIC)
@@ -179,6 +191,7 @@ __FBSDID("$FreeBSD$");
 #define PV_STAT(x)	do { } while (0)
 #endif
 
+#define	pmap_l1_pindex(v)	(NUL2E + ((v) >> L1_SHIFT))
 #define	pmap_l2_pindex(v)	((v) >> L2_SHIFT)
 #define	pa_to_pvh(pa)		(&pv_table[pa_index(pa)])
 
@@ -219,6 +232,8 @@ __FBSDID("$FreeBSD$");
 LIST_HEAD(pmaplist, pmap);
 static struct pmaplist allpmaps = LIST_HEAD_INITIALIZER();
 
+enum pmap_mode __read_frequently pmap_mode = PMAP_MODE_SV39;
+
 struct pmap kernel_pmap_store;
 
 vm_offset_t virtual_avail;	/* VA of first avail page (after kernel bss) */
@@ -338,6 +353,7 @@ pagezero(void *p)
 	bzero(p, PAGE_SIZE);
 }
 
+#define	pmap_l0_index(va)	(((va) >> L0_SHIFT) & Ln_ADDR_MASK)
 #define	pmap_l1_index(va)	(((va) >> L1_SHIFT) & Ln_ADDR_MASK)
 #define	pmap_l2_index(va)	(((va) >> L2_SHIFT) & Ln_ADDR_MASK)
 #define	pmap_l3_index(va)	(((va) >> L3_SHIFT) & Ln_ADDR_MASK)