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

Reply via email to