Merge tag 'mvebu-fixes-4.8-1' of git://git.infradead.org/linux-mvebu into fixes
[cascardo/linux.git] / arch / powerpc / kernel / exceptions-64s.S
index 8bcc1b4..df6d45e 100644 (file)
@@ -107,25 +107,9 @@ BEGIN_FTR_SECTION
        beq     9f
 
        cmpwi   cr3,r13,2
-
-       /*
-        * Check if last bit of HSPGR0 is set. This indicates whether we are
-        * waking up from winkle.
-        */
        GET_PACA(r13)
-       clrldi  r5,r13,63
-       clrrdi  r13,r13,1
-       cmpwi   cr4,r5,1
-       mtspr   SPRN_HSPRG0,r13
+       bl      pnv_restore_hyp_resource
 
-       lbz     r0,PACA_THREAD_IDLE_STATE(r13)
-       cmpwi   cr2,r0,PNV_THREAD_NAP
-       bgt     cr2,8f                          /* Either sleep or Winkle */
-
-       /* Waking up from nap should not cause hypervisor state loss */
-       bgt     cr3,.
-
-       /* Waking up from nap */
        li      r0,PNV_THREAD_RUNNING
        stb     r0,PACA_THREAD_IDLE_STATE(r13)  /* Clear thread state */
 
@@ -143,13 +127,9 @@ BEGIN_FTR_SECTION
 
        /* Return SRR1 from power7_nap() */
        mfspr   r3,SPRN_SRR1
-       beq     cr3,2f
-       b       power7_wakeup_noloss
-2:     b       power7_wakeup_loss
-
-       /* Fast Sleep wakeup on PowerNV */
-8:     GET_PACA(r13)
-       b       power7_wakeup_tb_loss
+       blt     cr3,2f
+       b       pnv_wakeup_loss
+2:     b       pnv_wakeup_noloss
 
 9:
 END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
@@ -164,29 +144,14 @@ machine_check_pSeries_1:
         * vector
         */
        SET_SCRATCH0(r13)               /* save r13 */
-#ifdef CONFIG_PPC_P7_NAP
-BEGIN_FTR_SECTION
-       /* Running native on arch 2.06 or later, check if we are
-        * waking up from nap. We only handle no state loss and
-        * supervisor state loss. We do -not- handle hypervisor
-        * state loss at this time.
+       /*
+        * Running native on arch 2.06 or later, we may wakeup from winkle
+        * inside machine check. If yes, then last bit of HSPGR0 would be set
+        * to 1. Hence clear it unconditionally.
         */
-       mfspr   r13,SPRN_SRR1
-       rlwinm. r13,r13,47-31,30,31
-       OPT_GET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR)
-       beq     9f
-
-       mfspr   r13,SPRN_SRR1
-       rlwinm. r13,r13,47-31,30,31
-       /* waking up from powersave (nap) state */
-       cmpwi   cr1,r13,2
-       /* Total loss of HV state is fatal. let's just stay stuck here */
-       OPT_GET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR)
-       bgt     cr1,.
-9:
-       OPT_SET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR)
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
-#endif /* CONFIG_PPC_P7_NAP */
+       GET_PACA(r13)
+       clrrdi  r13,r13,1
+       SET_PACA(r13)
        EXCEPTION_PROLOG_0(PACA_EXMC)
 BEGIN_FTR_SECTION
        b       machine_check_powernv_early
@@ -351,6 +316,12 @@ hv_doorbell_trampoline:
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       h_doorbell_hv
 
+       . = 0xea0
+hv_virt_irq_trampoline:
+       SET_SCRATCH0(r13)
+       EXCEPTION_PROLOG_0(PACA_EXGEN)
+       b       h_virt_irq_hv
+
        /* We need to deal with the Altivec unavailable exception
         * here which is at 0xf20, thus in the middle of the
         * prolog code of the PerformanceMonitor one. A little
@@ -601,6 +572,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
        MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell)
        KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82)
 
+       MASKABLE_EXCEPTION_HV_OOL(0xea2, h_virt_irq)
+       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xea2)
+
        /* moved from 0xf00 */
        STD_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
        KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xf00)
@@ -680,6 +654,10 @@ _GLOBAL(__replay_interrupt)
 BEGIN_FTR_SECTION
        cmpwi   r3,0xe80
        beq     h_doorbell_common
+       cmpwi   r3,0xea0
+       beq     h_virt_irq_common
+       cmpwi   r3,0xe60
+       beq     hmi_exception_common
 FTR_SECTION_ELSE
        cmpwi   r3,0xa00
        beq     doorbell_super_common
@@ -754,6 +732,7 @@ kvmppc_skip_Hinterrupt:
 #else
        STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, unknown_exception)
 #endif
+       STD_EXCEPTION_COMMON_ASYNC(0xea0, h_virt_irq, do_IRQ)
        STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, performance_monitor_exception)
        STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, instruction_breakpoint_exception)
        STD_EXCEPTION_COMMON(0x1502, denorm, unknown_exception)
@@ -762,11 +741,6 @@ kvmppc_skip_Hinterrupt:
 #else
        STD_EXCEPTION_COMMON(0x1700, altivec_assist, unknown_exception)
 #endif
-#ifdef CONFIG_CBE_RAS
-       STD_EXCEPTION_COMMON(0x1200, cbe_system_error, cbe_system_error_exception)
-       STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, cbe_maintenance_exception)
-       STD_EXCEPTION_COMMON(0x1800, cbe_thermal, cbe_thermal_exception)
-#endif /* CONFIG_CBE_RAS */
 
        /*
         * Relocation-on interrupts: A subset of the interrupts can be delivered
@@ -877,6 +851,12 @@ h_doorbell_relon_trampoline:
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       h_doorbell_relon_hv
 
+       . = 0x4ea0
+h_virt_irq_relon_trampoline:
+       SET_SCRATCH0(r13)
+       EXCEPTION_PROLOG_0(PACA_EXGEN)
+       b       h_virt_irq_relon_hv
+
        . = 0x4f00
 performance_monitor_relon_pseries_trampoline:
        SET_SCRATCH0(r13)
@@ -945,7 +925,7 @@ BEGIN_MMU_FTR_SECTION
        b       do_hash_page            /* Try to handle as hpte fault */
 MMU_FTR_SECTION_ELSE
        b       handle_page_fault
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
 
        .align  7
        .globl  h_data_storage_common
@@ -976,7 +956,7 @@ BEGIN_MMU_FTR_SECTION
        b       do_hash_page            /* Try to handle as hpte fault */
 MMU_FTR_SECTION_ELSE
        b       handle_page_fault
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
 
        STD_EXCEPTION_COMMON(0xe20, h_instr_storage, unknown_exception)
 
@@ -1131,12 +1111,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        bl      vsx_unavailable_exception
        b       ret_from_except
 
-       STD_EXCEPTION_COMMON(0xf60, facility_unavailable, facility_unavailable_exception)
-       STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, facility_unavailable_exception)
-
        /* Equivalents to the above handlers for relocation-on interrupt vectors */
        STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist)
        MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
+       MASKABLE_RELON_EXCEPTION_HV_OOL(0xea0, h_virt_irq)
 
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
@@ -1170,9 +1148,18 @@ fwnmi_data_area:
        . = 0x8000
 #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
+       STD_EXCEPTION_COMMON(0xf60, facility_unavailable, facility_unavailable_exception)
+       STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, facility_unavailable_exception)
+
+#ifdef CONFIG_CBE_RAS
+       STD_EXCEPTION_COMMON(0x1200, cbe_system_error, cbe_system_error_exception)
+       STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, cbe_maintenance_exception)
+       STD_EXCEPTION_COMMON(0x1800, cbe_thermal, cbe_thermal_exception)
+#endif /* CONFIG_CBE_RAS */
+
        .globl hmi_exception_early
 hmi_exception_early:
-       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0xe60)
+       EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, 0xe62)
        mr      r10,r1                  /* Save r1                      */
        ld      r1,PACAEMERGSP(r13)     /* Use emergency stack          */
        subi    r1,r1,INT_FRAME_SIZE    /* alloc stack frame            */
@@ -1271,25 +1258,51 @@ machine_check_handle_early:
         * Check if thread was in power saving mode. We come here when any
         * of the following is true:
         * a. thread wasn't in power saving mode
-        * b. thread was in power saving mode with no state loss or
-        *    supervisor state loss
+        * b. thread was in power saving mode with no state loss,
+        *    supervisor state loss or hypervisor state loss.
         *
-        * Go back to nap again if (b) is true.
+        * Go back to nap/sleep/winkle mode again if (b) is true.
         */
        rlwinm. r11,r12,47-31,30,31     /* Was it in power saving mode? */
        beq     4f                      /* No, it wasn;t */
        /* Thread was in power saving mode. Go back to nap again. */
        cmpwi   r11,2
-       bne     3f
-       /* Supervisor state loss */
+       blt     3f
+       /* Supervisor/Hypervisor state loss */
        li      r0,1
        stb     r0,PACA_NAPSTATELOST(r13)
 3:     bl      machine_check_queue_event
        MACHINE_CHECK_HANDLER_WINDUP
        GET_PACA(r13)
        ld      r1,PACAR1(r13)
-       li      r3,PNV_THREAD_NAP
-       b       power7_enter_nap_mode
+       /*
+        * Check what idle state this CPU was in and go back to same mode
+        * again.
+        */
+       lbz     r3,PACA_THREAD_IDLE_STATE(r13)
+       cmpwi   r3,PNV_THREAD_NAP
+       bgt     10f
+       IDLE_STATE_ENTER_SEQ(PPC_NAP)
+       /* No return */
+10:
+       cmpwi   r3,PNV_THREAD_SLEEP
+       bgt     2f
+       IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
+       /* No return */
+
+2:
+       /*
+        * Go back to winkle. Please note that this thread was woken up in
+        * machine check from winkle and have not restored the per-subcore
+        * state. Hence before going back to winkle, set last bit of HSPGR0
+        * to 1. This will make sure that if this thread gets woken up
+        * again at reset vector 0x100 then it will get chance to restore
+        * the subcore state.
+        */
+       ori     r13,r13,1
+       SET_PACA(r13)
+       IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
+       /* No return */
 4:
 #endif
        /*
@@ -1390,7 +1403,7 @@ slb_miss_realmode:
 #ifdef CONFIG_PPC_STD_MMU_64
 BEGIN_MMU_FTR_SECTION
        bl      slb_allocate_realmode
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
 #endif
        /* All done -- return from exception. */
 
@@ -1404,7 +1417,7 @@ BEGIN_MMU_FTR_SECTION
        beq-    2f
 FTR_SECTION_ELSE
        b       2f
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
 
 .machine       push
 .machine       "power4"