aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/exceptions-64e.S
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-14 00:12:16 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-14 00:13:18 -0400
commit34d97e07cc81ab6f1e63696127cc7a5d2c4fce4b (patch)
treec406c3e1b964c4ec8bcd5650d6a339115b4ef6d3 /arch/powerpc/kernel/exceptions-64e.S
parent850f22d5688941ea51628f3f8f8dcf3baff409ff (diff)
powerpc/book3e: Add generic 64-bit idle powersave support
We use a similar technique to ppc32: We set a thread local flag to indicate that we are about to enter or have entered the stop state, and have fixup code in the async interrupt entry code that reacts to this flag to make us return to a different location (sets NIP to LINK in our case). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> -- v2. Fix lockdep bug Re-mask interrupts when coming back from idle
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64e.S')
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S23
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index a42637c3a72d..316465a32a9c 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -204,11 +204,30 @@ exc_##n##_bad_stack: \
204 lis r,TSR_FIS@h; \ 204 lis r,TSR_FIS@h; \
205 mtspr SPRN_TSR,r 205 mtspr SPRN_TSR,r
206 206
207/* Used by asynchronous interrupt that may happen in the idle loop.
208 *
209 * This check if the thread was in the idle loop, and if yes, returns
210 * to the caller rather than the PC. This is to avoid a race if
211 * interrupts happen before the wait instruction.
212 */
213#define CHECK_NAPPING() \
214 clrrdi r11,r1,THREAD_SHIFT; \
215 ld r10,TI_LOCAL_FLAGS(r11); \
216 andi. r9,r10,_TLF_NAPPING; \
217 beq+ 1f; \
218 ld r8,_LINK(r1); \
219 rlwinm r7,r10,0,~_TLF_NAPPING; \
220 std r8,_NIP(r1); \
221 std r7,TI_LOCAL_FLAGS(r11); \
2221:
223
224
207#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ 225#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \
208 START_EXCEPTION(label); \ 226 START_EXCEPTION(label); \
209 NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ 227 NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \
210 EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \ 228 EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \
211 ack(r8); \ 229 ack(r8); \
230 CHECK_NAPPING(); \
212 addi r3,r1,STACK_FRAME_OVERHEAD; \ 231 addi r3,r1,STACK_FRAME_OVERHEAD; \
213 bl hdlr; \ 232 bl hdlr; \
214 b .ret_from_except_lite; 233 b .ret_from_except_lite;
@@ -257,6 +276,7 @@ interrupt_end_book3e:
257 CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) 276 CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE)
258// EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL) 277// EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL)
259// bl special_reg_save_crit 278// bl special_reg_save_crit
279// CHECK_NAPPING();
260// addi r3,r1,STACK_FRAME_OVERHEAD 280// addi r3,r1,STACK_FRAME_OVERHEAD
261// bl .critical_exception 281// bl .critical_exception
262// b ret_from_crit_except 282// b ret_from_crit_except
@@ -268,6 +288,7 @@ interrupt_end_book3e:
268// EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL) 288// EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL)
269// bl special_reg_save_mc 289// bl special_reg_save_mc
270// addi r3,r1,STACK_FRAME_OVERHEAD 290// addi r3,r1,STACK_FRAME_OVERHEAD
291// CHECK_NAPPING();
271// bl .machine_check_exception 292// bl .machine_check_exception
272// b ret_from_mc_except 293// b ret_from_mc_except
273 b . 294 b .
@@ -338,6 +359,7 @@ interrupt_end_book3e:
338 CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) 359 CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE)
339// EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL) 360// EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL)
340// bl special_reg_save_crit 361// bl special_reg_save_crit
362// CHECK_NAPPING();
341// addi r3,r1,STACK_FRAME_OVERHEAD 363// addi r3,r1,STACK_FRAME_OVERHEAD
342// bl .unknown_exception 364// bl .unknown_exception
343// b ret_from_crit_except 365// b ret_from_crit_except
@@ -434,6 +456,7 @@ kernel_dbg_exc:
434 CRIT_EXCEPTION_PROLOG(0x2080, PROLOG_ADDITION_NONE) 456 CRIT_EXCEPTION_PROLOG(0x2080, PROLOG_ADDITION_NONE)
435// EXCEPTION_COMMON(0x2080, PACA_EXCRIT, INTS_DISABLE_ALL) 457// EXCEPTION_COMMON(0x2080, PACA_EXCRIT, INTS_DISABLE_ALL)
436// bl special_reg_save_crit 458// bl special_reg_save_crit
459// CHECK_NAPPING();
437// addi r3,r1,STACK_FRAME_OVERHEAD 460// addi r3,r1,STACK_FRAME_OVERHEAD
438// bl .doorbell_critical_exception 461// bl .doorbell_critical_exception
439// b ret_from_crit_except 462// b ret_from_crit_except