aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2026-04-13 11:50:32 +0000
committerAndrew Turner <andrew@FreeBSD.org>2026-04-13 14:23:05 +0000
commitc208439cdb588d91aead9403cec3d4acf4a8bebf (patch)
tree2c38143a0e7807788da049549611198d046b7fe7
parentb0ef03f0c4bc2a7715e4b8ea4ead8dd73dffdd95 (diff)
arm64: Add a cmap page to pmap
When modifying mappings in pmap we may need to perform a break-before-make sequence. This creates an invalid mapping, then recreates it with the changes. When modifying DMAP mappings we may be changing the mapping that contains its own page table then after breaking the old entry we are unable to create the new entry. To fix this create a map that can be used & won't be affected by the break-before-make sequence. Reviewed by: kib Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D56306
-rw-r--r--sys/arm64/arm64/pmap.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 678030f827dd..7d19c927d369 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -290,6 +290,10 @@ VM_PAGE_TO_PV_LIST_LOCK(vm_page_t m)
#define PTE_TO_VM_PAGE(pte) PHYS_TO_VM_PAGE(PTE_TO_PHYS(pte))
#define VM_PAGE_TO_PTE(m) PHYS_TO_PTE(VM_PAGE_TO_PHYS(m))
+static struct mtx cmap_lock;
+static void *cmap1_addr;
+static pt_entry_t *cmap1_pte;
+
/*
* The presence of this flag indicates that the mapping is writeable.
* If the ATTR_S1_AP_RO bit is also set, then the mapping is clean, otherwise
@@ -1363,7 +1367,7 @@ pmap_bootstrap(void)
virtual_avail = preinit_map_va + PMAP_PREINIT_MAPPING_SIZE;
virtual_avail = roundup2(virtual_avail, L1_SIZE);
- virtual_end = VM_MAX_KERNEL_ADDRESS - PMAP_MAPDEV_EARLY_SIZE;
+ virtual_end = VM_MAX_KERNEL_ADDRESS - PMAP_MAPDEV_EARLY_SIZE - L2_SIZE;
kernel_vm_end = virtual_avail;
/*
@@ -1419,6 +1423,19 @@ pmap_bootstrap(void)
alloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
msgbufp = (void *)msgbufpv;
+ /* Allocate space for the CPU0 CMAP */
+ bs_state.va = virtual_end;
+ pmap_bootstrap_l2_table(&bs_state);
+ pmap_store(&bs_state.l3[pmap_l3_index(bs_state.va)],
+ PHYS_TO_PTE(pmap_early_vtophys((vm_offset_t)bs_state.l3)) |
+ ATTR_AF | pmap_sh_attr | ATTR_S1_XN | ATTR_KERN_GP |
+ ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | L3_PAGE);
+ dsb(ishst);
+
+ mtx_init(&cmap_lock, "SYSMAPS", NULL, MTX_DEF);
+ cmap1_addr = (void *)(virtual_end + L3_SIZE);
+ cmap1_pte = &bs_state.l3[pmap_l3_index((vm_offset_t)cmap1_addr)];
+
pa = pmap_early_vtophys(bs_state.freemempos);
physmem_exclude_region(start_pa, pa - start_pa, EXFLAG_NOALLOC);