[POWERPC] Make sure interrupt enable gets restored properly
authorPaul Mackerras <paulus@samba.org>
Wed, 18 Oct 2006 00:11:22 +0000 (10:11 +1000)
committerPaul Mackerras <paulus@samba.org>
Wed, 18 Oct 2006 00:12:53 +0000 (10:12 +1000)
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>
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/head_64.S

index efda487..86e2bdd 100644 (file)
@@ -489,6 +489,10 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
        andi.   r0,r3,MSR_RI
        beq-    unrecov_restore
 
+       /* extract EE bit and use it to restore paca->hard_enabled */
+       rldicl  r4,r3,49,63             /* r0 = (r3 >> 15) & 1 */
+       stb     r4,PACAHARDIRQEN(r13)
+
        andi.   r0,r3,MSR_PR
 
        /*
index c93d9f3..d289005 100644 (file)
@@ -961,10 +961,18 @@ bad_stack:
  * any task or sent any task a signal, you should use
  * ret_from_except or ret_from_except_lite instead of this.
  */
+fast_exc_return_irq:                   /* restores irq state too */
+       ld      r3,SOFTE(r1)
+       ld      r12,_MSR(r1)
+       stb     r3,PACASOFTIRQEN(r13)   /* restore paca->soft_enabled */
+       rldicl  r4,r12,49,63            /* get MSR_EE to LSB */
+       stb     r4,PACAHARDIRQEN(r13)   /* restore paca->hard_enabled */
+       b       1f
+
        .globl  fast_exception_return
 fast_exception_return:
        ld      r12,_MSR(r1)
-       ld      r11,_NIP(r1)
+1:     ld      r11,_NIP(r1)
        andi.   r3,r12,MSR_RI           /* check if RI is set */
        beq-    unrecov_fer
 
@@ -1361,6 +1369,16 @@ BEGIN_FW_FTR_SECTION
         * interrupts if necessary.
         */
        beq     .ret_from_except_lite
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+#endif
+BEGIN_FW_FTR_SECTION
+       /*
+        * Here we have interrupts hard-disabled, so it is sufficient
+        * to restore paca->{soft,hard}_enable and get out.
+        */
+       beq     fast_exc_return_irq     /* Return from exception on success */
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
+
        /* For a hash failure, we don't bother re-enabling interrupts */
        ble-    12f
 
@@ -1372,14 +1390,6 @@ BEGIN_FW_FTR_SECTION
        ld      r3,SOFTE(r1)
        bl      .local_irq_restore
        b       11f
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif
-BEGIN_FW_FTR_SECTION
-       beq     fast_exception_return   /* Return from exception on success */
-       ble-    12f                     /* Failure return from hash_page */
-
-       /* fall through */
-END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 
 /* Here we have a page fault that hash_page can't handle. */
 _GLOBAL(handle_page_fault)