one more try at idle improvements
Nicholas Piggin
reviewercover one more try at idle improvements
The recent KVM work clashed with a couple of my patches, so they were reverted/dropped for this merge window.
I've made another attempt at them, hopefully done in a way that is more compatible with KVM requirements and in a bit nicer way (POWER8 contex switching should speed up a bit too). I'm not completely sure I got patch 2 right. It works on POWER8, but haven't been able to get POWER9 running with hash on radix.
Thanks,
Nick
Nicholas Piggin (3):
powerpc/64s/idle: POWER9 implement a separate idle stop function for
hotplug
powerpc/64s/idle: avoid sync for KVM state when waking from idle powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/kernel/idle_book3s.S | 62 +++++++++++++++++------------------ arch/powerpc/platforms/powernv/idle.c | 9 +++-- 3 files changed, 38 insertions(+), 34 deletions(-)
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 1/3 powerpc/64s/idle: POWER9 implement a separate idle stop function for hotplug
Implement a new function to invoke stop, power9_offline_stop, which is like power9_idle_stop but used by the cpu hotplug code.
Move KVM secondary state manipulation code to the offline case.
--- arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/kernel/idle_book3s.S | 24 ++++++++++++++++++------ arch/powerpc/platforms/powernv/idle.c | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-)
arch/powerpc/include/asm/processor.h +1 -0
@@ -500,6 +500,7 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */extern unsigned long power7_idle_insn (unsigned long type);/* PNV_THREAD_NAP/etc*/ extern void power7_idle_type (unsigned long type);extern unsigned long power9_idle_stop (unsigned long psscr_val); +extern unsigned long power9_offline_stop (unsigned long psscr_val);extern void power9_idle_type (unsigned long stop_psscr_val,unsigned long stop_psscr_mask);
arch/powerpc/kernel/idle_book3s.S +18 -6
@@ -325,12 +325,6 @@ enter_winkle: * r3 - PSSCR value corresponding to the requested stop state. */ power_enter_stop: -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE - /* Tell KVM we're entering idle */ - li r4,KVM_HWTHREAD_IN_IDLE - /* DO THIS IN REAL MODE! See comment above. */ - stb r4,HSTATE_HWTHREAD_STATE(r13) -#endif /* * Check if we are executing the lite variant with ESL=EC=0 */
@@ -435,6 +429,24 @@ _GLOBAL(power9_idle_stop) b pnv_powersave_common /* No return */ +/* + * Entered with MSR[EE]=0 and no soft-masked interrupts pending. + * r3 contains desired PSSCR register value. + */ +_GLOBAL(power9_offline_stop) + std r3, PACA_REQ_PSSCR(r13) + mtspr SPRN_PSSCR,r3 +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + /* Tell KVM we're entering idle */ + li r4,KVM_HWTHREAD_IN_IDLE + /* DO THIS IN REAL MODE! See comment above. */ + stb r4,HSTATE_HWTHREAD_STATE(r13) +#endif + LOAD_REG_ADDR(r4,power_enter_stop) + b pnv_powersave_common + /* No return */ + + /* * On waking up from stop 0,1,2 with ESL=1 on POWER9 DD1, * HSPRG0 will be set to the HSPRG0 value of one of the
arch/powerpc/platforms/powernv/idle.c +1 -1
@@ -434,7 +434,7 @@ unsigned long pnv_cpu_offline(unsigned int cpu) psscr =mfspr (SPRN_PSSCR ); psscr = (psscr & ~pnv_deepest_stop_psscr_mask) | pnv_deepest_stop_psscr_val; - srr1 =power9_idle_stop (psscr); + srr1 =power9_offline_stop (psscr); }else if ((idle_states &OPAL_PM_WINKLE_ENABLED ) && (idle_states &OPAL_PM_LOSE_FULL_CONTEXT )) {
Signature · 1 line
2.15.0
Re: [PATCH 1/3] powerpc/64s/idle: POWER9 implement a separate idle stop function for hotplug
Quoted 6 lines · Nicholas Piggin
Implement a new function to invoke stop,
power9_offline_stop, which is likepower9_idle_stopbut used by the cpu hotplug code.Move KVM secondary state manipulation code to the offline case.
Signed-off-by Nicholas Piggin <[email protected]>
Quoted 46 lines
--- arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/kernel/idle_book3s.S | 24 ++++++++++++++++++------ arch/powerpc/platforms/powernv/idle.c | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-)arch/powerpc/include/asm/processor.h +1
-0@@ -500,6 +500,7 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */extern unsigned long power7_idle_insn (unsigned long type);/* PNV_THREAD_NAP/etc*/ extern void power7_idle_type (unsigned long type);extern unsigned long power9_idle_stop (unsigned long psscr_val); +extern unsigned long power9_offline_stop (unsigned long psscr_val);extern void power9_idle_type (unsigned long stop_psscr_val,unsigned long stop_psscr_mask);arch/powerpc/kernel/idle_book3s.S +7
-6@@ -325,12 +325,6 @@ enter_winkle: * r3 - PSSCR value corresponding to the requested stop state. */ power_enter_stop: -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE - /* Tell KVM we're entering idle */ - li r4,KVM_HWTHREAD_IN_IDLE - /* DO THIS IN REAL MODE! See comment above. */ - stb r4,HSTATE_HWTHREAD_STATE(r13) -#endif /* * Check if we are executing the lite variant with ESL=EC=0 */@@ -435,6 +429,24 @@ _GLOBAL(power9_idle_stop) b pnv_powersave_common /* No return */ +/* + * Entered with MSR[EE]=0 and no soft-masked interrupts pending. + * r3 contains desired PSSCR register value. + */ +_GLOBAL(power9_offline_stop) + std r3, PACA_REQ_PSSCR(r13) + mtspr SPRN_PSSCR,r3
arch/powerpc/kernel/idle_book3s.S _GLOBAL(power9_idle_stop) · line 448
Quoted 10 lines
arch/powerpc/kernel/idle_book3s.S +10
-0+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + /* Tell KVM we're entering idle */ + li r4,KVM_HWTHREAD_IN_IDLE + /* DO THIS IN REAL MODE! See comment above. */ + stb r4,HSTATE_HWTHREAD_STATE(r13) +#endif + LOAD_REG_ADDR(r4,power_enter_stop) + b pnv_powersave_common + /* No return */ +
Good optimization. This code is needed only when an offline thread is wokenup at 0x100 to get into guest. Can be skipped in idle wakeup case.
Quoted 20 lines
arch/powerpc/kernel/idle_book3s.S +1
-0+ /* * On waking up from stop 0,1,2 with ESL=1 on POWER9 DD1, * HSPRG0 will be set to the HSPRG0 value of one of thearch/powerpc/platforms/powernv/idle.c +1
-1@@ -434,7 +434,7 @@ unsigned long pnv_cpu_offline(unsigned int cpu) psscr =mfspr (SPRN_PSSCR ); psscr = (psscr & ~pnv_deepest_stop_psscr_mask) | pnv_deepest_stop_psscr_val; - srr1 =power9_idle_stop (psscr); + srr1 =power9_offline_stop (psscr); }else if ((idle_states &OPAL_PM_WINKLE_ENABLED ) && (idle_states &OPAL_PM_LOSE_FULL_CONTEXT )) {Signature · 1 line
2.15.0
Michael Ellerman
AppliedRe: [1/3] powerpc/64s/idle: POWER9 implement a separate idle stop function for hotplug
In reply to Nicholas PigginQuoted 7 lines · Nicholas Piggin
Implement a new function to invoke stop,
power9_offline_stop, which is likepower9_idle_stopbut used by the cpu hotplug code.Move KVM secondary state manipulation code to the offline case.
Signed-off-by Nicholas Piggin <[email protected]>Reviewed-by Vaidyanathan Srinivasan <[email protected]>
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/3d4fbffdd703d2b968db443911f214
cheers
Nicholas Piggin
reviewerRe: [1/3] powerpc/64s/idle: POWER9 implement a separate idle stop function for hotplug
Quoted 6 lines · On Wed, 4 Apr 2018 02:03:18 +1000 (AEST) Michael Ellerman…
Quoted 5 lines · Nicholas Piggin
Implement a new function to invoke stop,
power9_offline_stop, which is likepower9_idle_stopbut used by the cpu hotplug code.Move KVM secondary state manipulation code to the offline case.
Quoted 8 lines
Quoted 2 lines
Signed-off-by Nicholas Piggin <[email protected]>Reviewed-by Vaidyanathan Srinivasan <[email protected]>Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/3d4fbffdd703d2b968db443911f214
cheers
I sent out a new series for this which is rebased and a bit cleaner. I probably wasn't clear enough about the change, sorry.
This patch will need to be adjusted for the force SMT4 change. The end result should look like this,
https://patchwork.ozlabs.org/patch/893948/
Thanks,
Nick
Michael Ellerman
reviewerRe: [1/3] powerpc/64s/idle: POWER9 implement a separate idle stop function for hotplug
Quoted 11 lines · Nicholas Piggin
Quoted 9 lines · On Wed, 4 Apr 2018 02:03:18 +1000 (AEST) Michael Ellerman…
Quoted 7 lines · Nicholas Piggin
Implement a new function to invoke stop,
power9_offline_stop, which is likepower9_idle_stopbut used by the cpu hotplug code.Move KVM secondary state manipulation code to the offline case.
Signed-off-by Nicholas Piggin <[email protected]>Reviewed-by Vaidyanathan Srinivasan <[email protected]>
Quoted 6 lines
Quoted 3 lines
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/3d4fbffdd703d2b968db443911f214
I sent out a new series for this which is rebased and a bit cleaner. I probably wasn't clear enough about the change, sorry.
No that's OK, I just already had the previous series applied (partially) in my testing tree and didn't see the new series in time to back it out.
Quoted 4 lines
This patch will need to be adjusted for the force SMT4 change. The end result should look like this,
Thanks. I did a patch to get everything in sync, and confirmed the result is the same as applying your new series.
cheers
Nicholas Piggin
reviewerPATCH 2/3 powerpc/64s/idle: avoid sync for KVM state when waking from idle
In reply to Nicholas PigginWhen waking from a CPU idle instruction (e.g., nap or stop), the sync for ordering the KVM secondary thread state can be avoided if there wakeup is coming from a kernel context rather than KVM context.
This improves performance for ping-pong benchmark with the stop0 idle state by 0.46% for 2 threads in the same core, and 1.02% for different cores.
--- arch/powerpc/kernel/idle_book3s.S | 3 +++ 1 file changed, 3 insertions(+)
arch/powerpc/kernel/idle_book3s.S +3 -0
@@ -532,6 +532,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) mr r3,r12 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + lbz r0,HSTATE_HWTHREAD_STATE(r13) + cmpwi r0,KVM_HWTHREAD_IN_KERNEL + beq 1f li r0,KVM_HWTHREAD_IN_KERNEL stb r0,HSTATE_HWTHREAD_STATE(r13) /* Order setting hwthread_state vs. testing hwthread_req */
Signature · 1 line
2.15.0
Re: [PATCH 2/3] powerpc/64s/idle: avoid sync for KVM state when waking from idle
Quoted 7 lines · Nicholas Piggin
When waking from a CPU idle instruction (e.g., nap or stop), the sync for ordering the KVM secondary thread state can be avoided if there wakeup is coming from a kernel context rather than KVM context.
This improves performance for ping-pong benchmark with the stop0 idle state by 0.46% for 2 threads in the same core, and 1.02% for different cores.
Cool, the improvement comes from avoiding the "sync" alone?
Quoted 10 lines
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/kernel/idle_book3s.S | 3 +++ 1 file changed, 3 insertions(+)arch/powerpc/kernel/idle_book3s.S +0
-0
arch/powerpc/kernel/idle_book3s.S ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) · line 540
Quoted 9 lines
arch/powerpc/kernel/idle_book3s.S +3
-0@@ -532,6 +532,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) mr r3,r12 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + lbz r0,HSTATE_HWTHREAD_STATE(r13) + cmpwi r0,KVM_HWTHREAD_IN_KERNEL + beq 1f li r0,KVM_HWTHREAD_IN_KERNEL stb r0,HSTATE_HWTHREAD_STATE(r13) /* Order setting hwthread_state vs. testing hwthread_req */
With this change, we will not check for HSTATE_HWTHREAD_REQ != 0 condition but unconditionally goto host kernel if HSTATE_HWTHREAD_STATE == KVM_HWTHREAD_IN_KERNEL at wakeup.
Host is in ST mode and sibling thread got a wakeup event (door bell) to execute a new vcpu by calling kvm_start_guest, what will HSTATE_HWTHREAD_STATE be?
Just to clarify, what will the flags looks like for
(a) Host cpu sibling thread is offline and need to execute guest
(b) Host cpu sibling thread is idle and need to execute guest
--Vaidy
Nicholas Piggin
reviewerRe: [PATCH 2/3] powerpc/64s/idle: avoid sync for KVM state when waking from idle
Quoted 11 lines · On Wed, 28 Feb 2018 23:46:23 +0530 Vaidyanathan Srinivasan…
Quoted 7 lines · Nicholas Piggin
When waking from a CPU idle instruction (e.g., nap or stop), the sync for ordering the KVM secondary thread state can be avoided if there wakeup is coming from a kernel context rather than KVM context.
This improves performance for ping-pong benchmark with the stop0 idle state by 0.46% for 2 threads in the same core, and 1.02% for different cores.
Cool, the improvement comes from avoiding the "sync" alone?
Yes, they can be pretty costly.
Quoted 13 lines
Quoted 13 lines
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/kernel/idle_book3s.S | 3 +++ 1 file changed, 3 insertions(+)arch/powerpc/kernel/idle_book3s.S +0
-0@@ -532,6 +532,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) mr r3,r12
Quoted 11 lines
arch/powerpc/kernel/idle_book3s.S ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) · line 540
Quoted 7 lines
arch/powerpc/kernel/idle_book3s.S +3
-0#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + lbz r0,HSTATE_HWTHREAD_STATE(r13) + cmpwi r0,KVM_HWTHREAD_IN_KERNEL + beq 1f li r0,KVM_HWTHREAD_IN_KERNEL stb r0,HSTATE_HWTHREAD_STATE(r13) /* Order setting hwthread_state vs. testing hwthread_req */With this change, we will not check for
HSTATE_HWTHREAD_REQ!= 0 condition but unconditionally goto host kernel ifHSTATE_HWTHREAD_STATE==KVM_HWTHREAD_IN_KERNELat wakeup.
That's right.
Quoted 2 lines
Host is in ST mode and sibling thread got a wakeup event (door bell) to execute a new vcpu by calling
kvm_start_guest, what willHSTATE_HWTHREAD_STATEbe?
It should be KVM_HWTHREAD_IN_IDLE.
Quoted 4 lines
Just to clarify, what will the flags looks like for
(a) Host cpu sibling thread is offline and need to execute guest
(b) Host cpu sibling thread is idle and need to execute guest
In the idle case we are running with independent threads mode and siblings not unplugged, so we should not get KVM wake-up requests come through this path. I'm not fluent in KVM though, so I could be wrong.
Thanks,
Nick
Michael Ellerman
AppliedRe: [2/3] powerpc/64s/idle: avoid sync for KVM state when waking from idle
In reply to Nicholas PigginQuoted 9 lines · Nicholas Piggin
When waking from a CPU idle instruction (e.g., nap or stop), the sync for ordering the KVM secondary thread state can be avoided if there wakeup is coming from a kernel context rather than KVM context.
This improves performance for ping-pong benchmark with the stop0 idle state by 0.46% for 2 threads in the same core, and 1.02% for different cores.
Signed-off-by Nicholas Piggin <[email protected]>
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/8c1c7fb0b5ec95c392e9b585a6cf8c
cheers
Nicholas Piggin
reviewerPATCH 3/3 powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
In reply to Nicholas PigginWhen stop is executed with EC=ESL=0, it appears to execute like a normal instruction (resuming from NIP when woken by interrupt). So all the save/restore handling can be avoided completely. In particular NV GPRs do not have to be saved, and MSR does not have to be switched back to kernel MSR.
So move the test for EC=ESL=0 sleep states out to power9_idle_stop, and return directly to the caller after stop in that case. The mtspr to PSSCR is moved to the top of power9_offline_stop just so it matches power9_idle_stop.
This improves performance for ping-pong benchmark with the stop0_lite idle state by 2.54% for 2 threads in the same core, and 2.57% for different cores.
--- arch/powerpc/kernel/idle_book3s.S | 43 +++++++++++------------------------ arch/powerpc/platforms/powernv/idle.c | 7 +++++- 2 files changed, 19 insertions(+), 31 deletions(-)
arch/powerpc/kernel/idle_book3s.S +13 -30
@@ -324,31 +324,8 @@ enter_winkle: /* * r3 - PSSCR value corresponding to the requested stop state. */ -power_enter_stop: -/* - * Check if we are executing the lite variant with ESL=EC=0 - */ - andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED +power_enter_stop_esl: clrldi r3,r3,60 /* r3 = Bits[60:63] = Requested Level (RL) */ - bne .Lhandle_esl_ec_set - PPC_STOP - li r3,0 /* Since we didn't lose state, return 0 */ - - /* - * pnv_wakeup_noloss() expects r12 to contain the SRR1 value so - * it can determine if the wakeup reason is an HMI in - * CHECK_HMI_INTERRUPT. - * - * However, when we wakeup with ESL=0, SRR1 will not contain the wakeup - * reason, so there is no point setting r12 to SRR1. - * - * Further, we clear r12 here, so that we don't accidentally enter the - * HMI in pnv_wakeup_noloss() if the value of r12[42:45] == WAKE_HMI. - */ - li r12, 0 - b pnv_wakeup_noloss - -.Lhandle_esl_ec_set: BEGIN_FTR_SECTION /* * POWER9 DD2.0 or earlier can incorrectly set PMAO when waking up after
@@ -423,26 +400,32 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ * r3 contains desired PSSCR register value. */ _GLOBAL(power9_idle_stop) - std r3, PACA_REQ_PSSCR(r13) mtspr SPRN_PSSCR,r3 - LOAD_REG_ADDR(r4,power_enter_stop) + andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED + bne 1f + PPC_STOP + li r3,0 /* Since we didn't lose state, return 0 */ + blr + +1: std r3, PACA_REQ_PSSCR(r13) + LOAD_REG_ADDR(r4,power_enter_stop_esl) b pnv_powersave_common /* No return */ /* - * Entered with MSR[EE]=0 and no soft-masked interrupts pending. - * r3 contains desired PSSCR register value. + * This is the same as the above, but it sets KVM state for secondaries, + * and it must have PSSCR[EC]=1 */ _GLOBAL(power9_offline_stop) - std r3, PACA_REQ_PSSCR(r13) mtspr SPRN_PSSCR,r3 + std r3, PACA_REQ_PSSCR(r13) #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* Tell KVM we're entering idle */ li r4,KVM_HWTHREAD_IN_IDLE /* DO THIS IN REAL MODE! See comment above. */ stb r4,HSTATE_HWTHREAD_STATE(r13) #endif - LOAD_REG_ADDR(r4,power_enter_stop) + LOAD_REG_ADDR(r4,power_enter_stop_esl) b pnv_powersave_common /* No return */
arch/powerpc/platforms/powernv/idle.c +6 -1
@@ -621,7 +621,12 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags,continue ; } -if (max_residency_ns < residency_ns[i]) { +/* +* Deepest stop for unplug must be PSSCR[EC]=1 (wakeup at +* 0x100. +*/ +if ((max_residency_ns < residency_ns[i])&& + (psscr_val[i] &PSSCR_EC )) { max_residency_ns = residency_ns[i]; pnv_deepest_stop_psscr_val = psscr_val[i]; pnv_deepest_stop_psscr_mask = psscr_mask[i];
Signature · 1 line
2.15.0
Re: [PATCH 3/3] powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
Quoted 11 lines · Nicholas Piggin
When stop is executed with EC=ESL=0, it appears to execute like a normal instruction (resuming from NIP when woken by interrupt). So all the save/restore handling can be avoided completely. In particular NV GPRs do not have to be saved, and MSR does not have to be switched back to kernel MSR.
So move the test for EC=ESL=0 sleep states out to
power9_idle_stop, and return directly to the caller after stop in that case. The mtspr to PSSCR is moved to the top ofpower9_offline_stopjust so it matchespower9_idle_stop.
Quoted 5 lines
This improves performance for ping-pong benchmark with the
stop0_liteidle state by 2.54% for 2 threads in the same core, and 2.57% for different cores.Signed-off-by Nicholas Piggin <[email protected]>
Quoted 49 lines
--- arch/powerpc/kernel/idle_book3s.S | 43 +++++++++++------------------------ arch/powerpc/platforms/powernv/idle.c | 7 +++++- 2 files changed, 19 insertions(+), 31 deletions(-)arch/powerpc/kernel/idle_book3s.S +1
-26@@ -324,31 +324,8 @@ enter_winkle: /* * r3 - PSSCR value corresponding to the requested stop state. */ -power_enter_stop: -/* - * Check if we are executing the lite variant with ESL=EC=0 - */ - andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED +power_enter_stop_esl: clrldi r3,r3,60 /* r3 = Bits[60:63] = Requested Level (RL) */ - bne .Lhandle_esl_ec_set - PPC_STOP - li r3,0 /* Since we didn't lose state, return 0 */ - - /* - * pnv_wakeup_noloss() expects r12 to contain the SRR1 value so - * it can determine if the wakeup reason is an HMI in - * CHECK_HMI_INTERRUPT. - * - * However, when we wakeup with ESL=0, SRR1 will not contain the wakeup - * reason, so there is no point setting r12 to SRR1. - * - * Further, we clear r12 here, so that we don't accidentally enter the - * HMI in pnv_wakeup_noloss() if the value of r12[42:45] == WAKE_HMI. - */ - li r12, 0 - b pnv_wakeup_noloss - -.Lhandle_esl_ec_set: BEGIN_FTR_SECTION /* * POWER9 DD2.0 or earlier can incorrectly set PMAO when waking up after@@ -423,26 +400,32 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ * r3 contains desired PSSCR register value. */ _GLOBAL(power9_idle_stop) - std r3, PACA_REQ_PSSCR(r13) mtspr SPRN_PSSCR,r3 - LOAD_REG_ADDR(r4,power_enter_stop)
arch/powerpc/kernel/idle_book3s.S ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ · line 413
Quoted 10 lines
arch/powerpc/kernel/idle_book3s.S +8
-0+ andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED + bne 1f + PPC_STOP + li r3,0 /* Since we didn't lose state, return 0 */ + blr + +1: std r3, PACA_REQ_PSSCR(r13) + LOAD_REG_ADDR(r4,power_enter_stop_esl) b pnv_powersave_common /* No return */
Good optimization to skip the context save and directly execute stop for ESL=EC=0 case.
Quoted 29 lines
arch/powerpc/kernel/idle_book3s.S +4
-4/* - * Entered with MSR[EE]=0 and no soft-masked interrupts pending. - * r3 contains desired PSSCR register value. + * This is the same as the above, but it sets KVM state for secondaries, + * and it must have PSSCR[EC]=1 */ _GLOBAL(power9_offline_stop) - std r3, PACA_REQ_PSSCR(r13) mtspr SPRN_PSSCR,r3 + std r3, PACA_REQ_PSSCR(r13) #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* Tell KVM we're entering idle */ li r4,KVM_HWTHREAD_IN_IDLE /* DO THIS IN REAL MODE! See comment above. */ stb r4,HSTATE_HWTHREAD_STATE(r13) #endif - LOAD_REG_ADDR(r4,power_enter_stop) + LOAD_REG_ADDR(r4,power_enter_stop_esl) b pnv_powersave_common /* No return */arch/powerpc/platforms/powernv/idle.c +0
-0@@ -621,7 +621,12 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags,continue ; }
arch/powerpc/platforms/powernv/idle.c static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, · line 632
Quoted 10 lines
arch/powerpc/platforms/powernv/idle.c +6
-1-if (max_residency_ns < residency_ns[i]) { +/* +* Deepest stop for unplug must be PSSCR[EC]=1 (wakeup at +* 0x100. +*/ +if ((max_residency_ns < residency_ns[i])&& + (psscr_val[i] &PSSCR_EC )) { max_residency_ns = residency_ns[i]; pnv_deepest_stop_psscr_val = psscr_val[i]; pnv_deepest_stop_psscr_mask = psscr_mask[i];
If firmware did not provide any ESL=EC=1 state, we can still leave threads in stop ESL=0 state. This is just a corner case or random test scenario. Why do we want to enforce that offline cpus really use a ESL=0 state or just spin?
--Vaidy
Nicholas Piggin
reviewerRe: [PATCH 3/3] powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
Quoted 75 lines · On Thu, 1 Mar 2018 00:04:39 +0530 Vaidyanathan Srinivasan…
Quoted 11 lines · Nicholas Piggin
When stop is executed with EC=ESL=0, it appears to execute like a normal instruction (resuming from NIP when woken by interrupt). So all the save/restore handling can be avoided completely. In particular NV GPRs do not have to be saved, and MSR does not have to be switched back to kernel MSR.
So move the test for EC=ESL=0 sleep states out to
power9_idle_stop, and return directly to the caller after stop in that case. The mtspr to PSSCR is moved to the top ofpower9_offline_stopjust so it matchespower9_idle_stop.Quoted 5 lines
This improves performance for ping-pong benchmark with the
stop0_liteidle state by 2.54% for 2 threads in the same core, and 2.57% for different cores.Signed-off-by Nicholas Piggin <[email protected]>Reviewed-by Vaidyanathan Srinivasan <[email protected]>Quoted 54 lines
--- arch/powerpc/kernel/idle_book3s.S | 43 +++++++++++------------------------ arch/powerpc/platforms/powernv/idle.c | 7 +++++- 2 files changed, 19 insertions(+), 31 deletions(-)arch/powerpc/kernel/idle_book3s.S +6
-26@@ -324,31 +324,8 @@ enter_winkle: /* * r3 - PSSCR value corresponding to the requested stop state. */ -power_enter_stop: -/* - * Check if we are executing the lite variant with ESL=EC=0 - */ - andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED +power_enter_stop_esl: clrldi r3,r3,60 /* r3 = Bits[60:63] = Requested Level (RL) */ - bne .Lhandle_esl_ec_set - PPC_STOP - li r3,0 /* Since we didn't lose state, return 0 */ - - /* - * pnv_wakeup_noloss() expects r12 to contain the SRR1 value so - * it can determine if the wakeup reason is an HMI in - * CHECK_HMI_INTERRUPT. - * - * However, when we wakeup with ESL=0, SRR1 will not contain the wakeup - * reason, so there is no point setting r12 to SRR1. - * - * Further, we clear r12 here, so that we don't accidentally enter the - * HMI in pnv_wakeup_noloss() if the value of r12[42:45] == WAKE_HMI. - */ - li r12, 0 - b pnv_wakeup_noloss - -.Lhandle_esl_ec_set: BEGIN_FTR_SECTION /* * POWER9 DD2.0 or earlier can incorrectly set PMAO when waking up after@@ -423,26 +400,32 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ * r3 contains desired PSSCR register value. */ _GLOBAL(power9_idle_stop) - std r3, PACA_REQ_PSSCR(r13) mtspr SPRN_PSSCR,r3 - LOAD_REG_ADDR(r4,power_enter_stop) + andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED + bne 1f + PPC_STOP + li r3,0 /* Since we didn't lose state, return 0 */ + blr
Quoted 8 lines
arch/powerpc/kernel/idle_book3s.S ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ · line 413
Quoted 5 lines
arch/powerpc/kernel/idle_book3s.S +3
-0+ +1: std r3, PACA_REQ_PSSCR(r13) + LOAD_REG_ADDR(r4,power_enter_stop_esl) b pnv_powersave_common /* No return */Good optimization to skip the context save and directly execute stop for ESL=EC=0 case.
Yep we should now be getting pretty close to optimal for ESL=EC=0. About the only other thing we could do is maintain PSSCR state and only change it when going to a different idle state. May not be worth worrying about but I haven't benchmarked it.
Quoted 30 lines
Quoted 30 lines
arch/powerpc/kernel/idle_book3s.S +4
-4/* - * Entered with MSR[EE]=0 and no soft-masked interrupts pending. - * r3 contains desired PSSCR register value. + * This is the same as the above, but it sets KVM state for secondaries, + * and it must have PSSCR[EC]=1 */ _GLOBAL(power9_offline_stop) - std r3, PACA_REQ_PSSCR(r13) mtspr SPRN_PSSCR,r3 + std r3, PACA_REQ_PSSCR(r13) #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* Tell KVM we're entering idle */ li r4,KVM_HWTHREAD_IN_IDLE /* DO THIS IN REAL MODE! See comment above. */ stb r4,HSTATE_HWTHREAD_STATE(r13) #endif - LOAD_REG_ADDR(r4,power_enter_stop) + LOAD_REG_ADDR(r4,power_enter_stop_esl) b pnv_powersave_common /* No return */arch/powerpc/platforms/powernv/idle.c +0
-0@@ -621,7 +621,12 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags,continue ; }
Quoted 15 lines
arch/powerpc/platforms/powernv/idle.c static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, · line 632
Quoted 10 lines
arch/powerpc/platforms/powernv/idle.c +6
-1-if (max_residency_ns < residency_ns[i]) { +/* +* Deepest stop for unplug must be PSSCR[EC]=1 (wakeup at +* 0x100. +*/ +if ((max_residency_ns < residency_ns[i])&& + (psscr_val[i] &PSSCR_EC )) { max_residency_ns = residency_ns[i]; pnv_deepest_stop_psscr_val = psscr_val[i]; pnv_deepest_stop_psscr_mask = psscr_mask[i];If firmware did not provide any ESL=EC=1 state, we can still leave threads in stop ESL=0 state. This is just a corner case or random test scenario. Why do we want to enforce that offline cpus really use a ESL=0 state or just spin?
It's because power9_offline_stop only has cases for EC=ESL=1 states now.
It actually looks like EC=ESL=0 unplug today is broken KVM, because the wakeup side does not check HWTHREAD_REQ, and yet they do set HWTHREAD_IN_IDLE. That would probably hang in KVM if we run with dependent threads, wouldn't it?
I think banning it for now should be okay.
Thanks,
Nick
Re: [PATCH 3/3] powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
Quoted 4 lines · Nicholas Piggin
Quoted 1 line · On Thu, 1 Mar 2018 00:04:39 +0530 Vaidyanathan Srinivasan…
* Nicholas Piggin <[email protected]> [2017-11-18 00:08:07]:
[snip]
Quoted 24 lines
Quoted 8 lines
Quoted 8 lines
arch/powerpc/platforms/powernv/idle.c +0
-0@@ -621,7 +621,12 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags,continue ; }Quoted 15 lines
arch/powerpc/platforms/powernv/idle.c static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, · line 632
Quoted 10 lines
arch/powerpc/platforms/powernv/idle.c +6
-1-if (max_residency_ns < residency_ns[i]) { +/* +* Deepest stop for unplug must be PSSCR[EC]=1 (wakeup at +* 0x100. +*/ +if ((max_residency_ns < residency_ns[i])&& + (psscr_val[i] &PSSCR_EC )) { max_residency_ns = residency_ns[i]; pnv_deepest_stop_psscr_val = psscr_val[i]; pnv_deepest_stop_psscr_mask = psscr_mask[i];If firmware did not provide any ESL=EC=1 state, we can still leave threads in stop ESL=0 state. This is just a corner case or random test scenario. Why do we want to enforce that offline cpus really use a ESL=0 state or just spin?
Quoted 7 lines
It's because
power9_offline_stoponly has cases for EC=ESL=1 states now.It actually looks like EC=ESL=0 unplug today is broken KVM, because the wakeup side does not check
HWTHREAD_REQ, and yet they do setHWTHREAD_IN_IDLE. That would probably hang in KVM if we run with dependent threads, wouldn't it?
Right. KVM with indep_threads_mode=N is broken at the moment if you run with powersave=off or if firmware provides no stop states with EC=ESL=1. I'm not sure what's the best way to fix that.
Quoted 1 line
I think banning it for now should be okay.
Banning what exactly?
Paul.
Nicholas Piggin
reviewerRe: [PATCH 3/3] powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
Quoted 33 lines · On Mon, 5 Mar 2018 10:01:01 +1100 Paul Mackerras <[email protected]> wrote:
Quoted 4 lines · Nicholas Piggin
Quoted 1 line · On Thu, 1 Mar 2018 00:04:39 +0530 Vaidyanathan Srinivasan…
* Nicholas Piggin <[email protected]> [2017-11-18 00:08:07]:
[snip]
Quoted 27 lines
Quoted 8 lines
Quoted 8 lines
arch/powerpc/platforms/powernv/idle.c +0
-0@@ -621,7 +621,12 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags,continue ; }Quoted 15 lines
arch/powerpc/platforms/powernv/idle.c static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, · line 632
Quoted 10 lines
arch/powerpc/platforms/powernv/idle.c +6
-1-if (max_residency_ns < residency_ns[i]) { +/* +* Deepest stop for unplug must be PSSCR[EC]=1 (wakeup at +* 0x100. +*/ +if ((max_residency_ns < residency_ns[i])&& + (psscr_val[i] &PSSCR_EC )) { max_residency_ns = residency_ns[i]; pnv_deepest_stop_psscr_val = psscr_val[i]; pnv_deepest_stop_psscr_mask = psscr_mask[i];If firmware did not provide any ESL=EC=1 state, we can still leave threads in stop ESL=0 state. This is just a corner case or random test scenario. Why do we want to enforce that offline cpus really use a ESL=0 state or just spin?
It's because
power9_offline_stoponly has cases for EC=ESL=1 states now.
Quoted 8 lines
Quoted 4 lines
It actually looks like EC=ESL=0 unplug today is broken KVM, because the wakeup side does not check
HWTHREAD_REQ, and yet they do setHWTHREAD_IN_IDLE. That would probably hang in KVM if we run with dependent threads, wouldn't it?Right. KVM with indep_threads_mode=N is broken at the moment if you run with powersave=off or if firmware provides no stop states with EC=ESL=1. I'm not sure what's the best way to fix that.
For EC=ESL=1, would it be enough to do a test and branch right after the stop instruction?
Quoted 3 lines
Quoted 1 line
I think banning it for now should be okay.
Banning what exactly?
power9 CPU unplug using a EC=ESL=0 stop state.
Thanks,
Nick
Michael Ellerman
reviewerRe: [PATCH 3/3] powerpc/64s/idle: POWER9 ESL=0 stop avoid save/restore overhead
In reply to Nicholas PigginQuoted 29 lines · Nicholas Piggin
When stop is executed with EC=ESL=0, it appears to execute like a normal instruction (resuming from NIP when woken by interrupt). So all the save/restore handling can be avoided completely. In particular NV GPRs do not have to be saved, and MSR does not have to be switched back to kernel MSR.
So move the test for EC=ESL=0 sleep states out to
power9_idle_stop, and return directly to the caller after stop in that case. The mtspr to PSSCR is moved to the top ofpower9_offline_stopjust so it matchespower9_idle_stop.This improves performance for ping-pong benchmark with the
stop0_liteidle state by 2.54% for 2 threads in the same core, and 2.57% for different cores.Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/kernel/idle_book3s.S | 43 +++++++++++------------------------ arch/powerpc/platforms/powernv/idle.c | 7 +++++- 2 files changed, 19 insertions(+), 31 deletions(-)arch/powerpc/kernel/idle_book3s.S +0
-0@@ -324,31 +324,8 @@ enter_winkle: /* * r3 - PSSCR value corresponding to the requested stop state. */
arch/powerpc/kernel/idle_book3s.S enter_winkle: · line 335
Quoted 10 lines
arch/powerpc/kernel/idle_book3s.S +1
-8-power_enter_stop: -/* - * Check if we are executing the lite variant with ESL=EC=0 - */ - andis. r4,r3,PSSCR_EC_ESL_MASK_SHIFTED +power_enter_stop_esl: clrldi r3,r3,60 /* r3 = Bits[60:63] = Requested Level (RL) */ - bne .Lhandle_esl_ec_set - PPC_STOP - li r3,0 /* Since we didn't lose state, return 0 */
Sorry this clashed with Paul's force-SMT4 patches which I needed to merge to enable TM workarounds.
Can you rebase?
cheers