aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-10-17 20:11:22 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-17 20:12:53 -0400
commitb0a779debd56514b2b5de7617a1643e5dac2d4dd (patch)
treee342bf44d34b8944da803efc690197988319fa4f /arch/powerpc
parent035223fb28791f0eb0d5719727355d3f6817d228 (diff)
[POWERPC] Make sure interrupt enable gets restored properly
The lazy IRQ disable patch missed a couple of places where the interrupt enable flags need to be restored correctly. First, we weren't restoring the paca->hard_enabled flag on interrupt exit. Instead of saving it on entry, we compute it from the MSR_EE bit in the MSR we are restoring at exit. Secondly, the MMU hash miss code was clearing both paca->soft_enabled and paca->hard_enabled but not restoring them in the case where hash_page was able to resolve the miss from the Linux page tables. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/entry_64.S4
-rw-r--r--arch/powerpc/kernel/head_64.S28
2 files changed, 23 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index efda48741b29..86e2bdd5afd6 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -489,6 +489,10 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
489 andi. r0,r3,MSR_RI 489 andi. r0,r3,MSR_RI
490 beq- unrecov_restore 490 beq- unrecov_restore
491 491
492 /* extract EE bit and use it to restore paca->hard_enabled */
493 rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
494 stb r4,PACAHARDIRQEN(r13)
495
492 andi. r0,r3,MSR_PR 496 andi. r0,r3,MSR_PR
493 497
494 /* 498 /*
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index c93d9f35a121..d2890050b7e0 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -961,10 +961,18 @@ bad_stack:
961 * any task or sent any task a signal, you should use 961 * any task or sent any task a signal, you should use
962 * ret_from_except or ret_from_except_lite instead of this. 962 * ret_from_except or ret_from_except_lite instead of this.
963 */ 963 */
964fast_exc_return_irq: /* restores irq state too */
965 ld r3,SOFTE(r1)
966 ld r12,_MSR(r1)
967 stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */
968 rldicl r4,r12,49,63 /* get MSR_EE to LSB */
969 stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
970 b 1f
971
964 .globl fast_exception_return 972 .globl fast_exception_return
965fast_exception_return: 973fast_exception_return:
966 ld r12,_MSR(r1) 974 ld r12,_MSR(r1)
967 ld r11,_NIP(r1) 9751: ld r11,_NIP(r1)
968 andi. r3,r12,MSR_RI /* check if RI is set */ 976 andi. r3,r12,MSR_RI /* check if RI is set */
969 beq- unrecov_fer 977 beq- unrecov_fer
970 978
@@ -1361,6 +1369,16 @@ BEGIN_FW_FTR_SECTION
1361 * interrupts if necessary. 1369 * interrupts if necessary.
1362 */ 1370 */
1363 beq .ret_from_except_lite 1371 beq .ret_from_except_lite
1372END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1373#endif
1374BEGIN_FW_FTR_SECTION
1375 /*
1376 * Here we have interrupts hard-disabled, so it is sufficient
1377 * to restore paca->{soft,hard}_enable and get out.
1378 */
1379 beq fast_exc_return_irq /* Return from exception on success */
1380END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1381
1364 /* For a hash failure, we don't bother re-enabling interrupts */ 1382 /* For a hash failure, we don't bother re-enabling interrupts */
1365 ble- 12f 1383 ble- 12f
1366 1384
@@ -1372,14 +1390,6 @@ BEGIN_FW_FTR_SECTION
1372 ld r3,SOFTE(r1) 1390 ld r3,SOFTE(r1)
1373 bl .local_irq_restore 1391 bl .local_irq_restore
1374 b 11f 1392 b 11f
1375END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1376#endif
1377BEGIN_FW_FTR_SECTION
1378 beq fast_exception_return /* Return from exception on success */
1379 ble- 12f /* Failure return from hash_page */
1380
1381 /* fall through */
1382END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1383 1393
1384/* Here we have a page fault that hash_page can't handle. */ 1394/* Here we have a page fault that hash_page can't handle. */
1385_GLOBAL(handle_page_fault) 1395_GLOBAL(handle_page_fault)