diff options
author | Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> | 2014-02-25 19:08:25 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-03-04 23:56:31 -0500 |
commit | aca79d2b6ec2c0b955b22abb71c6dab90fa1d4d5 (patch) | |
tree | d4eb7a475ad1c2163719924bc1886ff7b2dff3bf | |
parent | 1b7839559b3f1c7a09ff94904788a732063ce2de (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.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle_power7.S | 63 |
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 | ||
451 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ | 451 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ |
452 | extern void power7_nap(void); | 452 | extern void power7_nap(void); |
453 | extern void power7_sleep(void); | ||
453 | extern void flush_instruction_cache(void); | 454 | extern void flush_instruction_cache(void); |
454 | extern void hard_reset_now(void); | 455 | extern void hard_reset_now(void); |
455 | extern void poweroff_now(void); | 456 | extern 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 |
143 | 2: b .power7_wakeup_loss | 144 | 2: b .power7_wakeup_loss |
145 | |||
146 | /* Fast Sleep wakeup on PowerNV */ | ||
147 | 8: GET_PACA(r13) | ||
148 | b .power7_wakeup_loss | ||
149 | |||
144 | 9: | 150 | 9: |
145 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) | 151 | END_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 | 30 | 1: 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 */ | ||
107 | 2: 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) |
98 | 1: 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) |