The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=9faeaac936aea78f9b5ce1a8ad3d27e2632d4e37
commit 9faeaac936aea78f9b5ce1a8ad3d27e2632d4e37 Author: Justin Hibbits <[email protected]> AuthorDate: 2025-12-17 03:20:55 +0000 Commit: Justin Hibbits <[email protected]> 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
