git: d8f9d3388f5d - main - powerpc/pmap(booke): Allocate 64-bit roots from DMAP
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 05 Sep 2026 04:15:18 UTC
The branch main has been updated by jhibbits:
URL: https://cgit.FreeBSD.org/src/commit/?id=d8f9d3388f5dfed0b426d11a1b985397c12010e8
commit d8f9d3388f5dfed0b426d11a1b985397c12010e8
Author: Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2026-09-04 20:44:39 +0000
Commit: Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2026-09-05 04:11:53 +0000
powerpc/pmap(booke): Allocate 64-bit roots from DMAP
When a TLB miss exception occurs the exception handler must walk the
page table from the root. When the root is allocated from KVA the TLB
miss exception may take another exception if the root page(s) aren't in
the TLB.
The 64-bit page table is modeled after the AIM radix page table, with a
64kB root "page", so 16 pages. This makes regular use of UMA
allocations unable to refer back to the DMAP, which itself is mapped in
TLB1. Now we take another page from the radix pmap driver and grab
contiguous pages from the VM system, so that we can simply refer
directly to DMAP and avoid more nested TLB misses. We can still take a
nested miss, though, because the pmap itself may be in KVA, but this
reduces the nesting.
---
sys/powerpc/booke/pmap.c | 6 +-----
sys/powerpc/booke/pmap_32.c | 4 ++++
sys/powerpc/booke/pmap_64.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 2872da55f1f2..280b7df7a6b4 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -1121,11 +1121,7 @@ mmu_booke_init(void)
/* Pre-fill pvzone with initial number of pv entries. */
uma_prealloc(pvzone, PV_ENTRY_ZONE_MIN);
- /* Create a UMA zone for page table roots. */
- ptbl_root_zone = uma_zcreate("pmap root", PMAP_ROOT_SIZE,
- NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, UMA_ZONE_VM);
-
- /* Initialize ptbl allocation. */
+ /* Initialize ptbl allocation, including the page table root zone. */
ptbl_init();
}
diff --git a/sys/powerpc/booke/pmap_32.c b/sys/powerpc/booke/pmap_32.c
index ef946194b649..6442a64bc7b0 100644
--- a/sys/powerpc/booke/pmap_32.c
+++ b/sys/powerpc/booke/pmap_32.c
@@ -165,6 +165,10 @@ ptbl_init(void)
{
int i;
+ /* Create the UMA zone for page table roots. */
+ ptbl_root_zone = uma_zcreate("pmap root", PMAP_ROOT_SIZE,
+ NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, UMA_ZONE_VM);
+
CTR3(KTR_PMAP, "%s: s (ptbl_bufs = 0x%08x size 0x%08x)", __func__,
(uint32_t)ptbl_bufs, sizeof(struct ptbl_buf) * PTBL_BUFS);
CTR3(KTR_PMAP, "%s: s (ptbl_buf_pool_vabase = 0x%08x size = 0x%08x)",
diff --git a/sys/powerpc/booke/pmap_64.c b/sys/powerpc/booke/pmap_64.c
index 3f2db07ce931..87c2c84ba83b 100644
--- a/sys/powerpc/booke/pmap_64.c
+++ b/sys/powerpc/booke/pmap_64.c
@@ -177,10 +177,55 @@ mmu_booke_alloc_page(pmap_t pmap, unsigned int idx, bool nosleep)
return (VM_PAGE_TO_DMAP(m));
}
+/*
+ * Allocate PMAP roots from the DMAP, as mmu_radix does on AIM. Since DMAP is
+ * statically mapped in TLB1, and all other PMAP pages are taken from DMAP, we
+ * can avoid all TLB misses when doing page table lookups.
+ */
+static int
+ptbl_root_import(void *arg __unused, void **store, int count,
+ int domain __unused, int flags)
+{
+ vm_page_t m;
+ int i, req;
+
+ req = VM_ALLOC_WIRED | malloc2vm_flags(flags);
+ for (i = 0; i < count; i++) {
+ m = vm_page_alloc_noobj_contig(req, PMAP_ROOT_SIZE / PAGE_SIZE,
+ 0, ~(vm_paddr_t)0, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT);
+ if (m == NULL)
+ break;
+ store[i] = VM_PAGE_TO_DMAP(m);
+ }
+ return (i);
+}
+
+static void
+ptbl_root_release(void *arg __unused, void **store, int count)
+{
+ struct spglist free;
+ vm_page_t m;
+ int i, j;
+
+ for (i = 0; i < count; i++) {
+ SLIST_INIT(&free);
+ m = DMAP_TO_VM_PAGE(store[i]);
+ for (j = PMAP_ROOT_SIZE / PAGE_SIZE - 1; j >= 0; j--) {
+ vm_page_unwire_noq(&m[j]);
+ SLIST_INSERT_HEAD(&free, &m[j], plinks.s.ss);
+ }
+ vm_page_free_pages_toq(&free, false);
+ }
+}
+
/* Initialize pool of kva ptbl buffers. */
static void
ptbl_init(void)
{
+
+ ptbl_root_zone = uma_zcache_create("pmap root", PMAP_ROOT_SIZE,
+ NULL, NULL, NULL, NULL, ptbl_root_import, ptbl_root_release,
+ NULL, UMA_ZONE_NOBUCKET);
}
/* Get a pointer to a PTE in a page table. */