diff options
author | Paul Mackerras <paulus@samba.org> | 2006-10-17 20:11:22 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-10-17 20:12:53 -0400 |
commit | b0a779debd56514b2b5de7617a1643e5dac2d4dd (patch) | |
tree | e342bf44d34b8944da803efc690197988319fa4f /arch/powerpc | |
parent | 035223fb28791f0eb0d5719727355d3f6817d228 (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.S | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 28 |
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 | */ |
964 | fast_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 |
965 | fast_exception_return: | 973 | fast_exception_return: |
966 | ld r12,_MSR(r1) | 974 | ld r12,_MSR(r1) |
967 | ld r11,_NIP(r1) | 975 | 1: 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 |
1372 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
1373 | #endif | ||
1374 | BEGIN_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 */ | ||
1380 | END_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 |
1375 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
1376 | #endif | ||
1377 | BEGIN_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 */ | ||
1382 | END_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) |