* [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states
@ 2016-07-07 20:47 Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle Shreyas B. Prabhu
` (11 more replies)
0 siblings, 12 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu, Rafael J. Wysocki, Daniel Lezcano, linux-pm,
Rob Herring, Lorenzo Pieralisi
POWER ISA v3 defines a new idle processor core mechanism. In summary,
a) new instruction named stop is added. This instruction replaces
instructions like nap, sleep, rvwinkle.
b) new per thread SPR named PSSCR is added which controls the behavior
of stop instruction.
PSSCR has following key fields
Bits 0:3 - Power-Saving Level Status. This field indicates the
lowest power-saving state the thread entered since stop
instruction was last executed.
Bit 42 - Enable State Loss
0 - No state is lost irrespective of other fields
1 - Allows state loss
Bits 44:47 - Power-Saving Level Limit
This limits the power-saving level that can be entered into.
Bits 60:63 - Requested Level
Used to specify which power-saving level must be entered on
executing stop instruction
Stop idle states and their properties like name, latency, target
residency, psscr value are exposed via device tree.
This patch series adds support for this new mechanism.
Patches 1-6 are cleanups and code movement.
Patch 7 adds platform specific support for stop and psscr handling.
Patch 8 and 9 are minor cleanup in cpuidle driver.
Patch 10 adds cpuidle driver support.
Patch 11 makes offlined cpu use deepest stop state.
Note: Documentation for the device tree bindings is posted here-
http://patchwork.ozlabs.org/patch/629125/
Changes in v7
=============
- File renamed to idle_book3s.S instead of idle_power_common.S
- Comment changes
- power_stop0, power_stop renamed to power9_idle and power_idle_stop
- PSSCR template is now a macro instead of storing in paca
- power9_idle in C file instead of assembly
- Fixed TOC related bug
- Handling subcore within FTR section
- Functions in idle.c reordered and broken into multiple functions
- calling __restore_cpu_power8/9 via cur_cpu_spec->cpu_restore
- Added a minor patch with minor cleanups in cpuidle-powernv.c . This
was mainly to make the existing code consistent with the review
comments for new code
- Using stack for variables while probing for idle states instead of
kzalloc/kcalloc
Changes in v6
=============
- Restore new POWER ISA v3 SPRS when waking up from deep idle
Changes in v5
=============
- Use generic cpuidle constant CPUIDLE_NAME_LEN
- Fix return code handling for of_property_read_string_array
- Use DT flags to determine if are using stop instruction, instead of
cpu_has_feature
- Removed uncessary cast with names
- &stop_loop -> stop_loop
- Added POWERNV_THRESHOLD_LATENCY_NS to filter out idle states with high latency
Changes in v4
=============
- Added a patch to use PNV_THREAD_WINKLE macro while requesting for winkle
- Moved power7_powersave_common rename to more appropriate patch
- renaming power7_enter_nap_mode to pnv_enter_arch207_idle_mode
- Added PSSCR layout to Patch 7's commit message
- Improved / Fixed comments
- Fixed whitespace error in paca.h
- Using MAX_POSSIBLE_STOP_STATE macro instead of hardcoding 0xF has
max possible stop state
Changes in v3
=============
- Rebased on powerpc-next
- Dropping patch 1 since we are not adding a new file for P9 idle support
- Improved comments in multiple places
- Moved GET_PACA from power7_restore_hyp_resource to System Reset
- Instead of moving few functions from idle_power7 to idle_power_common,
renaming idle_power7.S to idle_power_common.S
- Moved HSTATE_HWTHREAD_STATE updation to power_powersave_common
- Dropped earlier patch 5 which moved few macros from idle_power_common to
asm/cpuidle.h.
- Added a patch to rename reusable power7_* idle functions to pnv_*
- Added new patch that creates abstraction for saving SPRs before
entering deep idle states
- Instead of introducing new file idle_power_stop.S, P9 idle support
is added to idle_power_common.S using CPU_FTR sections.
- Fixed r4 reg clobbering in power_stop0
Changes in v2
=============
- Rebased on v4.6-rc6
- Using CPU_FTR_ARCH_300 bit instead of CPU_FTR_STOP_INST
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: linux-pm@vger.kernel.org
Cc: Benjamin Herrenschmidt <benh@au1.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@ozlabs.org>
Cc: Michael Neuling <mikey@neuling.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
Shreyas B. Prabhu (11):
powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for
winkle
powerpc/kvm: make hypervisor state restore a function
powerpc/powernv: Rename idle_power7.S to idle_book3s.S
powerpc/powernv: Rename reusable idle functions to hardware agnostic
names
powerpc/powernv: Make pnv_powersave_common more generic
powerpc/powernv: abstraction for saving SPRs before entering deep idle
states
powerpc/powernv: Add platform support for stop instruction
cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of
MAX_POWERNV_IDLE_STATES
cpuidle/powernv: cleanup powernv_add_idle_states
cpuidle/powernv: Add support for POWER ISA v3 idle states
powerpc/powernv: Use deepest stop state when cpu is offlined
arch/powerpc/include/asm/cpuidle.h | 2 +
arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +-
arch/powerpc/include/asm/opal-api.h | 11 +-
arch/powerpc/include/asm/ppc-opcode.h | 4 +
arch/powerpc/include/asm/processor.h | 2 +
arch/powerpc/include/asm/reg.h | 10 +
arch/powerpc/kernel/Makefile | 2 +-
arch/powerpc/kernel/exceptions-64s.S | 30 +-
arch/powerpc/kernel/idle_book3s.S | 664 ++++++++++++++++++++++++++++++
arch/powerpc/kernel/idle_power7.S | 515 -----------------------
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 +-
arch/powerpc/platforms/powernv/idle.c | 185 +++++++--
arch/powerpc/platforms/powernv/powernv.h | 1 +
arch/powerpc/platforms/powernv/smp.c | 4 +-
drivers/cpuidle/cpuidle-powernv.c | 99 ++++-
15 files changed, 940 insertions(+), 595 deletions(-)
create mode 100644 arch/powerpc/kernel/idle_book3s.S
delete mode 100644 arch/powerpc/kernel/idle_power7.S
--
2.4.11
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-15 13:10 ` Balbir Singh
2016-07-07 20:47 ` [PATCH v7 02/11] powerpc/kvm: make hypervisor state restore a function Shreyas B. Prabhu
` (10 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
-No changes since v4
Changes in v4
=============
- New in v4
arch/powerpc/kernel/idle_power7.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 470ceeb..705c867 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -252,7 +252,7 @@ _GLOBAL(power7_sleep)
/* No return */
_GLOBAL(power7_winkle)
- li r3,3
+ li r3,PNV_THREAD_WINKLE
li r4,1
b power7_powersave_common
/* No return */
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 02/11] powerpc/kvm: make hypervisor state restore a function
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 03/11] powerpc/powernv: Rename idle_power7.S to idle_book3s.S Shreyas B. Prabhu
` (9 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
In the current code, when the thread wakes up in reset vector, some
of the state restore code and check for whether a thread needs to
branch to kvm is duplicated. Reorder the code such that this
duplication is avoided.
At a higher level this is what the change looks like-
Before this patch -
power7_wakeup_tb_loss:
restore hypervisor state
if (thread needed by kvm)
goto kvm_start_guest
restore nvgprs, cr, pc
rfid to process context
power7_wakeup_loss:
restore nvgprs, cr, pc
rfid to process context
reset vector:
if (waking from deep idle states)
goto power7_wakeup_tb_loss
else
if (thread needed by kvm)
goto kvm_start_guest
goto power7_wakeup_loss
After this patch -
power7_wakeup_tb_loss:
restore hypervisor state
return
power7_restore_hyp_resource():
if (waking from deep idle states)
goto power7_wakeup_tb_loss
return
power7_wakeup_loss:
restore nvgprs, cr, pc
rfid to process context
reset vector:
power7_restore_hyp_resource()
if (thread needed by kvm)
goto kvm_start_guest
goto power7_wakeup_loss
Reviewed-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- No changes since v3
Changes in v3:
=============
- Retaining GET_PACA(r13) in System Reset vector instead of moving it
to power7_restore_hyp_resource
- Added comments indicating entry conditions for power7_restore_hyp_resource
- Improved comments around return statements
arch/powerpc/kernel/exceptions-64s.S | 28 ++------------
arch/powerpc/kernel/idle_power7.S | 72 +++++++++++++++++++++---------------
2 files changed, 46 insertions(+), 54 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 4c94406..4a74d6a 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -107,25 +107,9 @@ BEGIN_FTR_SECTION
beq 9f
cmpwi cr3,r13,2
-
- /*
- * Check if last bit of HSPGR0 is set. This indicates whether we are
- * waking up from winkle.
- */
GET_PACA(r13)
- clrldi r5,r13,63
- clrrdi r13,r13,1
- cmpwi cr4,r5,1
- mtspr SPRN_HSPRG0,r13
+ bl power7_restore_hyp_resource
- lbz r0,PACA_THREAD_IDLE_STATE(r13)
- cmpwi cr2,r0,PNV_THREAD_NAP
- bgt cr2,8f /* Either sleep or Winkle */
-
- /* Waking up from nap should not cause hypervisor state loss */
- bgt cr3,.
-
- /* Waking up from nap */
li r0,PNV_THREAD_RUNNING
stb r0,PACA_THREAD_IDLE_STATE(r13) /* Clear thread state */
@@ -143,13 +127,9 @@ BEGIN_FTR_SECTION
/* Return SRR1 from power7_nap() */
mfspr r3,SPRN_SRR1
- beq cr3,2f
- b power7_wakeup_noloss
-2: b power7_wakeup_loss
-
- /* Fast Sleep wakeup on PowerNV */
-8: GET_PACA(r13)
- b power7_wakeup_tb_loss
+ blt cr3,2f
+ b power7_wakeup_loss
+2: b power7_wakeup_noloss
9:
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 705c867..d5def06 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -276,6 +276,39 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
20: nop;
+/*
+ * Called from reset vector. Check whether we have woken up with
+ * hypervisor state loss. If yes, restore hypervisor state and return
+ * back to reset vector.
+ *
+ * r13 - Contents of HSPRG0
+ * cr3 - set to gt if waking up with partial/complete hypervisor state loss
+ */
+_GLOBAL(power7_restore_hyp_resource)
+ /*
+ * Check if last bit of HSPGR0 is set. This indicates whether we are
+ * waking up from winkle.
+ */
+ clrldi r5,r13,63
+ clrrdi r13,r13,1
+ cmpwi cr4,r5,1
+ mtspr SPRN_HSPRG0,r13
+
+ lbz r0,PACA_THREAD_IDLE_STATE(r13)
+ cmpwi cr2,r0,PNV_THREAD_NAP
+ bgt cr2,power7_wakeup_tb_loss /* Either sleep or Winkle */
+
+ /*
+ * We fall through here if PACA_THREAD_IDLE_STATE shows we are waking
+ * up from nap. At this stage CR3 shouldn't contains 'gt' since that
+ * indicates we are waking with hypervisor state loss from nap.
+ */
+ bgt cr3,.
+
+ blr /* Return back to System Reset vector from where
+ power7_restore_hyp_resource was invoked */
+
+
_GLOBAL(power7_wakeup_tb_loss)
ld r2,PACATOC(r13);
ld r1,PACAR1(r13)
@@ -284,11 +317,13 @@ _GLOBAL(power7_wakeup_tb_loss)
* and they are restored before switching to the process context. Hence
* until they are restored, they are free to be used.
*
- * Save SRR1 in a NVGPR as it might be clobbered in opal_call_realmode
- * (called in CHECK_HMI_INTERRUPT). SRR1 is required to determine the
- * wakeup reason if we branch to kvm_start_guest.
+ * Save SRR1 and LR in NVGPRs as they might be clobbered in
+ * opal_call_realmode (called in CHECK_HMI_INTERRUPT). SRR1 is required
+ * to determine the wakeup reason if we branch to kvm_start_guest. LR
+ * is required to return back to reset vector after hypervisor state
+ * restore is complete.
*/
-
+ mflr r17
mfspr r16,SPRN_SRR1
BEGIN_FTR_SECTION
CHECK_HMI_INTERRUPT
@@ -438,33 +473,10 @@ common_exit:
hypervisor_state_restored:
- li r5,PNV_THREAD_RUNNING
- stb r5,PACA_THREAD_IDLE_STATE(r13)
-
mtspr SPRN_SRR1,r16
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
- li r0,KVM_HWTHREAD_IN_KERNEL
- stb r0,HSTATE_HWTHREAD_STATE(r13)
- /* Order setting hwthread_state vs. testing hwthread_req */
- sync
- lbz r0,HSTATE_HWTHREAD_REQ(r13)
- cmpwi r0,0
- beq 6f
- b kvm_start_guest
-6:
-#endif
-
- REST_NVGPRS(r1)
- REST_GPR(2, r1)
- ld r3,_CCR(r1)
- ld r4,_MSR(r1)
- ld r5,_NIP(r1)
- addi r1,r1,INT_FRAME_SIZE
- mtcr r3
- mfspr r3,SPRN_SRR1 /* Return SRR1 */
- mtspr SPRN_SRR1,r4
- mtspr SPRN_SRR0,r5
- rfid
+ mtlr r17
+ blr /* Return back to System Reset vector from where
+ power7_restore_hyp_resource was invoked */
fastsleep_workaround_at_exit:
li r3,1
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 03/11] powerpc/powernv: Rename idle_power7.S to idle_book3s.S
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 02/11] powerpc/kvm: make hypervisor state restore a function Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 04/11] powerpc/powernv: Rename reusable idle functions to hardware agnostic names Shreyas B. Prabhu
` (8 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
idle_power7.S handles idle entry/exit for POWER7, POWER8 and in next
patch for POWER9. Rename the file to a non-hardware specific
name.
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
Changes in v7:
=============
- File renamed to idle_book3s.S instead of idle_power_common.S
Changes in v3:
==============
- Instead of moving few common functions from idle_power7.S to
idle_power_common.S, renaming idle_power7.S to idle_power_common.S
arch/powerpc/kernel/Makefile | 2 +-
arch/powerpc/kernel/idle_book3s.S | 527 ++++++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/idle_power7.S | 527 --------------------------------------
3 files changed, 528 insertions(+), 528 deletions(-)
create mode 100644 arch/powerpc/kernel/idle_book3s.S
delete mode 100644 arch/powerpc/kernel/idle_power7.S
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 2da380f..9e7bfc32 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -47,7 +47,7 @@ obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o
obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
-obj-$(CONFIG_PPC_P7_NAP) += idle_power7.o
+obj-$(CONFIG_PPC_P7_NAP) += idle_book3s.o
procfs-y := proc_powerpc.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
new file mode 100644
index 0000000..d5def06
--- /dev/null
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -0,0 +1,527 @@
+/*
+ * This file contains the power_save function for Power7 CPUs.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/ppc-opcode.h>
+#include <asm/hw_irq.h>
+#include <asm/kvm_book3s_asm.h>
+#include <asm/opal.h>
+#include <asm/cpuidle.h>
+#include <asm/book3s/64/mmu-hash.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 _WORT GPR10
+#define _WORC GPR11
+
+/* Idle state entry routines */
+
+#define IDLE_STATE_ENTER_SEQ(IDLE_INST) \
+ /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
+ std r0,0(r1); \
+ ptesync; \
+ ld r0,0(r1); \
+1: cmp cr0,r0,r0; \
+ bne 1b; \
+ IDLE_INST; \
+ b .
+
+ .text
+
+/*
+ * Used by threads when the lock bit of core_idle_state is set.
+ * Threads will spin in HMT_LOW until the lock bit is cleared.
+ * r14 - pointer to core_idle_state
+ * r15 - used to load contents of core_idle_state
+ */
+
+core_idle_lock_held:
+ HMT_LOW
+3: lwz r15,0(r14)
+ andi. r15,r15,PNV_CORE_IDLE_LOCK_BIT
+ bne 3b
+ HMT_MEDIUM
+ lwarx r15,0,r14
+ blr
+
+/*
+ * Pass requested state in r3:
+ * r3 - PNV_THREAD_NAP/SLEEP/WINKLE
+ *
+ * To check IRQ_HAPPENED in r4
+ * 0 - don't check
+ * 1 - check
+ */
+_GLOBAL(power7_powersave_common)
+ /* Use r3 to pass state nap/sleep/winkle */
+ /* NAP is a state loss, we create a regs frame on the
+ * stack, fill it up with the state we care about and
+ * stick a pointer to it in PACAR1. We really only
+ * need to save PC, some CR bits and the NV GPRs,
+ * but for now an interrupt frame will do.
+ */
+ mflr r0
+ std r0,16(r1)
+ stdu r1,-INT_FRAME_SIZE(r1)
+ std r0,_LINK(r1)
+ std r0,_NIP(r1)
+
+ /* Hard disable interrupts */
+ mfmsr r9
+ rldicl r9,r9,48,1
+ rotldi r9,r9,16
+ mtmsrd r9,1 /* hard-disable interrupts */
+
+ /* Check if something happened while soft-disabled */
+ lbz r0,PACAIRQHAPPENED(r13)
+ andi. r0,r0,~PACA_IRQ_HARD_DIS@l
+ beq 1f
+ cmpwi cr0,r4,0
+ beq 1f
+ addi r1,r1,INT_FRAME_SIZE
+ ld r0,16(r1)
+ li r3,0 /* Return 0 (no nap) */
+ mtlr r0
+ blr
+
+1: /* We mark irqs hard disabled as this is the state we'll
+ * be in when returning and we need to tell arch_local_irq_restore()
+ * about it
+ */
+ li r0,PACA_IRQ_HARD_DIS
+ stb r0,PACAIRQHAPPENED(r13)
+
+ /* We haven't lost state ... yet */
+ li r0,0
+ stb r0,PACA_NAPSTATELOST(r13)
+
+ /* Continue saving state */
+ SAVE_GPR(2, r1)
+ SAVE_NVGPRS(r1)
+ mfcr r4
+ std r4,_CCR(r1)
+ std r9,_MSR(r1)
+ std r1,PACAR1(r13)
+
+ /*
+ * Go to real mode to do the nap, as required by the architecture.
+ * Also, we need to be in real mode before setting hwthread_state,
+ * because as soon as we do that, another thread can switch
+ * the MMU context to the guest.
+ */
+ LOAD_REG_IMMEDIATE(r5, MSR_IDLE)
+ li r6, MSR_RI
+ andc r6, r9, r6
+ LOAD_REG_ADDR(r7, power7_enter_nap_mode)
+ mtmsrd r6, 1 /* clear RI before setting SRR0/1 */
+ mtspr SPRN_SRR0, r7
+ mtspr SPRN_SRR1, r5
+ rfid
+
+ .globl power7_enter_nap_mode
+power7_enter_nap_mode:
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ /* Tell KVM we're napping */
+ li r4,KVM_HWTHREAD_IN_NAP
+ stb r4,HSTATE_HWTHREAD_STATE(r13)
+#endif
+ stb r3,PACA_THREAD_IDLE_STATE(r13)
+ cmpwi cr3,r3,PNV_THREAD_SLEEP
+ bge cr3,2f
+ IDLE_STATE_ENTER_SEQ(PPC_NAP)
+ /* No return */
+2:
+ /* Sleep or winkle */
+ lbz r7,PACA_THREAD_MASK(r13)
+ ld r14,PACA_CORE_IDLE_STATE_PTR(r13)
+lwarx_loop1:
+ lwarx r15,0,r14
+
+ andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
+ bnel core_idle_lock_held
+
+ andc r15,r15,r7 /* Clear thread bit */
+
+ andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS
+
+/*
+ * If cr0 = 0, then current thread is the last thread of the core entering
+ * sleep. Last thread needs to execute the hardware bug workaround code if
+ * required by the platform.
+ * Make the workaround call unconditionally here. The below branch call is
+ * patched out when the idle states are discovered if the platform does not
+ * require it.
+ */
+.global pnv_fastsleep_workaround_at_entry
+pnv_fastsleep_workaround_at_entry:
+ beq fastsleep_workaround_at_entry
+
+ stwcx. r15,0,r14
+ bne- lwarx_loop1
+ isync
+
+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:
+ ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
+ stwcx. r15,0,r14
+ bne- lwarx_loop1
+ isync
+
+ /* Fast sleep workaround */
+ li r3,1
+ li r4,1
+ li r0,OPAL_CONFIG_CPU_IDLE_STATE
+ bl opal_call_realmode
+
+ /* Clear Lock bit */
+ li r0,0
+ lwsync
+ 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_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 */
+ LOAD_REG_ADDRBASE(r3,powersave_nap)
+ lwz r4,ADDROFF(powersave_nap)(r3)
+ cmpwi 0,r4,0
+ beqlr
+ li r3, 1
+ /* fall through */
+
+_GLOBAL(power7_nap)
+ mr r4,r3
+ li r3,PNV_THREAD_NAP
+ b power7_powersave_common
+ /* No return */
+
+_GLOBAL(power7_sleep)
+ li r3,PNV_THREAD_SLEEP
+ li r4,1
+ b power7_powersave_common
+ /* No return */
+
+_GLOBAL(power7_winkle)
+ li r3,PNV_THREAD_WINKLE
+ li r4,1
+ b power7_powersave_common
+ /* No return */
+
+#define CHECK_HMI_INTERRUPT \
+ mfspr r0,SPRN_SRR1; \
+BEGIN_FTR_SECTION_NESTED(66); \
+ rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \
+FTR_SECTION_ELSE_NESTED(66); \
+ rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \
+ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
+ cmpwi r0,0xa; /* Hypervisor maintenance ? */ \
+ bne 20f; \
+ /* Invoke opal call to handle hmi */ \
+ ld r2,PACATOC(r13); \
+ ld r1,PACAR1(r13); \
+ std r3,ORIG_GPR3(r1); /* Save original r3 */ \
+ li r0,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \
+ bl opal_call_realmode; \
+ ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \
+20: nop;
+
+
+/*
+ * Called from reset vector. Check whether we have woken up with
+ * hypervisor state loss. If yes, restore hypervisor state and return
+ * back to reset vector.
+ *
+ * r13 - Contents of HSPRG0
+ * cr3 - set to gt if waking up with partial/complete hypervisor state loss
+ */
+_GLOBAL(power7_restore_hyp_resource)
+ /*
+ * Check if last bit of HSPGR0 is set. This indicates whether we are
+ * waking up from winkle.
+ */
+ clrldi r5,r13,63
+ clrrdi r13,r13,1
+ cmpwi cr4,r5,1
+ mtspr SPRN_HSPRG0,r13
+
+ lbz r0,PACA_THREAD_IDLE_STATE(r13)
+ cmpwi cr2,r0,PNV_THREAD_NAP
+ bgt cr2,power7_wakeup_tb_loss /* Either sleep or Winkle */
+
+ /*
+ * We fall through here if PACA_THREAD_IDLE_STATE shows we are waking
+ * up from nap. At this stage CR3 shouldn't contains 'gt' since that
+ * indicates we are waking with hypervisor state loss from nap.
+ */
+ bgt cr3,.
+
+ blr /* Return back to System Reset vector from where
+ power7_restore_hyp_resource was invoked */
+
+
+_GLOBAL(power7_wakeup_tb_loss)
+ ld r2,PACATOC(r13);
+ ld r1,PACAR1(r13)
+ /*
+ * Before entering any idle state, the NVGPRs are saved in the stack
+ * and they are restored before switching to the process context. Hence
+ * until they are restored, they are free to be used.
+ *
+ * Save SRR1 and LR in NVGPRs as they might be clobbered in
+ * opal_call_realmode (called in CHECK_HMI_INTERRUPT). SRR1 is required
+ * to determine the wakeup reason if we branch to kvm_start_guest. LR
+ * is required to return back to reset vector after hypervisor state
+ * restore is complete.
+ */
+ mflr r17
+ mfspr r16,SPRN_SRR1
+BEGIN_FTR_SECTION
+ CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+
+ lbz r7,PACA_THREAD_MASK(r13)
+ ld r14,PACA_CORE_IDLE_STATE_PTR(r13)
+lwarx_loop2:
+ lwarx r15,0,r14
+ andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
+ /*
+ * Lock bit is set in one of the 2 cases-
+ * a. In the sleep/winkle enter path, the last thread is executing
+ * fastsleep workaround code.
+ * b. In the wake up path, another thread is executing fastsleep
+ * workaround undo code or resyncing timebase or restoring context
+ * In either case loop until the lock bit is cleared.
+ */
+ bnel 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 - 0b0100 if first thread to wakeup in subcore
+ * cr2 - 0b0100 if first thread to wakeup in core
+ * cr3- 0b0010 if waking up from sleep or winkle
+ * cr4 - 0b0100 if waking up from winkle
+ */
+
+ or r15,r15,r7 /* Set thread bit */
+
+ beq cr1,first_thread_in_subcore
+
+ /* Not first thread in subcore to wake up */
+ stwcx. r15,0,r14
+ bne- lwarx_loop2
+ isync
+ b common_exit
+
+first_thread_in_subcore:
+ /* First thread in subcore to wakeup */
+ ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
+ stwcx. r15,0,r14
+ bne- lwarx_loop2
+ isync
+
+ /*
+ * If waking up from sleep, subcore state is not lost. Hence
+ * skip subcore state restore
+ */
+ bne cr4,subcore_state_restored
+
+ /* Restore per-subcore state */
+ ld r4,_SDR1(r1)
+ mtspr SPRN_SDR1,r4
+ ld r4,_RPR(r1)
+ mtspr SPRN_RPR,r4
+ ld r4,_AMOR(r1)
+ mtspr SPRN_AMOR,r4
+
+subcore_state_restored:
+ /*
+ * Check if the thread is also the first thread in the core. If not,
+ * skip to clear_lock.
+ */
+ bne cr2,clear_lock
+
+first_thread_in_core:
+
+ /*
+ * First thread in the core waking up from fastsleep. It needs to
+ * call the fastsleep workaround code if the platform requires it.
+ * Call it unconditionally here. The below branch instruction will
+ * be patched out when the idle states are discovered if platform
+ * does not require workaround.
+ */
+.global pnv_fastsleep_workaround_at_exit
+pnv_fastsleep_workaround_at_exit:
+ b fastsleep_workaround_at_exit
+
+timebase_resync:
+ /* Do timebase resync if we are waking up from sleep. Use cr3 value
+ * set in exceptions-64s.S */
+ ble cr3,clear_lock
+ /* Time base re-sync */
+ li r0,OPAL_RESYNC_TIMEBASE
+ bl opal_call_realmode;
+ /* TODO: Check r3 for failure */
+
+ /*
+ * If waking up from sleep, per core state is not lost, skip to
+ * clear_lock.
+ */
+ bne cr4,clear_lock
+
+ /* Restore per core state */
+ ld r4,_TSCR(r1)
+ mtspr SPRN_TSCR,r4
+ ld r4,_WORC(r1)
+ mtspr SPRN_WORC,r4
+
+clear_lock:
+ andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS
+ lwsync
+ stw r15,0(r14)
+
+common_exit:
+ /*
+ * Common to all threads.
+ *
+ * If waking up from sleep, hypervisor state is not lost. Hence
+ * skip hypervisor state restore.
+ */
+ bne cr4,hypervisor_state_restored
+
+ /* Waking up from winkle */
+
+ /* Restore per thread state */
+ bl __restore_cpu_power8
+
+ /* Restore SLB from PACA */
+ ld r8,PACA_SLBSHADOWPTR(r13)
+
+ .rept SLB_NUM_BOLTED
+ li r3, SLBSHADOW_SAVEAREA
+ LDX_BE r5, r8, r3
+ addi r3, r3, 8
+ LDX_BE r6, r8, r3
+ andis. r7,r5,SLB_ESID_V@h
+ beq 1f
+ slbmte r6,r5
+1: addi r8,r8,16
+ .endr
+
+ ld r4,_SPURR(r1)
+ mtspr SPRN_SPURR,r4
+ ld r4,_PURR(r1)
+ mtspr SPRN_PURR,r4
+ ld r4,_DSCR(r1)
+ mtspr SPRN_DSCR,r4
+ ld r4,_WORT(r1)
+ mtspr SPRN_WORT,r4
+
+hypervisor_state_restored:
+
+ mtspr SPRN_SRR1,r16
+ mtlr r17
+ blr /* Return back to System Reset vector from where
+ power7_restore_hyp_resource was invoked */
+
+fastsleep_workaround_at_exit:
+ li r3,1
+ li r4,0
+ li r0,OPAL_CONFIG_CPU_IDLE_STATE
+ bl opal_call_realmode
+ b timebase_resync
+
+/*
+ * R3 here contains the value that will be returned to the caller
+ * of power7_nap.
+ */
+_GLOBAL(power7_wakeup_loss)
+ ld r1,PACAR1(r13)
+BEGIN_FTR_SECTION
+ CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+ REST_NVGPRS(r1)
+ REST_GPR(2, r1)
+ ld r6,_CCR(r1)
+ ld r4,_MSR(r1)
+ ld r5,_NIP(r1)
+ addi r1,r1,INT_FRAME_SIZE
+ mtcr r6
+ mtspr SPRN_SRR1,r4
+ mtspr SPRN_SRR0,r5
+ rfid
+
+/*
+ * R3 here contains the value that will be returned to the caller
+ * of power7_nap.
+ */
+_GLOBAL(power7_wakeup_noloss)
+ lbz r0,PACA_NAPSTATELOST(r13)
+ cmpwi r0,0
+ bne power7_wakeup_loss
+BEGIN_FTR_SECTION
+ CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+ ld r1,PACAR1(r13)
+ ld r6,_CCR(r1)
+ ld r4,_MSR(r1)
+ ld r5,_NIP(r1)
+ addi r1,r1,INT_FRAME_SIZE
+ mtcr r6
+ mtspr SPRN_SRR1,r4
+ mtspr SPRN_SRR0,r5
+ rfid
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
deleted file mode 100644
index d5def06..0000000
--- a/arch/powerpc/kernel/idle_power7.S
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * This file contains the power_save function for Power7 CPUs.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/ppc-opcode.h>
-#include <asm/hw_irq.h>
-#include <asm/kvm_book3s_asm.h>
-#include <asm/opal.h>
-#include <asm/cpuidle.h>
-#include <asm/book3s/64/mmu-hash.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 _WORT GPR10
-#define _WORC GPR11
-
-/* Idle state entry routines */
-
-#define IDLE_STATE_ENTER_SEQ(IDLE_INST) \
- /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
- std r0,0(r1); \
- ptesync; \
- ld r0,0(r1); \
-1: cmp cr0,r0,r0; \
- bne 1b; \
- IDLE_INST; \
- b .
-
- .text
-
-/*
- * Used by threads when the lock bit of core_idle_state is set.
- * Threads will spin in HMT_LOW until the lock bit is cleared.
- * r14 - pointer to core_idle_state
- * r15 - used to load contents of core_idle_state
- */
-
-core_idle_lock_held:
- HMT_LOW
-3: lwz r15,0(r14)
- andi. r15,r15,PNV_CORE_IDLE_LOCK_BIT
- bne 3b
- HMT_MEDIUM
- lwarx r15,0,r14
- blr
-
-/*
- * Pass requested state in r3:
- * r3 - PNV_THREAD_NAP/SLEEP/WINKLE
- *
- * To check IRQ_HAPPENED in r4
- * 0 - don't check
- * 1 - check
- */
-_GLOBAL(power7_powersave_common)
- /* Use r3 to pass state nap/sleep/winkle */
- /* NAP is a state loss, we create a regs frame on the
- * stack, fill it up with the state we care about and
- * stick a pointer to it in PACAR1. We really only
- * need to save PC, some CR bits and the NV GPRs,
- * but for now an interrupt frame will do.
- */
- mflr r0
- std r0,16(r1)
- stdu r1,-INT_FRAME_SIZE(r1)
- std r0,_LINK(r1)
- std r0,_NIP(r1)
-
- /* Hard disable interrupts */
- mfmsr r9
- rldicl r9,r9,48,1
- rotldi r9,r9,16
- mtmsrd r9,1 /* hard-disable interrupts */
-
- /* Check if something happened while soft-disabled */
- lbz r0,PACAIRQHAPPENED(r13)
- andi. r0,r0,~PACA_IRQ_HARD_DIS@l
- beq 1f
- cmpwi cr0,r4,0
- beq 1f
- addi r1,r1,INT_FRAME_SIZE
- ld r0,16(r1)
- li r3,0 /* Return 0 (no nap) */
- mtlr r0
- blr
-
-1: /* We mark irqs hard disabled as this is the state we'll
- * be in when returning and we need to tell arch_local_irq_restore()
- * about it
- */
- li r0,PACA_IRQ_HARD_DIS
- stb r0,PACAIRQHAPPENED(r13)
-
- /* We haven't lost state ... yet */
- li r0,0
- stb r0,PACA_NAPSTATELOST(r13)
-
- /* Continue saving state */
- SAVE_GPR(2, r1)
- SAVE_NVGPRS(r1)
- mfcr r4
- std r4,_CCR(r1)
- std r9,_MSR(r1)
- std r1,PACAR1(r13)
-
- /*
- * Go to real mode to do the nap, as required by the architecture.
- * Also, we need to be in real mode before setting hwthread_state,
- * because as soon as we do that, another thread can switch
- * the MMU context to the guest.
- */
- LOAD_REG_IMMEDIATE(r5, MSR_IDLE)
- li r6, MSR_RI
- andc r6, r9, r6
- LOAD_REG_ADDR(r7, power7_enter_nap_mode)
- mtmsrd r6, 1 /* clear RI before setting SRR0/1 */
- mtspr SPRN_SRR0, r7
- mtspr SPRN_SRR1, r5
- rfid
-
- .globl power7_enter_nap_mode
-power7_enter_nap_mode:
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
- /* Tell KVM we're napping */
- li r4,KVM_HWTHREAD_IN_NAP
- stb r4,HSTATE_HWTHREAD_STATE(r13)
-#endif
- stb r3,PACA_THREAD_IDLE_STATE(r13)
- cmpwi cr3,r3,PNV_THREAD_SLEEP
- bge cr3,2f
- IDLE_STATE_ENTER_SEQ(PPC_NAP)
- /* No return */
-2:
- /* Sleep or winkle */
- lbz r7,PACA_THREAD_MASK(r13)
- ld r14,PACA_CORE_IDLE_STATE_PTR(r13)
-lwarx_loop1:
- lwarx r15,0,r14
-
- andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
- bnel core_idle_lock_held
-
- andc r15,r15,r7 /* Clear thread bit */
-
- andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS
-
-/*
- * If cr0 = 0, then current thread is the last thread of the core entering
- * sleep. Last thread needs to execute the hardware bug workaround code if
- * required by the platform.
- * Make the workaround call unconditionally here. The below branch call is
- * patched out when the idle states are discovered if the platform does not
- * require it.
- */
-.global pnv_fastsleep_workaround_at_entry
-pnv_fastsleep_workaround_at_entry:
- beq fastsleep_workaround_at_entry
-
- stwcx. r15,0,r14
- bne- lwarx_loop1
- isync
-
-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:
- ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
- stwcx. r15,0,r14
- bne- lwarx_loop1
- isync
-
- /* Fast sleep workaround */
- li r3,1
- li r4,1
- li r0,OPAL_CONFIG_CPU_IDLE_STATE
- bl opal_call_realmode
-
- /* Clear Lock bit */
- li r0,0
- lwsync
- 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_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 */
- LOAD_REG_ADDRBASE(r3,powersave_nap)
- lwz r4,ADDROFF(powersave_nap)(r3)
- cmpwi 0,r4,0
- beqlr
- li r3, 1
- /* fall through */
-
-_GLOBAL(power7_nap)
- mr r4,r3
- li r3,PNV_THREAD_NAP
- b power7_powersave_common
- /* No return */
-
-_GLOBAL(power7_sleep)
- li r3,PNV_THREAD_SLEEP
- li r4,1
- b power7_powersave_common
- /* No return */
-
-_GLOBAL(power7_winkle)
- li r3,PNV_THREAD_WINKLE
- li r4,1
- b power7_powersave_common
- /* No return */
-
-#define CHECK_HMI_INTERRUPT \
- mfspr r0,SPRN_SRR1; \
-BEGIN_FTR_SECTION_NESTED(66); \
- rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \
-FTR_SECTION_ELSE_NESTED(66); \
- rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \
-ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
- cmpwi r0,0xa; /* Hypervisor maintenance ? */ \
- bne 20f; \
- /* Invoke opal call to handle hmi */ \
- ld r2,PACATOC(r13); \
- ld r1,PACAR1(r13); \
- std r3,ORIG_GPR3(r1); /* Save original r3 */ \
- li r0,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \
- bl opal_call_realmode; \
- ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \
-20: nop;
-
-
-/*
- * Called from reset vector. Check whether we have woken up with
- * hypervisor state loss. If yes, restore hypervisor state and return
- * back to reset vector.
- *
- * r13 - Contents of HSPRG0
- * cr3 - set to gt if waking up with partial/complete hypervisor state loss
- */
-_GLOBAL(power7_restore_hyp_resource)
- /*
- * Check if last bit of HSPGR0 is set. This indicates whether we are
- * waking up from winkle.
- */
- clrldi r5,r13,63
- clrrdi r13,r13,1
- cmpwi cr4,r5,1
- mtspr SPRN_HSPRG0,r13
-
- lbz r0,PACA_THREAD_IDLE_STATE(r13)
- cmpwi cr2,r0,PNV_THREAD_NAP
- bgt cr2,power7_wakeup_tb_loss /* Either sleep or Winkle */
-
- /*
- * We fall through here if PACA_THREAD_IDLE_STATE shows we are waking
- * up from nap. At this stage CR3 shouldn't contains 'gt' since that
- * indicates we are waking with hypervisor state loss from nap.
- */
- bgt cr3,.
-
- blr /* Return back to System Reset vector from where
- power7_restore_hyp_resource was invoked */
-
-
-_GLOBAL(power7_wakeup_tb_loss)
- ld r2,PACATOC(r13);
- ld r1,PACAR1(r13)
- /*
- * Before entering any idle state, the NVGPRs are saved in the stack
- * and they are restored before switching to the process context. Hence
- * until they are restored, they are free to be used.
- *
- * Save SRR1 and LR in NVGPRs as they might be clobbered in
- * opal_call_realmode (called in CHECK_HMI_INTERRUPT). SRR1 is required
- * to determine the wakeup reason if we branch to kvm_start_guest. LR
- * is required to return back to reset vector after hypervisor state
- * restore is complete.
- */
- mflr r17
- mfspr r16,SPRN_SRR1
-BEGIN_FTR_SECTION
- CHECK_HMI_INTERRUPT
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
-
- lbz r7,PACA_THREAD_MASK(r13)
- ld r14,PACA_CORE_IDLE_STATE_PTR(r13)
-lwarx_loop2:
- lwarx r15,0,r14
- andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
- /*
- * Lock bit is set in one of the 2 cases-
- * a. In the sleep/winkle enter path, the last thread is executing
- * fastsleep workaround code.
- * b. In the wake up path, another thread is executing fastsleep
- * workaround undo code or resyncing timebase or restoring context
- * In either case loop until the lock bit is cleared.
- */
- bnel 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 - 0b0100 if first thread to wakeup in subcore
- * cr2 - 0b0100 if first thread to wakeup in core
- * cr3- 0b0010 if waking up from sleep or winkle
- * cr4 - 0b0100 if waking up from winkle
- */
-
- or r15,r15,r7 /* Set thread bit */
-
- beq cr1,first_thread_in_subcore
-
- /* Not first thread in subcore to wake up */
- stwcx. r15,0,r14
- bne- lwarx_loop2
- isync
- b common_exit
-
-first_thread_in_subcore:
- /* First thread in subcore to wakeup */
- ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
- stwcx. r15,0,r14
- bne- lwarx_loop2
- isync
-
- /*
- * If waking up from sleep, subcore state is not lost. Hence
- * skip subcore state restore
- */
- bne cr4,subcore_state_restored
-
- /* Restore per-subcore state */
- ld r4,_SDR1(r1)
- mtspr SPRN_SDR1,r4
- ld r4,_RPR(r1)
- mtspr SPRN_RPR,r4
- ld r4,_AMOR(r1)
- mtspr SPRN_AMOR,r4
-
-subcore_state_restored:
- /*
- * Check if the thread is also the first thread in the core. If not,
- * skip to clear_lock.
- */
- bne cr2,clear_lock
-
-first_thread_in_core:
-
- /*
- * First thread in the core waking up from fastsleep. It needs to
- * call the fastsleep workaround code if the platform requires it.
- * Call it unconditionally here. The below branch instruction will
- * be patched out when the idle states are discovered if platform
- * does not require workaround.
- */
-.global pnv_fastsleep_workaround_at_exit
-pnv_fastsleep_workaround_at_exit:
- b fastsleep_workaround_at_exit
-
-timebase_resync:
- /* Do timebase resync if we are waking up from sleep. Use cr3 value
- * set in exceptions-64s.S */
- ble cr3,clear_lock
- /* Time base re-sync */
- li r0,OPAL_RESYNC_TIMEBASE
- bl opal_call_realmode;
- /* TODO: Check r3 for failure */
-
- /*
- * If waking up from sleep, per core state is not lost, skip to
- * clear_lock.
- */
- bne cr4,clear_lock
-
- /* Restore per core state */
- ld r4,_TSCR(r1)
- mtspr SPRN_TSCR,r4
- ld r4,_WORC(r1)
- mtspr SPRN_WORC,r4
-
-clear_lock:
- andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS
- lwsync
- stw r15,0(r14)
-
-common_exit:
- /*
- * Common to all threads.
- *
- * If waking up from sleep, hypervisor state is not lost. Hence
- * skip hypervisor state restore.
- */
- bne cr4,hypervisor_state_restored
-
- /* Waking up from winkle */
-
- /* Restore per thread state */
- bl __restore_cpu_power8
-
- /* Restore SLB from PACA */
- ld r8,PACA_SLBSHADOWPTR(r13)
-
- .rept SLB_NUM_BOLTED
- li r3, SLBSHADOW_SAVEAREA
- LDX_BE r5, r8, r3
- addi r3, r3, 8
- LDX_BE r6, r8, r3
- andis. r7,r5,SLB_ESID_V@h
- beq 1f
- slbmte r6,r5
-1: addi r8,r8,16
- .endr
-
- ld r4,_SPURR(r1)
- mtspr SPRN_SPURR,r4
- ld r4,_PURR(r1)
- mtspr SPRN_PURR,r4
- ld r4,_DSCR(r1)
- mtspr SPRN_DSCR,r4
- ld r4,_WORT(r1)
- mtspr SPRN_WORT,r4
-
-hypervisor_state_restored:
-
- mtspr SPRN_SRR1,r16
- mtlr r17
- blr /* Return back to System Reset vector from where
- power7_restore_hyp_resource was invoked */
-
-fastsleep_workaround_at_exit:
- li r3,1
- li r4,0
- li r0,OPAL_CONFIG_CPU_IDLE_STATE
- bl opal_call_realmode
- b timebase_resync
-
-/*
- * R3 here contains the value that will be returned to the caller
- * of power7_nap.
- */
-_GLOBAL(power7_wakeup_loss)
- ld r1,PACAR1(r13)
-BEGIN_FTR_SECTION
- CHECK_HMI_INTERRUPT
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
- REST_NVGPRS(r1)
- REST_GPR(2, r1)
- ld r6,_CCR(r1)
- ld r4,_MSR(r1)
- ld r5,_NIP(r1)
- addi r1,r1,INT_FRAME_SIZE
- mtcr r6
- mtspr SPRN_SRR1,r4
- mtspr SPRN_SRR0,r5
- rfid
-
-/*
- * R3 here contains the value that will be returned to the caller
- * of power7_nap.
- */
-_GLOBAL(power7_wakeup_noloss)
- lbz r0,PACA_NAPSTATELOST(r13)
- cmpwi r0,0
- bne power7_wakeup_loss
-BEGIN_FTR_SECTION
- CHECK_HMI_INTERRUPT
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
- ld r1,PACAR1(r13)
- ld r6,_CCR(r1)
- ld r4,_MSR(r1)
- ld r5,_NIP(r1)
- addi r1,r1,INT_FRAME_SIZE
- mtcr r6
- mtspr SPRN_SRR1,r4
- mtspr SPRN_SRR0,r5
- rfid
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 04/11] powerpc/powernv: Rename reusable idle functions to hardware agnostic names
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (2 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 03/11] powerpc/powernv: Rename idle_power7.S to idle_book3s.S Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 05/11] powerpc/powernv: Make pnv_powersave_common more generic Shreyas B. Prabhu
` (7 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
Functions like power7_wakeup_loss, power7_wakeup_noloss,
power7_wakeup_tb_loss are used by POWER7 and POWER8 hardware. They can
also be used by POWER9. Hence rename these functions hardware agnostic
names.
Suggested-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- No changes since v4
Changes in v4:
==============
- renaming power7_powersave_common to pnv_powersave_common
- renaming power7_enter_nap_mode to pnv_enter_arch207_idle_mode
arch/powerpc/kernel/exceptions-64s.S | 8 ++++----
arch/powerpc/kernel/idle_book3s.S | 33 +++++++++++++++++----------------
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 ++--
3 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 4a74d6a..2a123cd 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -108,7 +108,7 @@ BEGIN_FTR_SECTION
cmpwi cr3,r13,2
GET_PACA(r13)
- bl power7_restore_hyp_resource
+ bl pnv_restore_hyp_resource
li r0,PNV_THREAD_RUNNING
stb r0,PACA_THREAD_IDLE_STATE(r13) /* Clear thread state */
@@ -128,8 +128,8 @@ BEGIN_FTR_SECTION
/* Return SRR1 from power7_nap() */
mfspr r3,SPRN_SRR1
blt cr3,2f
- b power7_wakeup_loss
-2: b power7_wakeup_noloss
+ b pnv_wakeup_loss
+2: b pnv_wakeup_noloss
9:
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
@@ -1269,7 +1269,7 @@ machine_check_handle_early:
GET_PACA(r13)
ld r1,PACAR1(r13)
li r3,PNV_THREAD_NAP
- b power7_enter_nap_mode
+ b pnv_enter_arch207_idle_mode
4:
#endif
/*
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index d5def06..34dbfc9 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -1,5 +1,6 @@
/*
- * This file contains the power_save function for Power7 CPUs.
+ * This file contains idle entry/exit functions for POWER7 and
+ * POWER8 CPUs.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -75,7 +76,7 @@ core_idle_lock_held:
* 0 - don't check
* 1 - check
*/
-_GLOBAL(power7_powersave_common)
+_GLOBAL(pnv_powersave_common)
/* Use r3 to pass state nap/sleep/winkle */
/* NAP is a state loss, we create a regs frame on the
* stack, fill it up with the state we care about and
@@ -135,14 +136,14 @@ _GLOBAL(power7_powersave_common)
LOAD_REG_IMMEDIATE(r5, MSR_IDLE)
li r6, MSR_RI
andc r6, r9, r6
- LOAD_REG_ADDR(r7, power7_enter_nap_mode)
+ LOAD_REG_ADDR(r7, pnv_enter_arch207_idle_mode)
mtmsrd r6, 1 /* clear RI before setting SRR0/1 */
mtspr SPRN_SRR0, r7
mtspr SPRN_SRR1, r5
rfid
- .globl power7_enter_nap_mode
-power7_enter_nap_mode:
+ .globl pnv_enter_arch207_idle_mode
+pnv_enter_arch207_idle_mode:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/* Tell KVM we're napping */
li r4,KVM_HWTHREAD_IN_NAP
@@ -242,19 +243,19 @@ _GLOBAL(power7_idle)
_GLOBAL(power7_nap)
mr r4,r3
li r3,PNV_THREAD_NAP
- b power7_powersave_common
+ b pnv_powersave_common
/* No return */
_GLOBAL(power7_sleep)
li r3,PNV_THREAD_SLEEP
li r4,1
- b power7_powersave_common
+ b pnv_powersave_common
/* No return */
_GLOBAL(power7_winkle)
li r3,PNV_THREAD_WINKLE
li r4,1
- b power7_powersave_common
+ b pnv_powersave_common
/* No return */
#define CHECK_HMI_INTERRUPT \
@@ -284,7 +285,7 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
* r13 - Contents of HSPRG0
* cr3 - set to gt if waking up with partial/complete hypervisor state loss
*/
-_GLOBAL(power7_restore_hyp_resource)
+_GLOBAL(pnv_restore_hyp_resource)
/*
* Check if last bit of HSPGR0 is set. This indicates whether we are
* waking up from winkle.
@@ -296,7 +297,7 @@ _GLOBAL(power7_restore_hyp_resource)
lbz r0,PACA_THREAD_IDLE_STATE(r13)
cmpwi cr2,r0,PNV_THREAD_NAP
- bgt cr2,power7_wakeup_tb_loss /* Either sleep or Winkle */
+ bgt cr2,pnv_wakeup_tb_loss /* Either sleep or Winkle */
/*
* We fall through here if PACA_THREAD_IDLE_STATE shows we are waking
@@ -306,10 +307,10 @@ _GLOBAL(power7_restore_hyp_resource)
bgt cr3,.
blr /* Return back to System Reset vector from where
- power7_restore_hyp_resource was invoked */
+ pnv_restore_hyp_resource was invoked */
-_GLOBAL(power7_wakeup_tb_loss)
+_GLOBAL(pnv_wakeup_tb_loss)
ld r2,PACATOC(r13);
ld r1,PACAR1(r13)
/*
@@ -476,7 +477,7 @@ hypervisor_state_restored:
mtspr SPRN_SRR1,r16
mtlr r17
blr /* Return back to System Reset vector from where
- power7_restore_hyp_resource was invoked */
+ pnv_restore_hyp_resource was invoked */
fastsleep_workaround_at_exit:
li r3,1
@@ -489,7 +490,7 @@ fastsleep_workaround_at_exit:
* R3 here contains the value that will be returned to the caller
* of power7_nap.
*/
-_GLOBAL(power7_wakeup_loss)
+_GLOBAL(pnv_wakeup_loss)
ld r1,PACAR1(r13)
BEGIN_FTR_SECTION
CHECK_HMI_INTERRUPT
@@ -509,10 +510,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
* R3 here contains the value that will be returned to the caller
* of power7_nap.
*/
-_GLOBAL(power7_wakeup_noloss)
+_GLOBAL(pnv_wakeup_noloss)
lbz r0,PACA_NAPSTATELOST(r13)
cmpwi r0,0
- bne power7_wakeup_loss
+ bne pnv_wakeup_loss
BEGIN_FTR_SECTION
CHECK_HMI_INTERRUPT
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index e571ad2..86f0cae 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -392,7 +392,7 @@ kvm_no_guest:
cmpwi r3, 0
bne 54f
/*
- * We jump to power7_wakeup_loss, which will return to the caller
+ * We jump to pnv_wakeup_loss, which will return to the caller
* of power7_nap in the powernv cpu offline loop. The value we
* put in r3 becomes the return value for power7_nap.
*/
@@ -401,7 +401,7 @@ kvm_no_guest:
rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
mtspr SPRN_LPCR, r4
li r3, 0
- b power7_wakeup_loss
+ b pnv_wakeup_loss
53: HMT_LOW
ld r5, HSTATE_KVM_VCORE(r13)
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 05/11] powerpc/powernv: Make pnv_powersave_common more generic
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (3 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 04/11] powerpc/powernv: Rename reusable idle functions to hardware agnostic names Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 06/11] powerpc/powernv: abstraction for saving SPRs before entering deep idle states Shreyas B. Prabhu
` (6 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
pnv_powersave_common does common steps needed before entering idle
state and eventually changes MSR to MSR_IDLE and does rfid to
pnv_enter_arch207_idle_mode.
Move the updation of HSTATE_HWTHREAD_STATE to pnv_powersave_common
from pnv_enter_arch207_idle_mode and make it more generic by passing the
rfid address as a function parameter.
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- No changes since v4
Changes in v4:
==============
- Moved renaming of power7_powersave_common to earlier patch
Changes in v3:
==============
- Moved HSTATE_HWTHREAD_STATE updation to power_powersave_common
arch/powerpc/kernel/idle_book3s.S | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index 34dbfc9..a8397e3 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -75,6 +75,8 @@ core_idle_lock_held:
* To check IRQ_HAPPENED in r4
* 0 - don't check
* 1 - check
+ *
+ * Address to 'rfid' to in r5
*/
_GLOBAL(pnv_powersave_common)
/* Use r3 to pass state nap/sleep/winkle */
@@ -127,28 +129,28 @@ _GLOBAL(pnv_powersave_common)
std r9,_MSR(r1)
std r1,PACAR1(r13)
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ /* Tell KVM we're entering idle */
+ li r4,KVM_HWTHREAD_IN_NAP
+ stb r4,HSTATE_HWTHREAD_STATE(r13)
+#endif
+
/*
* Go to real mode to do the nap, as required by the architecture.
* Also, we need to be in real mode before setting hwthread_state,
* because as soon as we do that, another thread can switch
* the MMU context to the guest.
*/
- LOAD_REG_IMMEDIATE(r5, MSR_IDLE)
+ LOAD_REG_IMMEDIATE(r7, MSR_IDLE)
li r6, MSR_RI
andc r6, r9, r6
- LOAD_REG_ADDR(r7, pnv_enter_arch207_idle_mode)
mtmsrd r6, 1 /* clear RI before setting SRR0/1 */
- mtspr SPRN_SRR0, r7
- mtspr SPRN_SRR1, r5
+ mtspr SPRN_SRR0, r5
+ mtspr SPRN_SRR1, r7
rfid
.globl pnv_enter_arch207_idle_mode
pnv_enter_arch207_idle_mode:
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
- /* Tell KVM we're napping */
- li r4,KVM_HWTHREAD_IN_NAP
- stb r4,HSTATE_HWTHREAD_STATE(r13)
-#endif
stb r3,PACA_THREAD_IDLE_STATE(r13)
cmpwi cr3,r3,PNV_THREAD_SLEEP
bge cr3,2f
@@ -243,18 +245,21 @@ _GLOBAL(power7_idle)
_GLOBAL(power7_nap)
mr r4,r3
li r3,PNV_THREAD_NAP
+ LOAD_REG_ADDR(r5, pnv_enter_arch207_idle_mode)
b pnv_powersave_common
/* No return */
_GLOBAL(power7_sleep)
li r3,PNV_THREAD_SLEEP
li r4,1
+ LOAD_REG_ADDR(r5, pnv_enter_arch207_idle_mode)
b pnv_powersave_common
/* No return */
_GLOBAL(power7_winkle)
li r3,PNV_THREAD_WINKLE
li r4,1
+ LOAD_REG_ADDR(r5, pnv_enter_arch207_idle_mode)
b pnv_powersave_common
/* No return */
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 06/11] powerpc/powernv: abstraction for saving SPRs before entering deep idle states
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (4 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 05/11] powerpc/powernv: Make pnv_powersave_common more generic Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction Shreyas B. Prabhu
` (5 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
Create a function for saving SPRs before entering deep idle states.
This function can be reused for POWER9 deep idle states.
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- No changes since v3
Changes in v3:
=============
- Newly added in v3
arch/powerpc/kernel/idle_book3s.S | 54 +++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index a8397e3..2f909a1 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -53,6 +53,36 @@
.text
/*
+ * Used by threads before entering deep idle states. Saves SPRs
+ * in interrupt stack frame
+ */
+save_sprs_to_stack:
+ /*
+ * 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_WORT
+ std r3,_WORT(r1)
+ mfspr r3,SPRN_WORC
+ std r3,_WORC(r1)
+
+ blr
+
+/*
* Used by threads when the lock bit of core_idle_state is set.
* Threads will spin in HMT_LOW until the lock bit is cleared.
* r14 - pointer to core_idle_state
@@ -209,28 +239,8 @@ fastsleep_workaround_at_entry:
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_WORT
- std r3,_WORT(r1)
- mfspr r3,SPRN_WORC
- std r3,_WORC(r1)
+ bl save_sprs_to_stack
+
IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
_GLOBAL(power7_idle)
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (5 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 06/11] powerpc/powernv: abstraction for saving SPRs before entering deep idle states Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-08 2:20 ` Michael Neuling
2016-07-07 20:47 ` [PATCH v7 08/11] cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of MAX_POWERNV_IDLE_STATES Shreyas B. Prabhu
` (4 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
POWER ISA v3 defines a new idle processor core mechanism. In summary,
a) new instruction named stop is added. This instruction replaces
instructions like nap, sleep, rvwinkle.
b) new per thread SPR named Processor Stop Status and Control Register
(PSSCR) is added which controls the behavior of stop instruction.
PSSCR layout:
----------------------------------------------------------
| PLS | /// | SD | ESL | EC | PSLL | /// | TR | MTL | RL |
----------------------------------------------------------
0 4 41 42 43 44 48 54 56 60
PSSCR key fields:
Bits 0:3 - Power-Saving Level Status. This field indicates the lowest
power-saving state the thread entered since stop instruction was last
executed.
Bit 42 - Enable State Loss
0 - No state is lost irrespective of other fields
1 - Allows state loss
Bits 44:47 - Power-Saving Level Limit
This limits the power-saving level that can be entered into.
Bits 60:63 - Requested Level
Used to specify which power-saving level must be entered on executing
stop instruction
This patch adds support for stop instruction and PSSCR handling.
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
Changes in v7
=============
- LMRR, LMSER and ADSR not restored since its not necessary
- power_stop0, power_stop renamed to power9_idle and power_idle_stop
- PSSCR template is now a macro instead of storing in paca
- power9_idle in C file instead of assembly
- Fixed TOC related bug
- Handling subcore within FTR section
- Functions in idle.c reordered and broken into multiple functions
- calling __restore_cpu_power8/9 via cur_cpu_spec->cpu_restore
Changes in v6
=============
- Save/restore new P9 SPRs when using deep idle states
Changes in v4:
==============
- Added PSSCR layout to commit message
- Improved / Fixed comments
- Fixed whitespace error in paca.h
- Using MAX_POSSIBLE_STOP_STATE macro instead of hardcoding 0xF as
max possible stop state
Changes in v3:
==============
- Instead of introducing new file idle_power_stop.S, P9 idle support
is added to idle_power_common.S using CPU_FTR sections.
- Fixed r4 reg clobbering in power_stop0
- Improved comments
Changes in v2:
==============
- Using CPU_FTR_ARCH_300 bit instead of CPU_FTR_STOP_INST
arch/powerpc/include/asm/cpuidle.h | 2 +
arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +-
arch/powerpc/include/asm/opal-api.h | 11 +-
arch/powerpc/include/asm/ppc-opcode.h | 4 +
arch/powerpc/include/asm/processor.h | 2 +
arch/powerpc/include/asm/reg.h | 10 ++
arch/powerpc/kernel/idle_book3s.S | 189 ++++++++++++++++++++++++------
arch/powerpc/platforms/powernv/idle.c | 174 ++++++++++++++++++++++-----
8 files changed, 328 insertions(+), 66 deletions(-)
diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/asm/cpuidle.h
index d2f99ca..3d7fc06 100644
--- a/arch/powerpc/include/asm/cpuidle.h
+++ b/arch/powerpc/include/asm/cpuidle.h
@@ -13,6 +13,8 @@
#ifndef __ASSEMBLY__
extern u32 pnv_fastsleep_workaround_at_entry[];
extern u32 pnv_fastsleep_workaround_at_exit[];
+
+extern u64 pnv_first_deep_stop_state;
#endif
#endif
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index 72b6225..d318d43 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -162,7 +162,7 @@ struct kvmppc_book3s_shadow_vcpu {
/* Values for kvm_state */
#define KVM_HWTHREAD_IN_KERNEL 0
-#define KVM_HWTHREAD_IN_NAP 1
+#define KVM_HWTHREAD_IN_IDLE 1
#define KVM_HWTHREAD_IN_KVM 2
#endif /* __ASM_KVM_BOOK3S_ASM_H__ */
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 72b5f27..6de1e4e 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -166,13 +166,20 @@
/* Device tree flags */
-/* Flags set in power-mgmt nodes in device tree if
- * respective idle states are supported in the platform.
+/*
+ * Flags set in power-mgmt nodes in device tree describing
+ * idle states that are supported in the platform.
*/
+
+#define OPAL_PM_TIMEBASE_STOP 0x00000002
+#define OPAL_PM_LOSE_HYP_CONTEXT 0x00002000
+#define OPAL_PM_LOSE_FULL_CONTEXT 0x00004000
#define OPAL_PM_NAP_ENABLED 0x00010000
#define OPAL_PM_SLEEP_ENABLED 0x00020000
#define OPAL_PM_WINKLE_ENABLED 0x00040000
#define OPAL_PM_SLEEP_ENABLED_ER1 0x00080000 /* with workaround */
+#define OPAL_PM_STOP_INST_FAST 0x00100000
+#define OPAL_PM_STOP_INST_DEEP 0x00200000
/*
* OPAL_CONFIG_CPU_IDLE_STATE parameters
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 9de9df1..81657a1 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -205,6 +205,8 @@
#define PPC_INST_SLEEP 0x4c0003a4
#define PPC_INST_WINKLE 0x4c0003e4
+#define PPC_INST_STOP 0x4c0002e4
+
/* A2 specific instructions */
#define PPC_INST_ERATWE 0x7c0001a6
#define PPC_INST_ERATRE 0x7c000166
@@ -394,6 +396,8 @@
#define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP)
#define PPC_WINKLE stringify_in_c(.long PPC_INST_WINKLE)
+#define PPC_STOP stringify_in_c(.long PPC_INST_STOP)
+
/* BHRB instructions */
#define PPC_CLRBHRB stringify_in_c(.long PPC_INST_CLRBHRB)
#define PPC_MFBHRBE(r, n) stringify_in_c(.long PPC_INST_BHRBE | \
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index b5925d5..68e3bf5 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -460,6 +460,8 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */
extern unsigned long power7_nap(int check_irq);
extern unsigned long power7_sleep(void);
extern unsigned long power7_winkle(void);
+extern unsigned long power9_idle_stop(unsigned long stop_level);
+
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(void);
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 320136f..387dc60 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -145,6 +145,15 @@
#define MSR_64BIT 0
#endif
+/* Power Management - Processor Stop Status and Control Register Fields */
+#define PSSCR_RL_MASK 0x0000000F /* Requested Level */
+#define PSSCR_MTL_MASK 0x000000F0 /* Maximum Transition Level */
+#define PSSCR_TR_MASK 0x00000300 /* Transition State */
+#define PSSCR_PSLL_MASK 0x000F0000 /* Power-Saving Level Limit */
+#define PSSCR_EC 0x00100000 /* Exit Criterion */
+#define PSSCR_ESL 0x00200000 /* Enable State Loss */
+#define PSSCR_SD 0x00400000 /* Status Disable */
+
/* Floating Point Status and Control Register (FPSCR) Fields */
#define FPSCR_FX 0x80000000 /* FPU exception summary */
#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
@@ -290,6 +299,7 @@
#define SPRN_PMICR 0x354 /* Power Management Idle Control Reg */
#define SPRN_PMSR 0x355 /* Power Management Status Reg */
#define SPRN_PMMAR 0x356 /* Power Management Memory Activity Register */
+#define SPRN_PSSCR 0x357 /* Processor Stop Status and Control Register (ISA 3.0) */
#define SPRN_PMCR 0x374 /* Power Management Control Register */
/* HFSCR and FSCR bit numbers are the same */
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index 2f909a1..601bbcc 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -1,6 +1,6 @@
/*
- * This file contains idle entry/exit functions for POWER7 and
- * POWER8 CPUs.
+ * This file contains idle entry/exit functions for POWER7,
+ * POWER8 and POWER9 CPUs.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,6 +21,7 @@
#include <asm/opal.h>
#include <asm/cpuidle.h>
#include <asm/book3s/64/mmu-hash.h>
+#include <asm/mmu.h>
#undef DEBUG
@@ -37,6 +38,11 @@
#define _AMOR GPR9
#define _WORT GPR10
#define _WORC GPR11
+#define _PTCR GPR12
+
+#define PSSCR_HV_TEMPLATE PSSCR_ESL | PSSCR_EC | \
+ PSSCR_PSLL_MASK | PSSCR_TR_MASK | \
+ PSSCR_MTL_MASK
/* Idle state entry routines */
@@ -61,8 +67,17 @@ save_sprs_to_stack:
* 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
*/
+BEGIN_FTR_SECTION
+ mfspr r3,SPRN_PTCR
+ std r3,_PTCR(r1)
+ /*
+ * Note - SDR1 is dropped in Power ISA v3. Hence not restoring
+ * SDR1 here
+ */
+FTR_SECTION_ELSE
mfspr r3,SPRN_SDR1
std r3,_SDR1(r1)
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
mfspr r3,SPRN_RPR
std r3,_RPR(r1)
mfspr r3,SPRN_SPURR
@@ -100,7 +115,8 @@ core_idle_lock_held:
/*
* Pass requested state in r3:
- * r3 - PNV_THREAD_NAP/SLEEP/WINKLE
+ * r3 - PNV_THREAD_NAP/SLEEP/WINKLE in POWER8
+ * - Requested STOP state in POWER9
*
* To check IRQ_HAPPENED in r4
* 0 - don't check
@@ -161,7 +177,7 @@ _GLOBAL(pnv_powersave_common)
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/* Tell KVM we're entering idle */
- li r4,KVM_HWTHREAD_IN_NAP
+ li r4,KVM_HWTHREAD_IN_IDLE
stb r4,HSTATE_HWTHREAD_STATE(r13)
#endif
@@ -243,6 +259,41 @@ enter_winkle:
IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
+/*
+ * r3 - requested stop state
+ */
+power_enter_stop:
+/*
+ * Check if the requested state is a deep idle state.
+ */
+ LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state)
+ ld r4,ADDROFF(pnv_first_deep_stop_state)(r5)
+ cmpd r3,r4
+ bge 2f
+ IDLE_STATE_ENTER_SEQ(PPC_STOP)
+2:
+/*
+ * Entering deep idle state.
+ * Clear thread bit in PACA_CORE_IDLE_STATE, save SPRs to
+ * stack and enter stop
+ */
+ lbz r7,PACA_THREAD_MASK(r13)
+ ld r14,PACA_CORE_IDLE_STATE_PTR(r13)
+
+lwarx_loop_stop:
+ lwarx r15,0,r14
+ andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
+ bnel core_idle_lock_held
+ andc r15,r15,r7 /* Clear thread bit */
+
+ stwcx. r15,0,r14
+ bne- lwarx_loop_stop
+ isync
+
+ bl save_sprs_to_stack
+
+ IDLE_STATE_ENTER_SEQ(PPC_STOP)
+
_GLOBAL(power7_idle)
/* Now check if user or arch enabled NAP mode */
LOAD_REG_ADDRBASE(r3,powersave_nap)
@@ -293,6 +344,17 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
/*
+ * r3 - requested stop state
+ */
+_GLOBAL(power9_idle_stop)
+ LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE)
+ or r4,r4,r3
+ mtspr SPRN_PSSCR, r4
+ li r4, 1
+ LOAD_REG_ADDR(r5,power_enter_stop)
+ b pnv_powersave_common
+ /* No return */
+/*
* Called from reset vector. Check whether we have woken up with
* hypervisor state loss. If yes, restore hypervisor state and return
* back to reset vector.
@@ -301,7 +363,33 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
* cr3 - set to gt if waking up with partial/complete hypervisor state loss
*/
_GLOBAL(pnv_restore_hyp_resource)
+ ld r2,PACATOC(r13);
+BEGIN_FTR_SECTION
+ /*
+ * POWER ISA 3. Use PSSCR to determine if we
+ * are waking up from deep idle state
+ */
+ LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state)
+ ld r4,ADDROFF(pnv_first_deep_stop_state)(r5)
+
+ mfspr r5,SPRN_PSSCR
/*
+ * 0-3 bits correspond to Power-Saving Level Status
+ * which indicates the idle state we are waking up from
+ */
+ rldicl r5,r5,4,60
+ cmpd cr4,r5,r4
+ bge cr4,pnv_wakeup_tb_loss
+ /*
+ * Waking up without hypervisor state loss. Return to
+ * reset vector
+ */
+ blr
+
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
+ /*
+ * POWER ISA 2.07 or less.
* Check if last bit of HSPGR0 is set. This indicates whether we are
* waking up from winkle.
*/
@@ -324,9 +412,17 @@ _GLOBAL(pnv_restore_hyp_resource)
blr /* Return back to System Reset vector from where
pnv_restore_hyp_resource was invoked */
-
+/*
+ * Called if waking up from idle state which can cause either partial or
+ * complete hyp state loss.
+ * In POWER8, called if waking up from fastsleep or winkle
+ * In POWER9, called if waking up from stop state >= pnv_first_deep_stop_state
+ *
+ * r13 - PACA
+ * cr3 - gt if waking up with partial/complete hypervisor state loss
+ * cr4 - eq if waking up from complete hypervisor state loss.
+ */
_GLOBAL(pnv_wakeup_tb_loss)
- ld r2,PACATOC(r13);
ld r1,PACAR1(r13)
/*
* Before entering any idle state, the NVGPRs are saved in the stack
@@ -361,35 +457,35 @@ lwarx_loop2:
bnel 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 - 0b0100 if first thread to wakeup in subcore
- * cr2 - 0b0100 if first thread to wakeup in core
- * cr3- 0b0010 if waking up from sleep or winkle
- * cr4 - 0b0100 if waking up from winkle
+ * cr2 - eq if first thread to wakeup in core
+ * cr3- gt if waking up with partial/complete hypervisor state loss
+ * cr4 - eq if waking up from complete hypervisor state loss.
*/
- or r15,r15,r7 /* Set thread bit */
-
- beq cr1,first_thread_in_subcore
-
- /* Not first thread in subcore to wake up */
- stwcx. r15,0,r14
- bne- lwarx_loop2
- isync
- b common_exit
-
-first_thread_in_subcore:
- /* First thread in subcore to wakeup */
ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
stwcx. r15,0,r14
bne- lwarx_loop2
isync
+BEGIN_FTR_SECTION
+ lbz r4,PACA_SUBCORE_SIBLING_MASK(r13)
+ and r4,r4,r15
+ cmpwi r4,0 /* Check if first in subcore */
+
+ or r15,r15,r7 /* Set thread bit */
+ beq first_thread_in_subcore
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
+
+ or r15,r15,r7 /* Set thread bit */
+ beq cr2,first_thread_in_core
+
+ /* Not first thread in core or subcore to wake up */
+ b clear_lock
+
+first_thread_in_subcore:
/*
* If waking up from sleep, subcore state is not lost. Hence
* skip subcore state restore
@@ -399,6 +495,7 @@ first_thread_in_subcore:
/* Restore per-subcore state */
ld r4,_SDR1(r1)
mtspr SPRN_SDR1,r4
+
ld r4,_RPR(r1)
mtspr SPRN_RPR,r4
ld r4,_AMOR(r1)
@@ -414,19 +511,23 @@ subcore_state_restored:
first_thread_in_core:
/*
- * First thread in the core waking up from fastsleep. It needs to
+ * First thread in the core waking up from any state which can cause
+ * partial or complete hypervisor state loss. It needs to
* call the fastsleep workaround code if the platform requires it.
* Call it unconditionally here. The below branch instruction will
- * be patched out when the idle states are discovered if platform
- * does not require workaround.
+ * be patched out if the platform does not have fastsleep or does not
+ * require the workaround. Patching will be performed during the
+ * discovery of idle-states.
*/
.global pnv_fastsleep_workaround_at_exit
pnv_fastsleep_workaround_at_exit:
b fastsleep_workaround_at_exit
timebase_resync:
- /* Do timebase resync if we are waking up from sleep. Use cr3 value
- * set in exceptions-64s.S */
+ /*
+ * Use cr3 which indicates that we are waking up with atleast partial
+ * hypervisor state loss to determine if TIMEBASE RESYNC is needed.
+ */
ble cr3,clear_lock
/* Time base re-sync */
li r0,OPAL_RESYNC_TIMEBASE
@@ -439,7 +540,18 @@ timebase_resync:
*/
bne cr4,clear_lock
- /* Restore per core state */
+ /*
+ * First thread in the core to wake up and its waking up with
+ * complete hypervisor state loss. Restore per core hypervisor
+ * state.
+ */
+BEGIN_FTR_SECTION
+ ld r4,_PTCR(r1)
+ mtspr SPRN_PTCR,r4
+ ld r4,_RPR(r1)
+ mtspr SPRN_RPR,r4
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
ld r4,_TSCR(r1)
mtspr SPRN_TSCR,r4
ld r4,_WORC(r1)
@@ -461,9 +573,7 @@ common_exit:
/* Waking up from winkle */
- /* Restore per thread state */
- bl __restore_cpu_power8
-
+BEGIN_MMU_FTR_SECTION
/* Restore SLB from PACA */
ld r8,PACA_SLBSHADOWPTR(r13)
@@ -477,6 +587,9 @@ common_exit:
slbmte r6,r5
1: addi r8,r8,16
.endr
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
+
+ /* Restore per thread state */
ld r4,_SPURR(r1)
mtspr SPRN_SPURR,r4
@@ -487,6 +600,16 @@ common_exit:
ld r4,_WORT(r1)
mtspr SPRN_WORT,r4
+ /* Call cur_cpu_spec->cpu_restore() */
+ LOAD_REG_ADDR(r4, cur_cpu_spec)
+ ld r4,0(r4)
+ ld r12,CPU_SPEC_RESTORE(r4)
+#ifdef PPC64_ELF_ABI_v1
+ ld r12,0(r12)
+#endif
+ mtctr r12
+ bctrl
+
hypervisor_state_restored:
mtspr SPRN_SRR1,r16
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 8a77f5c..006e467 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -27,9 +27,12 @@
#include "powernv.h"
#include "subcore.h"
+/* Power ISA 3.0 allows for stop states 0x0 - 0xF */
+#define MAX_STOP_STATE 0xF
+
static u32 supported_cpuidle_states;
-static int pnv_save_sprs_for_winkle(void)
+static int pnv_save_sprs_for_deep_states(void)
{
int cpu;
int rc;
@@ -50,15 +53,19 @@ static int pnv_save_sprs_for_winkle(void)
uint64_t pir = get_hard_smp_processor_id(cpu);
uint64_t hsprg0_val = (uint64_t)&paca[cpu];
- /*
- * HSPRG0 is used to store the cpu's pointer to paca. Hence last
- * 3 bits are guaranteed to be 0. Program slw to restore HSPRG0
- * with 63rd bit set, so that when a thread wakes up at 0x100 we
- * can use this bit to distinguish between fastsleep and
- * deep winkle.
- */
- hsprg0_val |= 1;
-
+ if (!cpu_has_feature(CPU_FTR_ARCH_300)) {
+ /*
+ * HSPRG0 is used to store the cpu's pointer to paca.
+ * Hence last 3 bits are guaranteed to be 0. Program
+ * slw to restore HSPRG0 with 63rd bit set, so that
+ * when a thread wakes up at 0x100 we can use this bit
+ * to distinguish between fastsleep and deep winkle.
+ * This is not necessary with stop/psscr since PLS
+ * field of psscr indicates which state we are waking
+ * up from.
+ */
+ hsprg0_val |= 1;
+ }
rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val);
if (rc != 0)
return rc;
@@ -130,8 +137,8 @@ static void pnv_alloc_idle_core_states(void)
update_subcore_sibling_mask();
- if (supported_cpuidle_states & OPAL_PM_WINKLE_ENABLED)
- pnv_save_sprs_for_winkle();
+ if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT)
+ pnv_save_sprs_for_deep_states();
}
u32 pnv_get_supported_cpuidle_states(void)
@@ -230,43 +237,151 @@ static DEVICE_ATTR(fastsleep_workaround_applyonce, 0600,
show_fastsleep_workaround_applyonce,
store_fastsleep_workaround_applyonce);
-static int __init pnv_init_idle_states(void)
+
+/*
+ * Used for ppc_md.power_save which needs a function with no parameters
+ */
+static void power9_idle(void)
{
- struct device_node *power_mgt;
- int dt_idle_states;
- u32 *flags;
- int i;
+ /* Requesting stop state 0 */
+ power9_idle_stop(0);
+}
+/*
+ * First deep stop state. Used to figure out when to save/restore
+ * hypervisor context.
+ */
+u64 pnv_first_deep_stop_state;
- supported_cpuidle_states = 0;
+/*
+ * Power ISA 3.0 idle initialization.
+ *
+ * POWER ISA 3.0 defines a new SPR Processor stop Status and Control
+ * Register (PSSCR) to control idle behavior.
+ *
+ * PSSCR layout:
+ * ----------------------------------------------------------
+ * | PLS | /// | SD | ESL | EC | PSLL | /// | TR | MTL | RL |
+ * ----------------------------------------------------------
+ * 0 4 41 42 43 44 48 54 56 60
+ *
+ * PSSCR key fields:
+ * Bits 0:3 - Power-Saving Level Status (PLS). This field indicates the
+ * lowest power-saving state the thread entered since stop instruction was
+ * last executed.
+ *
+ * Bit 41 - Status Disable(SD)
+ * 0 - Shows PLS entries
+ * 1 - PLS entries are all 0
+ *
+ * Bit 42 - Enable State Loss
+ * 0 - No state is lost irrespective of other fields
+ * 1 - Allows state loss
+ *
+ * Bit 43 - Exit Criterion
+ * 0 - Exit from power-save mode on any interrupt
+ * 1 - Exit from power-save mode controlled by LPCR's PECE bits
+ *
+ * Bits 44:47 - Power-Saving Level Limit
+ * This limits the power-saving level that can be entered into.
+ *
+ * Bits 60:63 - Requested Level
+ * Used to specify which power-saving level must be entered on executing
+ * stop instruction
+ *
+ * @np: /ibm,opal/power-mgt device node
+ * @flags: cpu-idle-state-flags array
+ * @dt_idle_states: Number of idle state entries
+ * Returns 0 on success
+ */
+static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags,
+ int dt_idle_states)
+{
+ u64 *psscr_val = NULL;
+ int rc = 0, i;
- if (cpuidle_disable != IDLE_NO_OVERRIDE)
+ psscr_val = kcalloc(dt_idle_states, sizeof(*psscr_val),
+ GFP_KERNEL);
+ if (!psscr_val) {
+ rc = -1;
goto out;
-
- if (!firmware_has_feature(FW_FEATURE_OPAL))
+ }
+ if (of_property_read_u64_array(np,
+ "ibm,cpu-idle-state-psscr",
+ psscr_val, dt_idle_states)) {
+ pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n");
+ rc = -1;
goto out;
+ }
- power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
- if (!power_mgt) {
+ /*
+ * Set pnv_first_deep_stop_state to the first stop level
+ * to cause hypervisor state loss
+ */
+ pnv_first_deep_stop_state = MAX_STOP_STATE;
+ for (i = 0; i < dt_idle_states; i++) {
+ u64 psscr_rl = psscr_val[i] & PSSCR_RL_MASK;
+
+ if ((flags[i] & OPAL_PM_LOSE_FULL_CONTEXT) &&
+ (pnv_first_deep_stop_state > psscr_rl))
+ pnv_first_deep_stop_state = psscr_rl;
+ }
+
+out:
+ kfree(psscr_val);
+ return rc;
+}
+
+/*
+ * Probe device tree for supported idle states
+ */
+static void __init pnv_probe_idle_states(void)
+{
+ struct device_node *np;
+ int dt_idle_states;
+ u32 *flags = NULL;
+ int i;
+
+ np = of_find_node_by_path("/ibm,opal/power-mgt");
+ if (!np) {
pr_warn("opal: PowerMgmt Node not found\n");
goto out;
}
- dt_idle_states = of_property_count_u32_elems(power_mgt,
+ dt_idle_states = of_property_count_u32_elems(np,
"ibm,cpu-idle-state-flags");
if (dt_idle_states < 0) {
pr_warn("cpuidle-powernv: no idle states found in the DT\n");
goto out;
}
- flags = kzalloc(sizeof(*flags) * dt_idle_states, GFP_KERNEL);
- if (of_property_read_u32_array(power_mgt,
+ flags = kcalloc(dt_idle_states, sizeof(*flags), GFP_KERNEL);
+
+ if (of_property_read_u32_array(np,
"ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n");
- goto out_free;
+ goto out;
+ }
+
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ if (pnv_arch300_idle_init(np, flags, dt_idle_states))
+ goto out;
}
for (i = 0; i < dt_idle_states; i++)
supported_cpuidle_states |= flags[i];
+out:
+ kfree(flags);
+}
+static int __init pnv_init_idle_states(void)
+{
+
+ supported_cpuidle_states = 0;
+
+ if (cpuidle_disable != IDLE_NO_OVERRIDE)
+ goto out;
+
+ pnv_probe_idle_states();
+
if (!(supported_cpuidle_states & OPAL_PM_SLEEP_ENABLED_ER1)) {
patch_instruction(
(unsigned int *)pnv_fastsleep_workaround_at_entry,
@@ -288,8 +403,9 @@ static int __init pnv_init_idle_states(void)
if (supported_cpuidle_states & OPAL_PM_NAP_ENABLED)
ppc_md.power_save = power7_idle;
-out_free:
- kfree(flags);
+ else if (supported_cpuidle_states & OPAL_PM_STOP_INST_FAST)
+ ppc_md.power_save = power9_idle;
+
out:
return 0;
}
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 08/11] cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of MAX_POWERNV_IDLE_STATES
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (6 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 09/11] cpuidle/powernv: cleanup powernv_add_idle_states Shreyas B. Prabhu
` (3 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu, Rafael J. Wysocki, Daniel Lezcano, linux-pm
Use cpuidle's CPUIDLE_STATE_MAX macro instead of powernv specific
MAX_POWERNV_IDLE_STATES.
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: linux-pm@vger.kernel.org
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- No changes after v5
Changes in v5
=============
- New in v5
drivers/cpuidle/cpuidle-powernv.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index e12dc30..3a763a8 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -20,8 +20,6 @@
#include <asm/opal.h>
#include <asm/runlatch.h>
-#define MAX_POWERNV_IDLE_STATES 8
-
struct cpuidle_driver powernv_idle_driver = {
.name = "powernv_idle",
.owner = THIS_MODULE,
@@ -96,7 +94,7 @@ static int fastsleep_loop(struct cpuidle_device *dev,
/*
* States for dedicated partition case.
*/
-static struct cpuidle_state powernv_states[MAX_POWERNV_IDLE_STATES] = {
+static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] = {
{ /* Snooze */
.name = "snooze",
.desc = "snooze",
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 09/11] cpuidle/powernv: cleanup powernv_add_idle_states
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (7 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 08/11] cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of MAX_POWERNV_IDLE_STATES Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-08 2:42 ` Michael Neuling
2016-07-07 20:47 ` [PATCH v7 10/11] cpuidle/powernv: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (2 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu, Rafael J. Wysocki, Daniel Lezcano, linux-pm
- Use stack instead of kzalloc'ed memory for variables while probing
device tree for idle states.
- Set cap for number of idle states that can be added to
cpuidle_state_table
- Minor change in way we check of_property_read_u32_array for error
for sake of consistency
- Drop unnecessary "&" while assigning function pointer
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: linux-pm@vger.kernel.org
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- New in v7. This was mainly to make the existing code
consistent with the review comments for new code
drivers/cpuidle/cpuidle-powernv.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 3a763a8..a89f546 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -166,7 +166,9 @@ static int powernv_add_idle_states(void)
struct device_node *power_mgt;
int nr_idle_states = 1; /* Snooze */
int dt_idle_states;
- u32 *latency_ns, *residency_ns, *flags;
+ u32 latency_ns[CPUIDLE_STATE_MAX];
+ u32 residency_ns[CPUIDLE_STATE_MAX];
+ u32 flags[CPUIDLE_STATE_MAX];
int i, rc;
/* Currently we have snooze statically defined */
@@ -184,22 +186,28 @@ static int powernv_add_idle_states(void)
goto out;
}
- flags = kzalloc(sizeof(*flags) * dt_idle_states, GFP_KERNEL);
+ /*
+ * Since snooze is used as first idle state, max idle states allowed is
+ * CPUIDLE_STATE_MAX -1
+ */
+ if (dt_idle_states > CPUIDLE_STATE_MAX - 1) {
+ pr_warn("cpuidle-powernv: discovered idle states more than allowed");
+ dt_idle_states = CPUIDLE_STATE_MAX - 1;
+ }
+
if (of_property_read_u32_array(power_mgt,
"ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n");
- goto out_free_flags;
+ goto out;
}
- latency_ns = kzalloc(sizeof(*latency_ns) * dt_idle_states, GFP_KERNEL);
- rc = of_property_read_u32_array(power_mgt,
- "ibm,cpu-idle-state-latencies-ns", latency_ns, dt_idle_states);
- if (rc) {
+ if (of_property_read_u32_array(power_mgt,
+ "ibm,cpu-idle-state-latencies-ns", latency_ns,
+ dt_idle_states)) {
pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n");
- goto out_free_latency;
+ goto out;
}
- residency_ns = kzalloc(sizeof(*residency_ns) * dt_idle_states, GFP_KERNEL);
rc = of_property_read_u32_array(power_mgt,
"ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);
@@ -215,7 +223,7 @@ static int powernv_add_idle_states(void)
strcpy(powernv_states[nr_idle_states].desc, "Nap");
powernv_states[nr_idle_states].flags = 0;
powernv_states[nr_idle_states].target_residency = 100;
- powernv_states[nr_idle_states].enter = &nap_loop;
+ powernv_states[nr_idle_states].enter = nap_loop;
}
/*
@@ -230,7 +238,7 @@ static int powernv_add_idle_states(void)
strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
powernv_states[nr_idle_states].target_residency = 300000;
- powernv_states[nr_idle_states].enter = &fastsleep_loop;
+ powernv_states[nr_idle_states].enter = fastsleep_loop;
}
#endif
powernv_states[nr_idle_states].exit_latency =
@@ -243,12 +251,6 @@ static int powernv_add_idle_states(void)
nr_idle_states++;
}
-
- kfree(residency_ns);
-out_free_latency:
- kfree(latency_ns);
-out_free_flags:
- kfree(flags);
out:
return nr_idle_states;
}
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 10/11] cpuidle/powernv: Add support for POWER ISA v3 idle states
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (8 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 09/11] cpuidle/powernv: cleanup powernv_add_idle_states Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 11/11] powerpc/powernv: Use deepest stop state when cpu is offlined Shreyas B. Prabhu
2016-07-08 2:49 ` [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Michael Neuling
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu, Rafael J. Wysocki, Daniel Lezcano,
Rob Herring, Lorenzo Pieralisi, linux-pm
POWER ISA v3 defines a new idle processor core mechanism. In summary,
a) new instruction named stop is added.
b) new per thread SPR named PSSCR is added which controls the behavior
of stop instruction.
Supported idle states and value to be written to PSSCR register to enter
any idle state is exposed via ibm,cpu-idle-state-names and
ibm,cpu-idle-state-psscr respectively. To enter an idle state,
platform provided power_stop() needs to be invoked with the appropriate
PSSCR value.
This patch adds support for this new mechanism in cpuidle powernv driver.
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
Cc: linux-pm@vger.kernel.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@ozlabs.org>
Cc: linuxppc-dev@lists.ozlabs.org
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
Note: Documentation for the device tree bindings is posted here-
http://patchwork.ozlabs.org/patch/629125/
Changes in v7
=============
- Using stack instead kzalloc/kcalloc
Changes in v5
=============
- Use generic cpuidle constant CPUIDLE_NAME_LEN
- Fix return code handling for of_property_read_string_array
- Use DT flags to determine if are using stop instruction, instead of
cpu_has_feature
- Removed uncessary cast with names
- &stop_loop -> stop_loop
- Added POWERNV_THRESHOLD_LATENCY_NS to filter out idle states with high latency
drivers/cpuidle/cpuidle-powernv.c | 61 +++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index a89f546..d27e955 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -20,6 +20,8 @@
#include <asm/opal.h>
#include <asm/runlatch.h>
+#define POWERNV_THRESHOLD_LATENCY_NS 200000
+
struct cpuidle_driver powernv_idle_driver = {
.name = "powernv_idle",
.owner = THIS_MODULE,
@@ -27,6 +29,9 @@ struct cpuidle_driver powernv_idle_driver = {
static int max_idle_state;
static struct cpuidle_state *cpuidle_state_table;
+
+static u64 stop_psscr_table[CPUIDLE_STATE_MAX];
+
static u64 snooze_timeout;
static bool snooze_timeout_en;
@@ -91,6 +96,17 @@ static int fastsleep_loop(struct cpuidle_device *dev,
return index;
}
#endif
+
+static int stop_loop(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ ppc64_runlatch_off();
+ power9_idle_stop(stop_psscr_table[index]);
+ ppc64_runlatch_on();
+ return index;
+}
+
/*
* States for dedicated partition case.
*/
@@ -169,6 +185,8 @@ static int powernv_add_idle_states(void)
u32 latency_ns[CPUIDLE_STATE_MAX];
u32 residency_ns[CPUIDLE_STATE_MAX];
u32 flags[CPUIDLE_STATE_MAX];
+ u64 psscr_val[CPUIDLE_STATE_MAX];
+ const char *names[CPUIDLE_STATE_MAX];
int i, rc;
/* Currently we have snooze statically defined */
@@ -207,11 +225,34 @@ static int powernv_add_idle_states(void)
pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n");
goto out;
}
+ if (of_property_read_string_array(power_mgt,
+ "ibm,cpu-idle-state-names", names, dt_idle_states)) {
+ pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n");
+ goto out;
+ }
+
+ /*
+ * If the idle states use stop instruction, probe for psscr values
+ * which are necessary to specify required stop level.
+ */
+ if (flags[0] & (OPAL_PM_STOP_INST_FAST | OPAL_PM_STOP_INST_DEEP))
+ if (of_property_read_u64_array(power_mgt,
+ "ibm,cpu-idle-state-psscr", psscr_val, dt_idle_states)) {
+ pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n");
+ goto out;
+ }
rc = of_property_read_u32_array(power_mgt,
"ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);
for (i = 0; i < dt_idle_states; i++) {
+ /*
+ * If an idle state has exit latency beyond
+ * POWERNV_THRESHOLD_LATENCY_NS then don't use it
+ * in cpu-idle.
+ */
+ if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS)
+ continue;
/*
* Cpuidle accepts exit_latency and target_residency in us.
@@ -224,6 +265,16 @@ static int powernv_add_idle_states(void)
powernv_states[nr_idle_states].flags = 0;
powernv_states[nr_idle_states].target_residency = 100;
powernv_states[nr_idle_states].enter = nap_loop;
+ } else if ((flags[i] & OPAL_PM_STOP_INST_FAST) &&
+ !(flags[i] & OPAL_PM_TIMEBASE_STOP)) {
+ strncpy(powernv_states[nr_idle_states].name,
+ names[i], CPUIDLE_NAME_LEN);
+ strncpy(powernv_states[nr_idle_states].desc,
+ names[i], CPUIDLE_NAME_LEN);
+ powernv_states[nr_idle_states].flags = 0;
+
+ powernv_states[nr_idle_states].enter = stop_loop;
+ stop_psscr_table[nr_idle_states] = psscr_val[i];
}
/*
@@ -239,6 +290,16 @@ static int powernv_add_idle_states(void)
powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
powernv_states[nr_idle_states].target_residency = 300000;
powernv_states[nr_idle_states].enter = fastsleep_loop;
+ } else if ((flags[i] & OPAL_PM_STOP_INST_DEEP) &&
+ (flags[i] & OPAL_PM_TIMEBASE_STOP)) {
+ strncpy(powernv_states[nr_idle_states].name,
+ names[i], CPUIDLE_NAME_LEN);
+ strncpy(powernv_states[nr_idle_states].desc,
+ names[i], CPUIDLE_NAME_LEN);
+
+ powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
+ powernv_states[nr_idle_states].enter = stop_loop;
+ stop_psscr_table[nr_idle_states] = psscr_val[i];
}
#endif
powernv_states[nr_idle_states].exit_latency =
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 11/11] powerpc/powernv: Use deepest stop state when cpu is offlined
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (9 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 10/11] cpuidle/powernv: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
@ 2016-07-07 20:47 ` Shreyas B. Prabhu
2016-07-08 2:49 ` [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Michael Neuling
11 siblings, 0 replies; 18+ messages in thread
From: Shreyas B. Prabhu @ 2016-07-07 20:47 UTC (permalink / raw)
To: mpe
Cc: benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy,
Shreyas B. Prabhu
If hardware supports stop state, use the deepest stop state when
the cpu is offlined.
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
---
- No changes since v1
arch/powerpc/platforms/powernv/idle.c | 15 +++++++++++++--
arch/powerpc/platforms/powernv/powernv.h | 1 +
arch/powerpc/platforms/powernv/smp.c | 4 +++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 006e467..2f6968c 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -253,6 +253,11 @@ static void power9_idle(void)
u64 pnv_first_deep_stop_state;
/*
+ * Deepest stop idle state. Used when a cpu is offlined
+ */
+u64 pnv_deepest_stop_state;
+
+/*
* Power ISA 3.0 idle initialization.
*
* POWER ISA 3.0 defines a new SPR Processor stop Status and Control
@@ -314,8 +319,11 @@ static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags,
}
/*
- * Set pnv_first_deep_stop_state to the first stop level
- * to cause hypervisor state loss
+ * Set pnv_first_deep_stop_state and pnv_deepest_stop_state.
+ * pnv_first_deep_stop_state should be set to the first stop
+ * level to cause hypervisor state loss.
+ * pnv_deepest_stop_state should be set to the deepest stop
+ * stop state.
*/
pnv_first_deep_stop_state = MAX_STOP_STATE;
for (i = 0; i < dt_idle_states; i++) {
@@ -324,6 +332,9 @@ static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags,
if ((flags[i] & OPAL_PM_LOSE_FULL_CONTEXT) &&
(pnv_first_deep_stop_state > psscr_rl))
pnv_first_deep_stop_state = psscr_rl;
+
+ if (pnv_deepest_stop_state < psscr_rl)
+ pnv_deepest_stop_state = psscr_rl;
}
out:
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h
index 6dbc0a1..da7c843 100644
--- a/arch/powerpc/platforms/powernv/powernv.h
+++ b/arch/powerpc/platforms/powernv/powernv.h
@@ -18,6 +18,7 @@ static inline void pnv_pci_shutdown(void) { }
#endif
extern u32 pnv_get_supported_cpuidle_states(void);
+extern u64 pnv_deepest_stop_state;
extern void pnv_lpc_init(void);
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index ad7b1a3..c789258 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -182,7 +182,9 @@ static void pnv_smp_cpu_kill_self(void)
ppc64_runlatch_off();
- if (idle_states & OPAL_PM_WINKLE_ENABLED)
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ srr1 = power9_idle_stop(pnv_deepest_stop_state);
+ else if (idle_states & OPAL_PM_WINKLE_ENABLED)
srr1 = power7_winkle();
else if ((idle_states & OPAL_PM_SLEEP_ENABLED) ||
(idle_states & OPAL_PM_SLEEP_ENABLED_ER1))
--
2.4.11
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction
2016-07-07 20:47 ` [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction Shreyas B. Prabhu
@ 2016-07-08 2:20 ` Michael Neuling
2016-07-08 4:19 ` Shreyas B Prabhu
0 siblings, 1 reply; 18+ messages in thread
From: Michael Neuling @ 2016-07-08 2:20 UTC (permalink / raw)
To: Shreyas B. Prabhu, mpe
Cc: benh, paulus, ego, linuxppc-dev, linux-kernel, maddy
> diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/as=
m/cpuidle.h
> index d2f99ca..3d7fc06 100644
> --- a/arch/powerpc/include/asm/cpuidle.h
> +++ b/arch/powerpc/include/asm/cpuidle.h
> @@ -13,6 +13,8 @@
> =C2=A0#ifndef __ASSEMBLY__
> =C2=A0extern u32 pnv_fastsleep_workaround_at_entry[];
> =C2=A0extern u32 pnv_fastsleep_workaround_at_exit[];
> +
> +extern u64 pnv_first_deep_stop_state;
mpe asked a question about this which you neither answered or addressed.
"Should this have some safe initial value?"
I'm thinking we could do this which is what you have in the init call.
=C2=A0 =C2=A0u64 pnv_first_deep_stop_state =3D=C2=A0MAX_STOP_STATE;
> @@ -439,7 +540,18 @@ timebase_resync:
> =C2=A0 =C2=A0*/
> =C2=A0 bne cr4,clear_lock
> =C2=A0
> - /* Restore per core state */
> + /*
> + =C2=A0* First thread in the core to wake up and its waking up with
> + =C2=A0* complete hypervisor state loss. Restore per core hypervisor
> + =C2=A0* state.
> + =C2=A0*/
> +BEGIN_FTR_SECTION
> + ld r4,_PTCR(r1)
> + mtspr SPRN_PTCR,r4
> + ld r4,_RPR(r1)
> + mtspr SPRN_RPR,r4
RPR looks wrong here. =C2=A0This should be on POWER8 too.
This has changed since v6 and not noted in the v7 comments. =C2=A0Why are y=
ou
changing this now?
> +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
> +
> =C2=A0 ld r4,_TSCR(r1)
> =C2=A0 mtspr SPRN_TSCR,r4
> =C2=A0 ld r4,_WORC(r1)
> @@ -461,9 +573,7 @@ common_exit:
> =C2=A0
> =C2=A0 /* Waking up from winkle */
> =C2=A0
> - /* Restore per thread state */
> - bl __restore_cpu_power8
> -
> +BEGIN_MMU_FTR_SECTION
> =C2=A0 /* Restore SLB=C2=A0=C2=A0from PACA */
> =C2=A0 ld r8,PACA_SLBSHADOWPTR(r13)
> =C2=A0
> @@ -477,6 +587,9 @@ common_exit:
> =C2=A0 slbmte r6,r5
> =C2=A01: addi r8,r8,16
> =C2=A0 .endr
> +END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
> +
> + /* Restore per thread state */
This FTR section is too big =C2=A0It ends up at 25 instructions with the lo=
op.
Probably better like this:
BEGIN_MMU_FTR_SECTION
b no_segments
END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
/* Restore SLB=C2=A0=C2=A0from PACA */
ld r8,PACA_SLBSHADOWPTR(r13)
.rept SLB_NUM_BOLTED
li r3, SLBSHADOW_SAVEAREA
LDX_BE r5, r8, r3
addi r3, r3, 8
LDX_BE r6, r8, r3
andis. r7,r5,SLB_ESID_V@h
beq 1f
slbmte r6,r5
1: addi r8,r8,16
.endr
no_segments:
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 09/11] cpuidle/powernv: cleanup powernv_add_idle_states
2016-07-07 20:47 ` [PATCH v7 09/11] cpuidle/powernv: cleanup powernv_add_idle_states Shreyas B. Prabhu
@ 2016-07-08 2:42 ` Michael Neuling
0 siblings, 0 replies; 18+ messages in thread
From: Michael Neuling @ 2016-07-08 2:42 UTC (permalink / raw)
To: Shreyas B. Prabhu, mpe
Cc: benh, paulus, ego, linuxppc-dev, linux-kernel, maddy,
Rafael J. Wysocki, Daniel Lezcano, linux-pm
> =C2=A0 /*
> @@ -230,7 +238,7 @@ static int powernv_add_idle_states(void)
> =C2=A0 strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
> =C2=A0 powernv_states[nr_idle_states].flags =3D CPUIDLE_FLAG_TIMER_STOP=
;
> =C2=A0 powernv_states[nr_idle_states].target_residency =3D 300000;
> - powernv_states[nr_idle_states].enter =3D &fastsleep_loop;
> + powernv_states[nr_idle_states].enter =3D fastsleep_loop;
You can change this code too with the same thing.
static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] =3D {
{ /* Snooze */
.name =3D "snooze",
.desc =3D "snooze",
.exit_latency =3D 0,
.target_residency =3D 0,
.enter =3D &snooze_loop },
};
Mikey
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
` (10 preceding siblings ...)
2016-07-07 20:47 ` [PATCH v7 11/11] powerpc/powernv: Use deepest stop state when cpu is offlined Shreyas B. Prabhu
@ 2016-07-08 2:49 ` Michael Neuling
11 siblings, 0 replies; 18+ messages in thread
From: Michael Neuling @ 2016-07-08 2:49 UTC (permalink / raw)
To: Shreyas B. Prabhu, mpe
Cc: benh, paulus, ego, linuxppc-dev, linux-kernel, maddy,
Rafael J. Wysocki, Daniel Lezcano, linux-pm, Rob Herring,
Lorenzo Pieralisi
Except for the issue with patch 7 I've already commented on the rest of
this series is good with me. =C2=A0FWIW:
Acked-by: Michael Neuling <mikey@neuling.org>
Thanks.
On Fri, 2016-07-08 at 02:17 +0530, Shreyas B. Prabhu wrote:
> POWER ISA v3 defines a new idle processor core mechanism. In summary,
> =C2=A0a) new instruction named stop is added. This instruction replaces
> instructions like nap, sleep, rvwinkle.
> =C2=A0b) new per thread SPR named PSSCR is added which controls the behav=
ior
> of stop instruction.=C2=A0
> =09
> PSSCR has following key fields
> Bits 0:3=C2=A0=C2=A0- Power-Saving Level Status. This field indicates th=
e
> lowest power-saving state the thread entered since stop
> instruction was last executed.
> =09
> Bit 42 - Enable State Loss=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0
> 0 - No state is lost irrespective of other fields=C2=A0=C2=A0
> 1 - Allows state loss
> =09
> Bits 44:47 - Power-Saving Level Limit=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0
> This limits the power-saving level that can be entered into.
> =09
> Bits 60:63 - Requested Level=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0
> Used to specify which power-saving level must be entered on
> executing stop instruction
> =09
> Stop idle states and their properties like name, latency, target
> residency, psscr value are exposed via device tree.
>=20
> This patch series adds support for this new mechanism.
>=20
> Patches 1-6 are cleanups and code movement.
> Patch 7 adds platform specific support for stop and psscr handling.
> Patch 8 and 9 are minor cleanup in cpuidle driver.
> Patch 10 adds cpuidle driver support.
> Patch 11 makes offlined cpu use deepest stop state.
>=20
> Note: Documentation for the device tree bindings is posted here-
> http://patchwork.ozlabs.org/patch/629125/
>=20
> Changes in v7
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =C2=A0- File renamed to idle_book3s.S instead of idle_power_common.S
> =C2=A0- Comment changes
> =C2=A0- power_stop0, power_stop renamed to power9_idle and power_idle_sto=
p
> =C2=A0- PSSCR template is now a macro instead of storing in paca
> =C2=A0- power9_idle in C file instead of assembly
> =C2=A0- Fixed TOC related bug
> =C2=A0- Handling subcore within FTR section
> =C2=A0- Functions in idle.c reordered and broken into multiple functions
> =C2=A0- calling __restore_cpu_power8/9 via cur_cpu_spec->cpu_restore=C2=
=A0
> =C2=A0- Added a minor patch with minor cleanups in cpuidle-powernv.c . Th=
is
> =C2=A0=C2=A0=C2=A0was mainly to make the existing code consistent with th=
e review
> =C2=A0=C2=A0=C2=A0comments for new code
> =C2=A0- Using stack for variables while probing for idle states instead o=
f
> =C2=A0=C2=A0=C2=A0kzalloc/kcalloc
>=20
> Changes in v6
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =C2=A0- Restore new POWER ISA v3 SPRS when waking up from deep idle
>=20
> Changes in v5
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =C2=A0- Use generic cpuidle constant CPUIDLE_NAME_LEN
> =C2=A0- Fix return code handling for of_property_read_string_array
> =C2=A0- Use DT flags to determine if are using stop instruction, instead =
of
> =C2=A0=C2=A0=C2=A0cpu_has_feature
> =C2=A0- Removed uncessary cast with names
> =C2=A0- &stop_loop -> stop_loop
> =C2=A0- Added POWERNV_THRESHOLD_LATENCY_NS to filter out idle states with=
high latency
>=20
> Changes in v4
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =C2=A0- Added a patch to use PNV_THREAD_WINKLE macro while requesting for=
winkle
> =C2=A0- Moved power7_powersave_common rename to more appropriate patch
> =C2=A0- renaming power7_enter_nap_mode to pnv_enter_arch207_idle_mode
> =C2=A0- Added PSSCR layout to Patch 7's commit message
> =C2=A0- Improved / Fixed comments
> =C2=A0- Fixed whitespace error in paca.h
> =C2=A0- Using MAX_POSSIBLE_STOP_STATE macro instead of hardcoding 0xF has
> =C2=A0=C2=A0=C2=A0max possible stop state
>=20
> Changes in v3
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =C2=A0- Rebased on powerpc-next
> =C2=A0- Dropping patch 1 since we are not adding a new file for P9 idle s=
upport
> =C2=A0- Improved comments in multiple places
> =C2=A0- Moved GET_PACA from power7_restore_hyp_resource to System Reset
> =C2=A0- Instead of moving few functions from idle_power7 to idle_power_co=
mmon,
> =C2=A0=C2=A0=C2=A0renaming idle_power7.S to idle_power_common.S
> =C2=A0- Moved HSTATE_HWTHREAD_STATE updation to power_powersave_common
> =C2=A0- Dropped earlier patch 5 which moved few macros from idle_power_co=
mmon to
> =C2=A0=C2=A0=C2=A0asm/cpuidle.h.=C2=A0
> =C2=A0- Added a patch to rename reusable power7_* idle functions to pnv_*
> =C2=A0- Added new patch that creates abstraction for saving SPRs before
> =C2=A0=C2=A0=C2=A0entering deep idle states
> =C2=A0- Instead of introducing new file idle_power_stop.S, P9 idle suppor=
t
> =C2=A0=C2=A0=C2=A0is added to idle_power_common.S using CPU_FTR sections.
> =C2=A0- Fixed r4 reg clobbering in power_stop0
>=20
> Changes in v2
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =C2=A0- Rebased on v4.6-rc6
> =C2=A0- Using CPU_FTR_ARCH_300 bit instead of CPU_FTR_STOP_INST
>=20
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: linux-pm@vger.kernel.org
> Cc: Benjamin Herrenschmidt <benh@au1.ibm.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Paul Mackerras <paulus@ozlabs.org>
> Cc: Michael Neuling <mikey@neuling.org>
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
>=20
> Shreyas B. Prabhu (11):
> =C2=A0 powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for
> =C2=A0=C2=A0=C2=A0=C2=A0winkle
> =C2=A0 powerpc/kvm: make hypervisor state restore a function
> =C2=A0 powerpc/powernv: Rename idle_power7.S to idle_book3s.S
> =C2=A0 powerpc/powernv: Rename reusable idle functions to hardware agnost=
ic
> =C2=A0=C2=A0=C2=A0=C2=A0names
> =C2=A0 powerpc/powernv: Make pnv_powersave_common more generic
> =C2=A0 powerpc/powernv: abstraction for saving SPRs before entering deep =
idle
> =C2=A0=C2=A0=C2=A0=C2=A0states
> =C2=A0 powerpc/powernv: Add platform support for stop instruction
> =C2=A0 cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of
> =C2=A0=C2=A0=C2=A0=C2=A0MAX_POWERNV_IDLE_STATES
> =C2=A0 cpuidle/powernv: cleanup powernv_add_idle_states
> =C2=A0 cpuidle/powernv: Add support for POWER ISA v3 idle states
> =C2=A0 powerpc/powernv: Use deepest stop state when cpu is offlined
>=20
> =C2=A0arch/powerpc/include/asm/cpuidle.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A02 +
> =C2=A0arch/powerpc/include/asm/kvm_book3s_asm.h |=C2=A0=C2=A0=C2=A02 +-
> =C2=A0arch/powerpc/include/asm/opal-api.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0|=C2=A0=C2=A011 +-
> =C2=A0arch/powerpc/include/asm/ppc-opcode.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
|=C2=A0=C2=A0=C2=A04 +
> =C2=A0arch/powerpc/include/asm/processor.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0|=C2=A0=C2=A0=C2=A02 +
> =C2=A0arch/powerpc/include/asm/reg.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A010 +
> =C2=A0arch/powerpc/kernel/Makefile=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A02 +-
> =C2=A0arch/powerpc/kernel/exceptions-64s.S=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0|=C2=A0=C2=A030 +-
> =C2=A0arch/powerpc/kernel/idle_book3s.S=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0| 664 ++++++++++++++++++++++++++++++
> =C2=A0arch/powerpc/kernel/idle_power7.S=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0| 515 -----------------------
> =C2=A0arch/powerpc/kvm/book3s_hv_rmhandlers.S=C2=A0=C2=A0=C2=A0|=C2=A0=C2=
=A0=C2=A04 +-
> =C2=A0arch/powerpc/platforms/powernv/idle.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
| 185 +++++++--
> =C2=A0arch/powerpc/platforms/powernv/powernv.h=C2=A0=C2=A0|=C2=A0=C2=A0=
=C2=A01 +
> =C2=A0arch/powerpc/platforms/powernv/smp.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0|=C2=A0=C2=A0=C2=A04 +-
> =C2=A0drivers/cpuidle/cpuidle-powernv.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A099 ++++-
> =C2=A015 files changed, 940 insertions(+), 595 deletions(-)
> =C2=A0create mode 100644 arch/powerpc/kernel/idle_book3s.S
> =C2=A0delete mode 100644 arch/powerpc/kernel/idle_power7.S
>=20
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction
2016-07-08 2:20 ` Michael Neuling
@ 2016-07-08 4:19 ` Shreyas B Prabhu
2016-07-08 4:27 ` Michael Neuling
0 siblings, 1 reply; 18+ messages in thread
From: Shreyas B Prabhu @ 2016-07-08 4:19 UTC (permalink / raw)
To: Michael Neuling, mpe; +Cc: benh, paulus, ego, linuxppc-dev, linux-kernel, maddy
On 07/08/2016 07:50 AM, Michael Neuling wrote:
>
>> diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/asm/cpuidle.h
>> index d2f99ca..3d7fc06 100644
>> --- a/arch/powerpc/include/asm/cpuidle.h
>> +++ b/arch/powerpc/include/asm/cpuidle.h
>> @@ -13,6 +13,8 @@
>> #ifndef __ASSEMBLY__
>> extern u32 pnv_fastsleep_workaround_at_entry[];
>> extern u32 pnv_fastsleep_workaround_at_exit[];
>> +
>> +extern u64 pnv_first_deep_stop_state;
>
> mpe asked a question about this which you neither answered or addressed.
> "Should this have some safe initial value?"
>
> I'm thinking we could do this which is what you have in the init call.
> u64 pnv_first_deep_stop_state = MAX_STOP_STATE;
>
I missed the comment. I'll make the change.
>
>> @@ -439,7 +540,18 @@ timebase_resync:
>> */
>> bne cr4,clear_lock
>>
>> - /* Restore per core state */
>> + /*
>> + * First thread in the core to wake up and its waking up with
>> + * complete hypervisor state loss. Restore per core hypervisor
>> + * state.
>> + */
>> +BEGIN_FTR_SECTION
>> + ld r4,_PTCR(r1)
>> + mtspr SPRN_PTCR,r4
>> + ld r4,_RPR(r1)
>> + mtspr SPRN_RPR,r4
>
> RPR looks wrong here. This should be on POWER8 too.
>
> This has changed since v6 and not noted in the v7 comments. Why are you
> changing this now?
>
RPR is a per-core resource in P9. So with this patch, RPR will continue
to be restored per-subcore in P8 and will restored once per core in P9.
>> +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
>> +
>> ld r4,_TSCR(r1)
>> mtspr SPRN_TSCR,r4
>> ld r4,_WORC(r1)
>> @@ -461,9 +573,7 @@ common_exit:
>>
>> /* Waking up from winkle */
>>
>> - /* Restore per thread state */
>> - bl __restore_cpu_power8
>> -
>> +BEGIN_MMU_FTR_SECTION
>> /* Restore SLB from PACA */
>> ld r8,PACA_SLBSHADOWPTR(r13)
>>
>> @@ -477,6 +587,9 @@ common_exit:
>> slbmte r6,r5
>> 1: addi r8,r8,16
>> .endr
>> +END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
>> +
>> + /* Restore per thread state */
>
> This FTR section is too big It ends up at 25 instructions with the loop.
> Probably better like this:
>
> BEGIN_MMU_FTR_SECTION
> b no_segments
> END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
> /* Restore SLB from PACA */
> ld r8,PACA_SLBSHADOWPTR(r13)
>
> .rept SLB_NUM_BOLTED
> li r3, SLBSHADOW_SAVEAREA
> LDX_BE r5, r8, r3
> addi r3, r3, 8
> LDX_BE r6, r8, r3
> andis. r7,r5,SLB_ESID_V@h
> beq 1f
> slbmte r6,r5
> 1: addi r8,r8,16
> .endr
>
> no_segments:
>
Cool. Will make the change.
Thanks,
Shreyas
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction
2016-07-08 4:19 ` Shreyas B Prabhu
@ 2016-07-08 4:27 ` Michael Neuling
0 siblings, 0 replies; 18+ messages in thread
From: Michael Neuling @ 2016-07-08 4:27 UTC (permalink / raw)
To: Shreyas B Prabhu, mpe
Cc: benh, paulus, ego, linuxppc-dev, linux-kernel, maddy
> > >=20
> > > @@ -439,7 +540,18 @@ timebase_resync:
> > > =C2=A0 =C2=A0*/
> > > =C2=A0 bne cr4,clear_lock
> > > =C2=A0
> > > - /* Restore per core state */
> > > + /*
> > > + =C2=A0* First thread in the core to wake up and its waking up
> > > with
> > > + =C2=A0* complete hypervisor state loss. Restore per core
> > > hypervisor
> > > + =C2=A0* state.
> > > + =C2=A0*/
> > > +BEGIN_FTR_SECTION
> > > + ld r4,_PTCR(r1)
> > > + mtspr SPRN_PTCR,r4
> > > + ld r4,_RPR(r1)
> > > + mtspr SPRN_RPR,r4
> > RPR looks wrong here.=C2=A0=C2=A0This should be on POWER8 too.
> >=20
> > This has changed since v6 and not noted in the v7 comments.=C2=A0=C2=A0=
Why are
> > you
> > changing this now?
> >=20
> RPR is a per-core resource in P9. So with this patch, RPR will continue
> to be restored per-subcore in P8 and will restored once per core in P9.
Ok, thanks for the explanation.
Mikey
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle
2016-07-07 20:47 ` [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle Shreyas B. Prabhu
@ 2016-07-15 13:10 ` Balbir Singh
0 siblings, 0 replies; 18+ messages in thread
From: Balbir Singh @ 2016-07-15 13:10 UTC (permalink / raw)
To: Shreyas B. Prabhu
Cc: mpe, benh, paulus, mikey, ego, linuxppc-dev, linux-kernel, maddy
On Fri, Jul 08, 2016 at 02:17:02AM +0530, Shreyas B. Prabhu wrote:
> Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
> ---
> -No changes since v4
>
> Changes in v4
> =============
> - New in v4
>
> arch/powerpc/kernel/idle_power7.S | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
> index 470ceeb..705c867 100644
> --- a/arch/powerpc/kernel/idle_power7.S
> +++ b/arch/powerpc/kernel/idle_power7.S
> @@ -252,7 +252,7 @@ _GLOBAL(power7_sleep)
> /* No return */
>
> _GLOBAL(power7_winkle)
> - li r3,3
> + li r3,PNV_THREAD_WINKLE
> li r4,1
> b power7_powersave_common
Acked-by: Balbir Singh <bsingharora@gmail.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2016-07-15 13:10 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-07 20:47 [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 01/11] powerpc/powernv: Use PNV_THREAD_WINKLE macro while requesting for winkle Shreyas B. Prabhu
2016-07-15 13:10 ` Balbir Singh
2016-07-07 20:47 ` [PATCH v7 02/11] powerpc/kvm: make hypervisor state restore a function Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 03/11] powerpc/powernv: Rename idle_power7.S to idle_book3s.S Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 04/11] powerpc/powernv: Rename reusable idle functions to hardware agnostic names Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 05/11] powerpc/powernv: Make pnv_powersave_common more generic Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 06/11] powerpc/powernv: abstraction for saving SPRs before entering deep idle states Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 07/11] powerpc/powernv: Add platform support for stop instruction Shreyas B. Prabhu
2016-07-08 2:20 ` Michael Neuling
2016-07-08 4:19 ` Shreyas B Prabhu
2016-07-08 4:27 ` Michael Neuling
2016-07-07 20:47 ` [PATCH v7 08/11] cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of MAX_POWERNV_IDLE_STATES Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 09/11] cpuidle/powernv: cleanup powernv_add_idle_states Shreyas B. Prabhu
2016-07-08 2:42 ` Michael Neuling
2016-07-07 20:47 ` [PATCH v7 10/11] cpuidle/powernv: Add support for POWER ISA v3 idle states Shreyas B. Prabhu
2016-07-07 20:47 ` [PATCH v7 11/11] powerpc/powernv: Use deepest stop state when cpu is offlined Shreyas B. Prabhu
2016-07-08 2:49 ` [PATCH v7 00/11] powerpc/powernv/cpuidle: Add support for POWER ISA v3 idle states Michael Neuling
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).