Stop idle threads on power9 in the idle task until an interrupt.

This reduces the CPU cycle wastage on power9, which is SMT4.  Any idle
thread that's spinning is simply starving working threads on the same core
of valuable resources.

This can be reduced further by taking more advantage of the PSSCR supported
states, as well as permitting state loss, as is currently done for power8.
The currently implemented stop state is the lowest latency, which may still
consume resources.
This commit is contained in:
Justin Hibbits 2018-05-27 20:24:24 +00:00
parent 6247478381
commit ce7b8e55e3
2 changed files with 29 additions and 2 deletions

View File

@ -383,6 +383,7 @@
#define SPR_MD_CAM 0x338 /* ..8 IMMU CAM entry read */
#define SPR_MD_RAM0 0x339 /* ..8 IMMU RAM entry read reg 0 */
#define SPR_MD_RAM1 0x33a /* ..8 IMMU RAM entry read reg 1 */
#define SPR_PSSCR 0x357 /* Processor Stop Status and Control Register (ISA 3.0) */
#define SPR_UMMCR2 0x3a0 /* .6. User Monitor Mode Control Register 2 */
#define SPR_UMMCR0 0x3a8 /* .6. User Monitor Mode Control Register 0 */
#define SPR_USIA 0x3ab /* .6. User Sampled Instruction Address */

View File

@ -91,6 +91,7 @@ static void cpu_idle_60x(sbintime_t);
static void cpu_idle_booke(sbintime_t);
#if defined(__powerpc64__) && defined(AIM)
static void cpu_idle_powerx(sbintime_t);
static void cpu_idle_power9(sbintime_t sbt);
#endif
struct cputab {
@ -181,7 +182,7 @@ static const struct cputab models[] = {
PPC_FEATURE2_ARCH_2_07 | PPC_FEATURE2_HTM | PPC_FEATURE2_DSCR |
PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | PPC_FEATURE2_HAS_VEC_CRYPTO |
PPC_FEATURE2_ARCH_3_00 | PPC_FEATURE2_HAS_IEEE128 |
PPC_FEATURE2_DARN, NULL },
PPC_FEATURE2_DARN, cpu_powerx_setup },
{ "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN,
PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup },
{ "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN,
@ -660,7 +661,12 @@ cpu_powerx_setup(int cpuid, uint16_t vers)
switch (vers) {
case IBMPOWER8:
case IBMPOWER8E:
cpu_idle_hook = cpu_idle_powerx;
mtspr(SPR_LPCR, mfspr(SPR_LPCR) | LPCR_PECE_WAKESET);
isync();
break;
case IBMPOWER9:
cpu_idle_hook = cpu_idle_power9;
mtspr(SPR_LPCR, mfspr(SPR_LPCR) | LPCR_PECE_WAKESET);
isync();
break;
@ -668,7 +674,6 @@ cpu_powerx_setup(int cpuid, uint16_t vers)
return;
}
cpu_idle_hook = cpu_idle_powerx;
#endif
}
@ -798,6 +803,27 @@ cpu_idle_powerx(sbintime_t sbt)
enter_idle_powerx();
spinlock_exit();
}
static void
cpu_idle_power9(sbintime_t sbt)
{
register_t msr;
msr = mfmsr();
/* Suspend external interrupts until stop instruction completes. */
mtmsr(msr & ~PSL_EE);
/* Set the stop state to lowest latency, wake up to next instruction */
mtspr(SPR_PSSCR, 0);
/* "stop" instruction (PowerISA 3.0) */
__asm __volatile (".long 0x4c0002e4");
/*
* Re-enable external interrupts to capture the interrupt that caused
* the wake up.
*/
mtmsr(msr);
}
#endif
int