git: 7fba91f52d17 - stable/13 - Split out creating the arm64 L2 dmap entries

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 04 Apr 2022 11:06:04 UTC
The branch stable/13 has been updated by andrew:

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

commit 7fba91f52d17e11c4f01a5688dc52dcc86580f0c
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2022-03-10 18:00:40 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2022-04-04 09:37:06 +0000

    Split out creating the arm64 L2 dmap entries
    
    When creating the DMAP region we may need to create level 2 page table
    entries at the start and end of a block of memory. The code to do this
    was almost identical so we can merge into a single function.
    
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit ba3b60200191399c3c128e9acee47b5254514822)
---
 sys/arm64/arm64/pmap.c | 113 +++++++++++++++++++++++--------------------------
 1 file changed, 54 insertions(+), 59 deletions(-)

diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index a7e5cb9186ca..0129457874e2 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -761,14 +761,62 @@ pmap_early_vtophys(vm_offset_t va)
 	return (pa_page | (va & PAR_LOW_MASK));
 }
 
+static vm_offset_t
+pmap_bootstrap_dmap_l2(vm_offset_t *va, vm_paddr_t *pa, u_int *prev_l1_slot,
+    pt_entry_t **l2p, int i, vm_offset_t freemempos)
+{
+	pt_entry_t *l2;
+	vm_paddr_t l2_pa;
+	u_int l1_slot, l2_slot;
+	bool first;
+
+	l2 = *l2p;
+	l1_slot = ((*va - DMAP_MIN_ADDRESS) >> L1_SHIFT);
+	if (l1_slot != *prev_l1_slot) {
+		*prev_l1_slot = l1_slot;
+		l2 = (pt_entry_t *)freemempos;
+		l2_pa = pmap_early_vtophys((vm_offset_t)l2);
+		freemempos += PAGE_SIZE;
+
+		pmap_store(&pagetable_dmap[l1_slot],
+		    (l2_pa & ~Ln_TABLE_MASK) |
+		    TATTR_PXN_TABLE | L1_TABLE);
+
+		memset(l2, 0, PAGE_SIZE);
+	}
+	KASSERT(l2 != NULL,
+	    ("pmap_bootstrap_dmap_l2: NULL l2 map"));
+	for (first = true; *va < DMAP_MAX_ADDRESS && *pa < physmap[i + 1];
+	    *pa += L2_SIZE, *va += L2_SIZE) {
+		/*
+		 * Stop if we are about to walk off the end of what the
+		 * current L1 slot can address.
+		 */
+		if (!first && (*pa & L1_OFFSET) == 0)
+			break;
+
+		first = false;
+		l2_slot = pmap_l2_index(*va);
+		pmap_store(&l2[l2_slot],
+		    (*pa & ~L2_OFFSET) | ATTR_DEFAULT |
+		    ATTR_S1_XN |
+		    ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) |
+		    L2_BLOCK);
+	}
+	MPASS(*va == (*pa - dmap_phys_base + DMAP_MIN_ADDRESS));
+	*l2p = l2;
+
+	return (freemempos);
+}
+
 static vm_offset_t
 pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa,
     vm_offset_t freemempos)
 {
 	pt_entry_t *l2;
 	vm_offset_t va;
-	vm_paddr_t l2_pa, pa;
-	u_int l1_slot, l2_slot, prev_l1_slot;
+	vm_paddr_t pa;
+	u_int l1_slot, prev_l1_slot;
 	int i;
 
 	dmap_phys_base = min_pa & ~L1_OFFSET;
@@ -786,40 +834,8 @@ pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa,
 
 		/* Create L2 mappings at the start of the region */
 		if ((pa & L1_OFFSET) != 0) {
-			l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT);
-			if (l1_slot != prev_l1_slot) {
-				prev_l1_slot = l1_slot;
-				l2 = (pt_entry_t *)freemempos;
-				l2_pa = pmap_early_vtophys((vm_offset_t)l2);
-				freemempos += PAGE_SIZE;
-
-				pmap_store(&pagetable_dmap[l1_slot],
-				    (l2_pa & ~Ln_TABLE_MASK) |
-				    TATTR_PXN_TABLE | L1_TABLE);
-
-				memset(l2, 0, PAGE_SIZE);
-			}
-			KASSERT(l2 != NULL,
-			    ("pmap_bootstrap_dmap: NULL l2 map"));
-			for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1];
-			    pa += L2_SIZE, va += L2_SIZE) {
-				/*
-				 * We are on a boundary, stop to
-				 * create a level 1 block
-				 */
-				if ((pa & L1_OFFSET) == 0)
-					break;
-
-				l2_slot = pmap_l2_index(va);
-				KASSERT(l2_slot != 0, ("..."));
-				pmap_store(&l2[l2_slot],
-				    (pa & ~L2_OFFSET) | ATTR_DEFAULT |
-				    ATTR_S1_XN |
-				    ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) |
-				    L2_BLOCK);
-			}
-			KASSERT(va == (pa - dmap_phys_base + DMAP_MIN_ADDRESS),
-			    ("..."));
+			freemempos = pmap_bootstrap_dmap_l2(&va, &pa,
+			    &prev_l1_slot, &l2, i, freemempos);
 		}
 
 		for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1] &&
@@ -833,29 +849,8 @@ pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa,
 
 		/* Create L2 mappings at the end of the region */
 		if (pa < physmap[i + 1]) {
-			l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT);
-			if (l1_slot != prev_l1_slot) {
-				prev_l1_slot = l1_slot;
-				l2 = (pt_entry_t *)freemempos;
-				l2_pa = pmap_early_vtophys((vm_offset_t)l2);
-				freemempos += PAGE_SIZE;
-
-				pmap_store(&pagetable_dmap[l1_slot],
-				    (l2_pa & ~Ln_TABLE_MASK) | L1_TABLE);
-
-				memset(l2, 0, PAGE_SIZE);
-			}
-			KASSERT(l2 != NULL,
-			    ("pmap_bootstrap_dmap: NULL l2 map"));
-			for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1];
-			    pa += L2_SIZE, va += L2_SIZE) {
-				l2_slot = pmap_l2_index(va);
-				pmap_store(&l2[l2_slot],
-				    (pa & ~L2_OFFSET) | ATTR_DEFAULT |
-				    ATTR_S1_XN |
-				    ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) |
-				    L2_BLOCK);
-			}
+			freemempos = pmap_bootstrap_dmap_l2(&va, &pa,
+			    &prev_l1_slot, &l2, i, freemempos);
 		}
 
 		if (pa > dmap_phys_max) {