aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>2014-02-25 19:08:25 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-03-04 23:56:31 -0500
commitaca79d2b6ec2c0b955b22abb71c6dab90fa1d4d5 (patch)
treed4eb7a475ad1c2163719924bc1886ff7b2dff3bf
parent1b7839559b3f1c7a09ff94904788a732063ce2de (diff)
powerpc/powernv: Add context management for Fast Sleep
Before adding Fast-Sleep into the cpuidle framework, some low level support needs to be added to enable it. This includes saving and restoring of certain registers at entry and exit time of this state respectively just like we do in the NAP idle state. Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> [Changelog modified by Preeti U. Murthy <preeti@linux.vnet.ibm.com>] Signed-off-by: Preeti U. Murthy <preeti@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/processor.h1
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S10
-rw-r--r--arch/powerpc/kernel/idle_power7.S63
3 files changed, 53 insertions, 21 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index b62de43ae5f3..d660dc36831a 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -450,6 +450,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
450 450
451extern int powersave_nap; /* set if nap mode can be used in idle loop */ 451extern int powersave_nap; /* set if nap mode can be used in idle loop */
452extern void power7_nap(void); 452extern void power7_nap(void);
453extern void power7_sleep(void);
453extern void flush_instruction_cache(void); 454extern void flush_instruction_cache(void);
454extern void hard_reset_now(void); 455extern void hard_reset_now(void);
455extern void poweroff_now(void); 456extern void poweroff_now(void);
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 38d507306a11..b01a9cb441e4 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -121,9 +121,10 @@ BEGIN_FTR_SECTION
121 cmpwi cr1,r13,2 121 cmpwi cr1,r13,2
122 /* Total loss of HV state is fatal, we could try to use the 122 /* Total loss of HV state is fatal, we could try to use the
123 * PIR to locate a PACA, then use an emergency stack etc... 123 * PIR to locate a PACA, then use an emergency stack etc...
124 * but for now, let's just stay stuck here 124 * OPAL v3 based powernv platforms have new idle states
125 * which fall in this catagory.
125 */ 126 */
126 bgt cr1,. 127 bgt cr1,8f
127 GET_PACA(r13) 128 GET_PACA(r13)
128 129
129#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 130#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
@@ -141,6 +142,11 @@ BEGIN_FTR_SECTION
141 beq cr1,2f 142 beq cr1,2f
142 b .power7_wakeup_noloss 143 b .power7_wakeup_noloss
1432: b .power7_wakeup_loss 1442: b .power7_wakeup_loss
145
146 /* Fast Sleep wakeup on PowerNV */
1478: GET_PACA(r13)
148 b .power7_wakeup_loss
149
1449: 1509:
145END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) 151END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
146#endif /* CONFIG_PPC_P7_NAP */ 152#endif /* CONFIG_PPC_P7_NAP */
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 3fdef0f0c67f..14f78bec62c4 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -20,17 +20,27 @@
20 20
21#undef DEBUG 21#undef DEBUG
22 22
23 .text 23/* Idle state entry routines */
24 24
25_GLOBAL(power7_idle) 25#define IDLE_STATE_ENTER_SEQ(IDLE_INST) \
26 /* Now check if user or arch enabled NAP mode */ 26 /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
27 LOAD_REG_ADDRBASE(r3,powersave_nap) 27 std r0,0(r1); \
28 lwz r4,ADDROFF(powersave_nap)(r3) 28 ptesync; \
29 cmpwi 0,r4,0 29 ld r0,0(r1); \
30 beqlr 301: cmp cr0,r0,r0; \
31 /* fall through */ 31 bne 1b; \
32 IDLE_INST; \
33 b .
32 34
33_GLOBAL(power7_nap) 35 .text
36
37/*
38 * Pass requested state in r3:
39 * 0 - nap
40 * 1 - sleep
41 */
42_GLOBAL(power7_powersave_common)
43 /* Use r3 to pass state nap/sleep/winkle */
34 /* NAP is a state loss, we create a regs frame on the 44 /* NAP is a state loss, we create a regs frame on the
35 * stack, fill it up with the state we care about and 45 * stack, fill it up with the state we care about and
36 * stick a pointer to it in PACAR1. We really only 46 * stick a pointer to it in PACAR1. We really only
@@ -79,8 +89,8 @@ _GLOBAL(power7_nap)
79 /* Continue saving state */ 89 /* Continue saving state */
80 SAVE_GPR(2, r1) 90 SAVE_GPR(2, r1)
81 SAVE_NVGPRS(r1) 91 SAVE_NVGPRS(r1)
82 mfcr r3 92 mfcr r4
83 std r3,_CCR(r1) 93 std r4,_CCR(r1)
84 std r9,_MSR(r1) 94 std r9,_MSR(r1)
85 std r1,PACAR1(r13) 95 std r1,PACAR1(r13)
86 96
@@ -90,15 +100,30 @@ _GLOBAL(power7_enter_nap_mode)
90 li r4,KVM_HWTHREAD_IN_NAP 100 li r4,KVM_HWTHREAD_IN_NAP
91 stb r4,HSTATE_HWTHREAD_STATE(r13) 101 stb r4,HSTATE_HWTHREAD_STATE(r13)
92#endif 102#endif
103 cmpwi cr0,r3,1
104 beq 2f
105 IDLE_STATE_ENTER_SEQ(PPC_NAP)
106 /* No return */
1072: IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
108 /* No return */
93 109
94 /* Magic NAP mode enter sequence */ 110_GLOBAL(power7_idle)
95 std r0,0(r1) 111 /* Now check if user or arch enabled NAP mode */
96 ptesync 112 LOAD_REG_ADDRBASE(r3,powersave_nap)
97 ld r0,0(r1) 113 lwz r4,ADDROFF(powersave_nap)(r3)
981: cmp cr0,r0,r0 114 cmpwi 0,r4,0
99 bne 1b 115 beqlr
100 PPC_NAP 116 /* fall through */
101 b . 117
118_GLOBAL(power7_nap)
119 li r3,0
120 b power7_powersave_common
121 /* No return */
122
123_GLOBAL(power7_sleep)
124 li r3,1
125 b power7_powersave_common
126 /* No return */
102 127
103_GLOBAL(power7_wakeup_loss) 128_GLOBAL(power7_wakeup_loss)
104 ld r1,PACAR1(r13) 129 ld r1,PACAR1(r13)