git: 9faeaac936ae - main - powerpc/pmap: Use variable-sized TID
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 21 Jun 2026 22:07:04 UTC
The branch main has been updated by jhibbits:
URL: https://cgit.FreeBSD.org/src/commit/?id=9faeaac936aea78f9b5ce1a8ad3d27e2632d4e37
commit 9faeaac936aea78f9b5ce1a8ad3d27e2632d4e37
Author: Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2025-12-17 03:20:55 +0000
Commit: Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2026-06-21 21:24:03 +0000
powerpc/pmap: Use variable-sized TID
e6500 core supports 14-bit TIDs (16384), while all earlier cores support
only 8 bit TIDs. Dynamically allocate the tidbusy array at bootstrap
time so that it stays in the TLB1, but is sized appropriately for the
core. With MAXCPU of 32, a e6500 tidbusy would be (8 * 32 * 16384), or
4MB for this array, while e5500 would use (8 * 32 * 256), or 64kB.
---
sys/powerpc/booke/pmap.c | 52 ++++++++++++++++++++++++++++++++++++++++-------
sys/powerpc/include/spr.h | 2 ++
2 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 625d57940c01..310d38d5c450 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -87,6 +87,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/kerneldump.h>
+#include <sys/limits.h>
#include <sys/linker.h>
#include <sys/msgbuf.h>
#include <sys/lock.h>
@@ -204,8 +205,10 @@ extern int elf32_nxstack;
/* TLB and TID handling */
/**************************************************************************/
-/* Translation ID busy table */
-static volatile pmap_t tidbusy[MAXCPU][TID_MAX + 1];
+/* Translation ID busy table (dynamically allocated) */
+static __inline void tid_set_busy(int cpu, int tid, pmap_t pmap);
+static volatile pmap_t *tidbusy;
+uint32_t tid_max;
/*
* TLB0 capabilities (entry, way numbers etc.). These can vary between e500
@@ -637,6 +640,7 @@ mmu_booke_bootstrap(vm_offset_t start, vm_offset_t kernelend)
vm_size_t kstack0_sz;
vm_paddr_t kstack0_phys;
vm_offset_t kstack0;
+ uint32_t tid_bits;
void *dpcpu;
debugf("mmu_booke_bootstrap: entered\n");
@@ -660,6 +664,18 @@ mmu_booke_bootstrap(vm_offset_t start, vm_offset_t kernelend)
/* Read TLB0 size and associativity. */
tlb0_get_tlbconf();
+ /*
+ * Calculate the max TID from the hardware. Allow overriding with a
+ * tunable. The tunable should be a power of 2.
+ */
+ tid_bits = ((mfspr(SPR_MMUCFG) & MMUCFG_PIDSIZE_M) >> MMUCFG_PIDSIZE_S);
+ TUNABLE_INT_FETCH("machdep.tid_max", &tid_max);
+ if (tid_max <= 0)
+ tid_max = INT_MAX;
+ else
+ tid_max = 1 << ilog2(tid_max);
+ tid_max = min((1 << tid_bits), tid_max) - 1;
+
/*
* Align kernel start and end address (kernel image).
* Note that kernel end does not necessarily relate to kernsize.
@@ -668,6 +684,11 @@ mmu_booke_bootstrap(vm_offset_t start, vm_offset_t kernelend)
data_start = round_page(kernelend);
data_end = data_start;
+ tidbusy = (void *)data_end;
+ printf("tidbusy at %p\n", tidbusy);
+ printf("tidmax = %d\n", tid_max);
+ data_end += round_page(sizeof(pmap_t) * MAXCPU * (tid_max + 1));
+
/* Allocate the dynamic per-cpu area. */
dpcpu = (void *)data_end;
data_end += DPCPU_SIZE;
@@ -913,7 +934,7 @@ mmu_booke_bootstrap(vm_offset_t start, vm_offset_t kernelend)
kernel_pmap->pm_tid[i] = TID_KERNEL;
/* Initialize each CPU's tidbusy entry 0 with kernel_pmap */
- tidbusy[i][TID_KERNEL] = kernel_pmap;
+ tid_set_busy(i, TID_KERNEL, kernel_pmap);
}
/* Mark kernel_pmap active on all CPUs */
@@ -2460,6 +2481,22 @@ mmu_booke_page_array_startup(long pages)
/* TID handling */
/**************************************************************************/
+static __inline void
+tid_set_busy(int cpu, int tid, pmap_t pmap)
+{
+ tidbusy[cpu * (tid_max + 1) + tid] = pmap;
+ if (pmap == NULL)
+ pmap->pm_tid[cpu] = TID_NONE;
+ else
+ pmap->pm_tid[cpu] = tid;
+}
+
+static __inline pmap_t
+tid_get_busy(int cpu, int tid)
+{
+ return (tidbusy[cpu * (tid_max + 1) + tid]);
+}
+
/*
* Allocate a TID. If necessary, steal one from someone else.
* The new TID is flushed from the TLB before returning.
@@ -2477,21 +2514,22 @@ tid_alloc(pmap_t pmap)
thiscpu = PCPU_GET(cpuid);
tid = PCPU_GET(booke.tid_next);
- if (tid > TID_MAX)
+ /* tid_max is always a power-of-2-minus-1, so check for overflow. */
+ if ((tid & ~tid_max) != 0)
tid = TID_MIN;
PCPU_SET(booke.tid_next, tid + 1);
/* If we are stealing TID then clear the relevant pmap's field */
- if (tidbusy[thiscpu][tid] != NULL) {
+ if (tid_get_busy(thiscpu, tid) != NULL) {
CTR2(KTR_PMAP, "%s: warning: stealing tid %d", __func__, tid);
- tidbusy[thiscpu][tid]->pm_tid[thiscpu] = TID_NONE;
+ tid_set_busy(thiscpu, tid, NULL);
/* Flush all entries from TLB0 matching this TID. */
tid_flush(tid);
}
- tidbusy[thiscpu][tid] = pmap;
+ tid_set_busy(thiscpu, tid, pmap);
pmap->pm_tid[thiscpu] = tid;
__asm __volatile("msync; isync");
diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h
index afa1692bed75..40911a7c293d 100644
--- a/sys/powerpc/include/spr.h
+++ b/sys/powerpc/include/spr.h
@@ -868,6 +868,8 @@
#define BUCSR_BBFI 0x00000200 /* Branch Buffer Flash Invalidate */
#define SPR_MMUCFG 0x3f7 /* ..8 MMU Configuration Register */
+#define MMUCFG_LPIDSIZE_M 0x0F000000
+#define MMUCFG_LPIDSIZE_S 24
#define MMUCFG_PIDSIZE_M 0x000007c0
#define MMUCFG_PIDSIZE_S 6
#define MMUCFG_MAVN_M 0x00000003