All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Mackerras <paulus@samba.org>
To: "Shreyas B. Prabhu" <shreyas@linux.vnet.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 4/4] powernv: powerpc: Add winkle support for offline cpus
Date: Mon, 8 Dec 2014 16:52:17 +1100	[thread overview]
Message-ID: <20141208055217.GC4437@drongo> (raw)
In-Reply-To: <1417678103-32571-5-git-send-email-shreyas@linux.vnet.ibm.com>

On Thu, Dec 04, 2014 at 12:58:23PM +0530, Shreyas B. Prabhu wrote:
> Winkle is a deep idle state supported in power8 chips. A core enters
> winkle when all the threads of the core enter winkle. In this state
> power supply to the entire chiplet i.e core, private L2 and private L3
> is turned off. As a result it gives higher powersavings compared to
> sleep.
> 
> But entering winkle results in a total hypervisor state loss. Hence the
> hypervisor context has to be preserved before entering winkle and
> restored upon wake up.
> 
> Power-on Reset Engine (PORE) is a dedicated engine which is responsible
> for powering on the chiplet during wake up. It can be programmed to
> restore the register contests of a few specific registers. This patch
> uses PORE to restore register state wherever possible and uses stack to
> save and restore rest of the necessary registers.
> 
> With hypervisor state restore things fall under three categories-
> per-core state, per-subcore state and per-thread state. To manage this,
> extend the infrastructure introduced for sleep. Mainly we add a paca
> variable subcore_sibling_mask. Using this and the core_idle_state we can
> distingush first thread in core and subcore.

Comments below...

> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index 7637889..2b9b5fb 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -102,9 +102,7 @@ system_reset_pSeries:
>  #ifdef CONFIG_PPC_P7_NAP
>  BEGIN_FTR_SECTION
>  	/* Running native on arch 2.06 or later, check if we are
> -	 * waking up from nap. We only handle no state loss and
> -	 * supervisor state loss. We do -not- handle hypervisor
> -	 * state loss at this time.
> +	 * waking up from nap/sleep/winkle.
>  	 */
>  	mfspr	r13,SPRN_SRR1
>  	rlwinm.	r13,r13,47-31,30,31
> @@ -112,7 +110,17 @@ BEGIN_FTR_SECTION
>  
>  	cmpwi	cr3,r13,2
>  
> -	GET_PACA(r13)
> +	/* Check if last bit of HSPGR0 is set. This indicates whether we are
> +	 * waking up from winkle */
> +	li	r3,1
> +	mfspr	r4,SPRN_HSPRG0
> +	and	r5,r4,r3
> +	cmpwi	cr4,r5,1	/* Store result in cr4 for later use */
> +
> +	andc	r4,r4,r3
> +	mtspr	SPRN_HSPRG0,r4
> +
> +	mr	r13,r4

This seems unnecessarily convoluted.  How about:

	GET_PACA(r13)
	clrldi	r5,r13,63
	clrrdi	r13,r13,1
	cmpwi	cr4,r5,1
	mtspr	SPRN_HSPRG0,r13

> diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
> index 8c3a1f4..8102075 100644
> --- a/arch/powerpc/kernel/idle_power7.S
> +++ b/arch/powerpc/kernel/idle_power7.S
> @@ -19,8 +19,24 @@
>  #include <asm/kvm_book3s_asm.h>
>  #include <asm/opal.h>
>  #include <asm/cpuidle.h>
> +#include <asm/mmu-hash64.h>
>  
>  #undef DEBUG
> +/*
> + * Use unused space in the interrupt stack to save and restore
> + * registers for winkle support.
> + */
> +#define _SDR1	GPR3
> +#define _RPR	GPR4
> +#define _SPURR	GPR5
> +#define _PURR	GPR6
> +#define _TSCR	GPR7
> +#define _DSCR	GPR8
> +#define _AMOR	GPR9
> +#define _PMC5	GPR10
> +#define _PMC6	GPR11

Why only PMC5 and PMC6 out of all the PMU registers?  What about
PMC1-PMC4 and the MMCR registers?  I assume they're lost during winkle
state also, aren't they?  If we're not saving them, what's the point
of saving and restoring PMC5 and PMC6?

> +#define _WORT	GPR12
> +#define _WORC	GPR13
>  
>  /* Idle state entry routines */
>  
> @@ -124,8 +140,8 @@ power7_enter_nap_mode:
>  	stb	r4,HSTATE_HWTHREAD_STATE(r13)
>  #endif
>  	stb	r3,PACA_THREAD_IDLE_STATE(r13)
> -	cmpwi	cr1,r3,PNV_THREAD_SLEEP
> -	bge	cr1,2f
> +	cmpwi	cr3,r3,PNV_THREAD_SLEEP
> +	bge	cr3,2f
>  	IDLE_STATE_ENTER_SEQ(PPC_NAP)
>  	/* No return */
>  2:
> @@ -154,7 +170,8 @@ pnv_fastsleep_workaround_at_entry:
>  	isync
>  	bne-	lwarx_loop1
>  
> -common_enter: /* common code for all the threads entering sleep */
> +common_enter: /* common code for all the threads entering sleep  or winkle */
> +	bgt	cr3,enter_winkle
>  	IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
>  
>  fastsleep_workaround_at_entry:
> @@ -175,6 +192,34 @@ fastsleep_workaround_at_entry:
>  	stw	r0,0(r14)
>  	b	common_enter
>  
> +enter_winkle:
> +	/*
> +	 * Note all register i.e per-core, per-subcore or per-thread is saved
> +	 * here since any thread in the core might wake up first
> +	 */
> +	mfspr	r3,SPRN_SDR1
> +	std	r3,_SDR1(r1)
> +	mfspr	r3,SPRN_RPR
> +	std	r3,_RPR(r1)
> +	mfspr	r3,SPRN_SPURR
> +	std	r3,_SPURR(r1)
> +	mfspr	r3,SPRN_PURR
> +	std	r3,_PURR(r1)
> +	mfspr	r3,SPRN_TSCR
> +	std	r3,_TSCR(r1)
> +	mfspr	r3,SPRN_DSCR
> +	std	r3,_DSCR(r1)
> +	mfspr	r3,SPRN_AMOR
> +	std	r3,_AMOR(r1)
> +	mfspr	r3,SPRN_PMC5
> +	std	r3,_PMC5(r1)
> +	mfspr	r3,SPRN_PMC6
> +	std	r3,_PMC6(r1)
> +	mfspr	r3,SPRN_WORT
> +	std	r3,_WORT(r1)
> +	mfspr	r3,SPRN_WORC
> +	std	r3,_WORC(r1)
> +	IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
>  
>  _GLOBAL(power7_idle)
>  	/* Now check if user or arch enabled NAP mode */
> @@ -197,6 +242,12 @@ _GLOBAL(power7_sleep)
>  	b	power7_powersave_common
>  	/* No return */
>  
> +_GLOBAL(power7_winkle)
> +	li	r3,3
> +	li	r4,1
> +	b	power7_powersave_common
> +	/* No return */
> +
>  #define CHECK_HMI_INTERRUPT						\
>  	mfspr	r0,SPRN_SRR1;						\
>  BEGIN_FTR_SECTION_NESTED(66);						\
> @@ -238,11 +289,23 @@ lwarx_loop2:
>  	bne	core_idle_lock_held
>  
>  	cmpwi	cr2,r15,0
> +	lbz	r4,PACA_SUBCORE_SIBLING_MASK(r13)
> +	and	r4,r4,r15
> +	cmpwi	cr1,r4,0	/* Check if first in subcore */
> +
> +	/*
> +	 * At this stage
> +	 * cr1 - 10 if first thread to wakeup in subcore
> +	 * cr2 - 10 if first thread to wakeup in core
> +	 * cr3-  01 if waking up from sleep or winkle
> +	 * cr4 - 10 if waking up from winkle
> +	 */

What do "10" and "01" mean in this comment?  (If they were CR field
values in binary they would need to be 3 or 4 bits, not 2.)

Paul.

WARNING: multiple messages have this Message-ID (diff)
From: Paul Mackerras <paulus@samba.org>
To: "Shreyas B. Prabhu" <shreyas@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Michael Ellerman <mpe@ellerman.id.au>,
	linuxppc-dev@lists.ozlabs.org
Subject: Re: [PATCH v3 4/4] powernv: powerpc: Add winkle support for offline cpus
Date: Mon, 8 Dec 2014 16:52:17 +1100	[thread overview]
Message-ID: <20141208055217.GC4437@drongo> (raw)
In-Reply-To: <1417678103-32571-5-git-send-email-shreyas@linux.vnet.ibm.com>

On Thu, Dec 04, 2014 at 12:58:23PM +0530, Shreyas B. Prabhu wrote:
> Winkle is a deep idle state supported in power8 chips. A core enters
> winkle when all the threads of the core enter winkle. In this state
> power supply to the entire chiplet i.e core, private L2 and private L3
> is turned off. As a result it gives higher powersavings compared to
> sleep.
> 
> But entering winkle results in a total hypervisor state loss. Hence the
> hypervisor context has to be preserved before entering winkle and
> restored upon wake up.
> 
> Power-on Reset Engine (PORE) is a dedicated engine which is responsible
> for powering on the chiplet during wake up. It can be programmed to
> restore the register contests of a few specific registers. This patch
> uses PORE to restore register state wherever possible and uses stack to
> save and restore rest of the necessary registers.
> 
> With hypervisor state restore things fall under three categories-
> per-core state, per-subcore state and per-thread state. To manage this,
> extend the infrastructure introduced for sleep. Mainly we add a paca
> variable subcore_sibling_mask. Using this and the core_idle_state we can
> distingush first thread in core and subcore.

Comments below...

> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index 7637889..2b9b5fb 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -102,9 +102,7 @@ system_reset_pSeries:
>  #ifdef CONFIG_PPC_P7_NAP
>  BEGIN_FTR_SECTION
>  	/* Running native on arch 2.06 or later, check if we are
> -	 * waking up from nap. We only handle no state loss and
> -	 * supervisor state loss. We do -not- handle hypervisor
> -	 * state loss at this time.
> +	 * waking up from nap/sleep/winkle.
>  	 */
>  	mfspr	r13,SPRN_SRR1
>  	rlwinm.	r13,r13,47-31,30,31
> @@ -112,7 +110,17 @@ BEGIN_FTR_SECTION
>  
>  	cmpwi	cr3,r13,2
>  
> -	GET_PACA(r13)
> +	/* Check if last bit of HSPGR0 is set. This indicates whether we are
> +	 * waking up from winkle */
> +	li	r3,1
> +	mfspr	r4,SPRN_HSPRG0
> +	and	r5,r4,r3
> +	cmpwi	cr4,r5,1	/* Store result in cr4 for later use */
> +
> +	andc	r4,r4,r3
> +	mtspr	SPRN_HSPRG0,r4
> +
> +	mr	r13,r4

This seems unnecessarily convoluted.  How about:

	GET_PACA(r13)
	clrldi	r5,r13,63
	clrrdi	r13,r13,1
	cmpwi	cr4,r5,1
	mtspr	SPRN_HSPRG0,r13

> diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
> index 8c3a1f4..8102075 100644
> --- a/arch/powerpc/kernel/idle_power7.S
> +++ b/arch/powerpc/kernel/idle_power7.S
> @@ -19,8 +19,24 @@
>  #include <asm/kvm_book3s_asm.h>
>  #include <asm/opal.h>
>  #include <asm/cpuidle.h>
> +#include <asm/mmu-hash64.h>
>  
>  #undef DEBUG
> +/*
> + * Use unused space in the interrupt stack to save and restore
> + * registers for winkle support.
> + */
> +#define _SDR1	GPR3
> +#define _RPR	GPR4
> +#define _SPURR	GPR5
> +#define _PURR	GPR6
> +#define _TSCR	GPR7
> +#define _DSCR	GPR8
> +#define _AMOR	GPR9
> +#define _PMC5	GPR10
> +#define _PMC6	GPR11

Why only PMC5 and PMC6 out of all the PMU registers?  What about
PMC1-PMC4 and the MMCR registers?  I assume they're lost during winkle
state also, aren't they?  If we're not saving them, what's the point
of saving and restoring PMC5 and PMC6?

> +#define _WORT	GPR12
> +#define _WORC	GPR13
>  
>  /* Idle state entry routines */
>  
> @@ -124,8 +140,8 @@ power7_enter_nap_mode:
>  	stb	r4,HSTATE_HWTHREAD_STATE(r13)
>  #endif
>  	stb	r3,PACA_THREAD_IDLE_STATE(r13)
> -	cmpwi	cr1,r3,PNV_THREAD_SLEEP
> -	bge	cr1,2f
> +	cmpwi	cr3,r3,PNV_THREAD_SLEEP
> +	bge	cr3,2f
>  	IDLE_STATE_ENTER_SEQ(PPC_NAP)
>  	/* No return */
>  2:
> @@ -154,7 +170,8 @@ pnv_fastsleep_workaround_at_entry:
>  	isync
>  	bne-	lwarx_loop1
>  
> -common_enter: /* common code for all the threads entering sleep */
> +common_enter: /* common code for all the threads entering sleep  or winkle */
> +	bgt	cr3,enter_winkle
>  	IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
>  
>  fastsleep_workaround_at_entry:
> @@ -175,6 +192,34 @@ fastsleep_workaround_at_entry:
>  	stw	r0,0(r14)
>  	b	common_enter
>  
> +enter_winkle:
> +	/*
> +	 * Note all register i.e per-core, per-subcore or per-thread is saved
> +	 * here since any thread in the core might wake up first
> +	 */
> +	mfspr	r3,SPRN_SDR1
> +	std	r3,_SDR1(r1)
> +	mfspr	r3,SPRN_RPR
> +	std	r3,_RPR(r1)
> +	mfspr	r3,SPRN_SPURR
> +	std	r3,_SPURR(r1)
> +	mfspr	r3,SPRN_PURR
> +	std	r3,_PURR(r1)
> +	mfspr	r3,SPRN_TSCR
> +	std	r3,_TSCR(r1)
> +	mfspr	r3,SPRN_DSCR
> +	std	r3,_DSCR(r1)
> +	mfspr	r3,SPRN_AMOR
> +	std	r3,_AMOR(r1)
> +	mfspr	r3,SPRN_PMC5
> +	std	r3,_PMC5(r1)
> +	mfspr	r3,SPRN_PMC6
> +	std	r3,_PMC6(r1)
> +	mfspr	r3,SPRN_WORT
> +	std	r3,_WORT(r1)
> +	mfspr	r3,SPRN_WORC
> +	std	r3,_WORC(r1)
> +	IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
>  
>  _GLOBAL(power7_idle)
>  	/* Now check if user or arch enabled NAP mode */
> @@ -197,6 +242,12 @@ _GLOBAL(power7_sleep)
>  	b	power7_powersave_common
>  	/* No return */
>  
> +_GLOBAL(power7_winkle)
> +	li	r3,3
> +	li	r4,1
> +	b	power7_powersave_common
> +	/* No return */
> +
>  #define CHECK_HMI_INTERRUPT						\
>  	mfspr	r0,SPRN_SRR1;						\
>  BEGIN_FTR_SECTION_NESTED(66);						\
> @@ -238,11 +289,23 @@ lwarx_loop2:
>  	bne	core_idle_lock_held
>  
>  	cmpwi	cr2,r15,0
> +	lbz	r4,PACA_SUBCORE_SIBLING_MASK(r13)
> +	and	r4,r4,r15
> +	cmpwi	cr1,r4,0	/* Check if first in subcore */
> +
> +	/*
> +	 * At this stage
> +	 * cr1 - 10 if first thread to wakeup in subcore
> +	 * cr2 - 10 if first thread to wakeup in core
> +	 * cr3-  01 if waking up from sleep or winkle
> +	 * cr4 - 10 if waking up from winkle
> +	 */

What do "10" and "01" mean in this comment?  (If they were CR field
values in binary they would need to be 3 or 4 bits, not 2.)

Paul.

  reply	other threads:[~2014-12-08  5:52 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-04  7:28 [PATCH v3 0/4] powernv: cpuidle: Redesign idle states management Shreyas B. Prabhu
2014-12-04  7:28 ` Shreyas B. Prabhu
2014-12-04  7:28 ` [PATCH v3 1/4] powerpc: powernv: Switch off MMU before entering nap/sleep/rvwinkle mode Shreyas B. Prabhu
2014-12-04  7:28   ` Shreyas B. Prabhu
2014-12-04  7:28 ` [PATCH v3 2/4] powerpc/powernv: Enable Offline CPUs to enter deep idle states Shreyas B. Prabhu
2014-12-04  7:28   ` Shreyas B. Prabhu
2014-12-08  3:33   ` Paul Mackerras
2014-12-08  3:33     ` Paul Mackerras
2014-12-14 10:05   ` [v3, " Michael Ellerman
2014-12-14 10:05     ` Michael Ellerman
2014-12-14 11:49     ` Shreyas B Prabhu
2014-12-14 11:49       ` Shreyas B Prabhu
2014-12-14 23:44       ` Michael Ellerman
2014-12-14 23:44         ` Michael Ellerman
2014-12-04  7:28 ` [PATCH v3 3/4] powernv: cpuidle: Redesign idle states management Shreyas B. Prabhu
2014-12-04  7:28   ` Shreyas B. Prabhu
2014-12-08  5:01   ` Paul Mackerras
2014-12-08  5:01     ` Paul Mackerras
2014-12-08  5:26     ` Shreyas B Prabhu
2014-12-08  5:26       ` Shreyas B Prabhu
2014-12-04  7:28 ` [PATCH v3 4/4] powernv: powerpc: Add winkle support for offline cpus Shreyas B. Prabhu
2014-12-04  7:28   ` Shreyas B. Prabhu
2014-12-08  5:52   ` Paul Mackerras [this message]
2014-12-08  5:52     ` Paul Mackerras
2014-12-08 21:54     ` Shreyas B Prabhu
2014-12-08 21:54       ` Shreyas B Prabhu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141208055217.GC4437@drongo \
    --to=paulus@samba.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=shreyas@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.