powerpc/book3s: handle HMIs for cpus in nap mode.
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Tue, 29 Jul 2014 13:10:13 +0000 (18:40 +0530)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 5 Aug 2014 06:33:57 +0000 (16:33 +1000)
HMIs are thread specific and can come while thread is in sleep/nap mode.
Hence with SMT=off mode we can receive HMIs on sleeping threads. For
interrupt received in nap mode, cpu wakes up at system reset vector, clears
the interrupt and go back to nap mode again. But HMIs are sticky and they
keep happening until we clear reason bits from HMER. Hence add a special
check for HMI in reset vector (through power7_wakeup_* functions) and
invoke opal call to handle HMI.

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/idle_power7.S

index 5cf3d367190df77cdde609d5a926ce3269b20a4a..06305f653ab1c557acac2f4c93fc7dde15757bec 100644 (file)
@@ -135,10 +135,36 @@ _GLOBAL(power7_sleep)
        b       power7_powersave_common
        /* No return */
 
+#define CHECK_HMI_INTERRUPT                                            \
+       mfspr   r0,SPRN_SRR1;                                           \
+BEGIN_FTR_SECTION_NESTED(66);                                          \
+       rlwinm  r0,r0,45-31,0xf;  /* extract wake reason field (P8) */  \
+FTR_SECTION_ELSE_NESTED(66);                                           \
+       rlwinm  r0,r0,45-31,0xe;  /* P7 wake reason field is 3 bits */  \
+ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66);               \
+       cmpwi   r0,0xa;                 /* Hypervisor maintenance ? */  \
+       bne     20f;                                                    \
+       /* Invoke opal call to handle hmi */                            \
+       ld      r2,PACATOC(r13);                                        \
+       ld      r1,PACAR1(r13);                                         \
+       std     r3,ORIG_GPR3(r1);       /* Save original r3 */          \
+       li      r0,OPAL_HANDLE_HMI;                                     \
+       LOAD_REG_ADDR(r11,opal);                                        \
+       ld      r12,8(r11);                                             \
+       ld      r2,0(r11);                                              \
+       mtctr   r12;                                                    \
+       bctrl;                                                          \
+       ld      r3,ORIG_GPR3(r1);       /* Restore original r3 */       \
+20:    nop;
+
+
 _GLOBAL(power7_wakeup_tb_loss)
        ld      r2,PACATOC(r13);
        ld      r1,PACAR1(r13)
 
+BEGIN_FTR_SECTION
+       CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
        /* Time base re-sync */
        li      r0,OPAL_RESYNC_TIMEBASE
        LOAD_REG_ADDR(r11,opal);
@@ -163,6 +189,9 @@ _GLOBAL(power7_wakeup_tb_loss)
 
 _GLOBAL(power7_wakeup_loss)
        ld      r1,PACAR1(r13)
+BEGIN_FTR_SECTION
+       CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
        REST_NVGPRS(r1)
        REST_GPR(2, r1)
        ld      r3,_CCR(r1)
@@ -178,6 +207,9 @@ _GLOBAL(power7_wakeup_noloss)
        lbz     r0,PACA_NAPSTATELOST(r13)
        cmpwi   r0,0
        bne     power7_wakeup_loss
+BEGIN_FTR_SECTION
+       CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
        ld      r1,PACAR1(r13)
        ld      r4,_MSR(r1)
        ld      r5,_NIP(r1)