aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/entry_32.S
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-04-18 07:49:11 -0400
committerPaul Mackerras <paulus@samba.org>2006-04-18 07:49:11 -0400
commitf39224a8c1828bdd327539da72a53d8a13595838 (patch)
treecc9e9139e2e7e2e36774e5c52a5311439160633c /arch/powerpc/kernel/entry_32.S
parent183b73ae7c9e4e19fa95d88e1778481899a65210 (diff)
powerpc: Use correct sequence for putting CPU into nap mode
We weren't using the recommended sequence for putting the CPU into nap mode. When I changed the idle loop, for some reason 7447A cpus started hanging when we put them into nap mode. Changing to the recommended sequence fixes that. The complexity here is that the recommended sequence is a loop that keeps putting the cpu back into nap mode. Clearly we need some way to break out of the loop when an interrupt (external interrupt, decrementer, performance monitor) occurs. Here we use a bit in the thread_info struct to indicate that we need this, and the exception entry code notices this and arranges for the exception to return to the value in the link register, thus breaking out of the loop. We use a new `local_flags' field in the thread_info which we can alter without needing to use an atomic update sequence. The PPC970 has the same recommended sequence, so we do the same thing there too. This also fixes a bug in the kernel stack overflow handling code on 32-bit, since it was causing a value that we needed in a register to get trashed. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/entry_32.S')
-rw-r--r--arch/powerpc/kernel/entry_32.S35
1 files changed, 17 insertions, 18 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index b3a979467225..8866fd26c6b9 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -128,37 +128,36 @@ transfer_to_handler:
128 stw r12,4(r11) 128 stw r12,4(r11)
129#endif 129#endif
130 b 3f 130 b 3f
131
1312: /* if from kernel, check interrupted DOZE/NAP mode and 1322: /* if from kernel, check interrupted DOZE/NAP mode and
132 * check for stack overflow 133 * check for stack overflow
133 */ 134 */
135 lwz r9,THREAD_INFO-THREAD(r12)
136 cmplw r1,r9 /* if r1 <= current->thread_info */
137 ble- stack_ovf /* then the kernel stack overflowed */
1385:
134#ifdef CONFIG_6xx 139#ifdef CONFIG_6xx
135 mfspr r11,SPRN_HID0 140 tophys(r9,r9) /* check local flags */
136 mtcr r11 141 lwz r12,TI_LOCAL_FLAGS(r9)
137BEGIN_FTR_SECTION 142 mtcrf 0x01,r12
138 bt- 8,4f /* Check DOZE */ 143 bt- 31-TLF_NAPPING,4f
139END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
140BEGIN_FTR_SECTION
141 bt- 9,4f /* Check NAP */
142END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
143#endif /* CONFIG_6xx */ 144#endif /* CONFIG_6xx */
144 .globl transfer_to_handler_cont 145 .globl transfer_to_handler_cont
145transfer_to_handler_cont: 146transfer_to_handler_cont:
146 lwz r11,THREAD_INFO-THREAD(r12)
147 cmplw r1,r11 /* if r1 <= current->thread_info */
148 ble- stack_ovf /* then the kernel stack overflowed */
1493: 1473:
150 mflr r9 148 mflr r9
151 lwz r11,0(r9) /* virtual address of handler */ 149 lwz r11,0(r9) /* virtual address of handler */
152 lwz r9,4(r9) /* where to go when done */ 150 lwz r9,4(r9) /* where to go when done */
153 FIX_SRR1(r10,r12)
154 mtspr SPRN_SRR0,r11 151 mtspr SPRN_SRR0,r11
155 mtspr SPRN_SRR1,r10 152 mtspr SPRN_SRR1,r10
156 mtlr r9 153 mtlr r9
157 SYNC 154 SYNC
158 RFI /* jump to handler, enable MMU */ 155 RFI /* jump to handler, enable MMU */
159 156
160#ifdef CONFIG_6xx 157#ifdef CONFIG_6xx
1614: b power_save_6xx_restore 1584: rlwinm r12,r12,0,~_TLF_NAPPING
159 stw r12,TI_LOCAL_FLAGS(r9)
160 b power_save_6xx_restore
162#endif 161#endif
163 162
164/* 163/*
@@ -167,10 +166,10 @@ transfer_to_handler_cont:
167 */ 166 */
168stack_ovf: 167stack_ovf:
169 /* sometimes we use a statically-allocated stack, which is OK. */ 168 /* sometimes we use a statically-allocated stack, which is OK. */
170 lis r11,_end@h 169 lis r12,_end@h
171 ori r11,r11,_end@l 170 ori r12,r12,_end@l
172 cmplw r1,r11 171 cmplw r1,r12
173 ble 3b /* r1 <= &_end is OK */ 172 ble 5b /* r1 <= &_end is OK */
174 SAVE_NVGPRS(r11) 173 SAVE_NVGPRS(r11)
175 addi r3,r1,STACK_FRAME_OVERHEAD 174 addi r3,r1,STACK_FRAME_OVERHEAD
176 lis r1,init_thread_union@ha 175 lis r1,init_thread_union@ha