From bfb1e3274b08f52d584b2ba0aeae4601d2ff69d4 Mon Sep 17 00:00:00 2001 From: jhibbits Date: Sat, 6 Jun 2020 02:40:52 +0000 Subject: [PATCH] powerpc: Add a (CPU/runtime features) flags set to pcpu struct Summary: The point of this addition is to cache CPU behavior 'features', to avoid having to recompute based on CPU, etc. The first such use case is to avoid the unnecessary manipulation of the SLBs (Segment Lookaside Buffers) when using the Radix pmap on POWER9. Since we already get the PCPU pointer wherever we swap the SLB entries, we can use a cached flag to check if it's necessary to perform the operation anyway, and skip it when not. Reviewed by: bdragon Differential Revision: https://reviews.freebsd.org/D24908 --- sys/powerpc/aim/mmu_radix.c | 1 + sys/powerpc/aim/trap_subr64.S | 7 +++++++ sys/powerpc/include/pcpu.h | 4 ++++ sys/powerpc/powerpc/db_interface.c | 1 + sys/powerpc/powerpc/genassym.c | 2 ++ sys/powerpc/powerpc/mp_machdep.c | 1 + 6 files changed, 16 insertions(+) diff --git a/sys/powerpc/aim/mmu_radix.c b/sys/powerpc/aim/mmu_radix.c index 4607911086de..b7c02d9b4b16 100644 --- a/sys/powerpc/aim/mmu_radix.c +++ b/sys/powerpc/aim/mmu_radix.c @@ -2327,6 +2327,7 @@ mmu_radix_bootstrap(vm_offset_t start, vm_offset_t end) printf("%s done\n", __func__); pmap_bootstrapped = 1; dmaplimit = roundup2(powerpc_ptob(Maxmem), L2_PAGE_SIZE); + PCPU_SET(flags, PCPU_GET(flags) | PC_FLAG_NOSRS); } static void diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index 827cffb56429..986d319bd74b 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -87,6 +87,9 @@ restore_usersrs: */ restore_kernsrs: GET_CPUINFO(%r28) + lwz %r29, PC_FLAGS(%r28) + mtcr %r29 + btlr 0 addi %r28,%r28,PC_KERNSLB ld %r29,16(%r28) /* One past USER_SLB_SLOT */ cmpdi %r29,0 @@ -270,9 +273,13 @@ restore_kernsrs: std %r29,(savearea+CPUSAVE_R29)(%r3); \ std %r30,(savearea+CPUSAVE_R30)(%r3); \ std %r31,(savearea+CPUSAVE_R31)(%r3); \ + lwz %r28,PC_FLAGS(%r3); \ + mtcr %r28; \ + bt 0, 0f; /* Check to skip restoring SRs. */ \ mflr %r27; /* preserve LR */ \ bl restore_usersrs; /* uses r28-r31 */ \ mtlr %r27; \ +0: \ ld %r31,(savearea+CPUSAVE_R31)(%r3); \ ld %r30,(savearea+CPUSAVE_R30)(%r3); \ ld %r29,(savearea+CPUSAVE_R29)(%r3); \ diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h index 76829ea50df0..31c4b2c47c70 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -50,6 +50,7 @@ struct pvo_entry; int pc_bsp; \ volatile int pc_awake; \ uint32_t pc_ipimask; \ + uint32_t pc_flags; /* cpu feature flags */ \ register_t pc_tempsave[CPUSAVE_LEN]; \ register_t pc_disisave[CPUSAVE_LEN]; \ register_t pc_dbsave[CPUSAVE_LEN]; \ @@ -77,6 +78,9 @@ struct pvo_entry; #define PCPU_MD_AIM_FIELDS PCPU_MD_AIM32_FIELDS #endif +/* CPU feature flags, can be used for cached flow control. */ +#define PC_FLAG_NOSRS 0x80000000 + #define BOOKE_CRITSAVE_LEN (CPUSAVE_LEN + 2) #define BOOKE_TLB_MAXNEST 4 #define BOOKE_TLB_SAVELEN 16 diff --git a/sys/powerpc/powerpc/db_interface.c b/sys/powerpc/powerpc/db_interface.c index c16b25849899..d465b6408c9f 100644 --- a/sys/powerpc/powerpc/db_interface.c +++ b/sys/powerpc/powerpc/db_interface.c @@ -91,4 +91,5 @@ db_show_mdpcpu(struct pcpu *pc) db_printf("PPC: hwref = %#zx\n", pc->pc_hwref); db_printf("PPC: ipimask = %#x\n", pc->pc_ipimask); + db_printf("PPC: flags = %#x\n", pc->pc_flags); } diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c index cffae30ad3d0..f25783ee3145 100644 --- a/sys/powerpc/powerpc/genassym.c +++ b/sys/powerpc/powerpc/genassym.c @@ -64,6 +64,7 @@ ASSYM(PC_TEMPSAVE, offsetof(struct pcpu, pc_tempsave)); ASSYM(PC_DISISAVE, offsetof(struct pcpu, pc_disisave)); ASSYM(PC_DBSAVE, offsetof(struct pcpu, pc_dbsave)); ASSYM(PC_RESTORE, offsetof(struct pcpu, pc_restore)); +ASSYM(PC_FLAGS, offsetof(struct pcpu, pc_flags)); #if defined(BOOKE) ASSYM(PC_BOOKE_CRITSAVE, offsetof(struct pcpu, pc_booke.critsave)); @@ -106,6 +107,7 @@ ASSYM(TLBSAVE_BOOKE_R31, TLBSAVE_BOOKE_R31*sizeof(register_t)); ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); +ASSYM(PC_FLAG_NOSRS, PC_FLAG_NOSRS); #if defined(AIM) ASSYM(USER_ADDR, USER_ADDR); #ifdef __powerpc64__ diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 6c2d1b60b60e..68fd7063b283 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -246,6 +246,7 @@ cpu_mp_unleash(void *dummy) printf("Waking up CPU %d (dev=%x)\n", pc->pc_cpuid, (int)pc->pc_hwref); + pc->pc_flags = PCPU_GET(flags); /* Copy cached CPU flags */ ret = platform_smp_start_cpu(pc); if (ret == 0) { timeout = 2000; /* wait 2sec for the AP */