Merge tag 'powerpc-4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / arch / powerpc / include / asm / exception-64s.h
index ed3bead..183d73b 100644 (file)
@@ -167,17 +167,14 @@ BEGIN_FTR_SECTION_NESTED(943)                                             \
        std     ra,offset(r13);                                         \
 END_FTR_SECTION_NESTED(ftr,ftr,943)
 
-#define EXCEPTION_PROLOG_0_PACA(area)                                  \
+#define EXCEPTION_PROLOG_0(area)                                       \
+       GET_PACA(r13);                                                  \
        std     r9,area+EX_R9(r13);     /* save r9 */                   \
        OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);                     \
        HMT_MEDIUM;                                                     \
        std     r10,area+EX_R10(r13);   /* save r10 - r12 */            \
        OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR)
 
-#define EXCEPTION_PROLOG_0(area)                                       \
-       GET_PACA(r13);                                                  \
-       EXCEPTION_PROLOG_0_PACA(area)
-
 #define __EXCEPTION_PROLOG_1(area, extra, vec)                         \
        OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR);         \
        OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR);          \
@@ -203,17 +200,26 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 #define EXCEPTION_PROLOG_PSERIES_1(label, h)                           \
        __EXCEPTION_PROLOG_PSERIES_1(label, h)
 
+/* _NORI variant keeps MSR_RI clear */
+#define __EXCEPTION_PROLOG_PSERIES_1_NORI(label, h)                    \
+       ld      r10,PACAKMSR(r13);      /* get MSR value for kernel */  \
+       xori    r10,r10,MSR_RI;         /* Clear MSR_RI */              \
+       mfspr   r11,SPRN_##h##SRR0;     /* save SRR0 */                 \
+       LOAD_HANDLER(r12,label)                                         \
+       mtspr   SPRN_##h##SRR0,r12;                                     \
+       mfspr   r12,SPRN_##h##SRR1;     /* and SRR1 */                  \
+       mtspr   SPRN_##h##SRR1,r10;                                     \
+       h##rfid;                                                        \
+       b       .       /* prevent speculative execution */
+
+#define EXCEPTION_PROLOG_PSERIES_1_NORI(label, h)                      \
+       __EXCEPTION_PROLOG_PSERIES_1_NORI(label, h)
+
 #define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec)           \
        EXCEPTION_PROLOG_0(area);                                       \
        EXCEPTION_PROLOG_1(area, extra, vec);                           \
        EXCEPTION_PROLOG_PSERIES_1(label, h);
 
-/* Have the PACA in r13 already */
-#define EXCEPTION_PROLOG_PSERIES_PACA(area, label, h, extra, vec)      \
-       EXCEPTION_PROLOG_0_PACA(area);                                  \
-       EXCEPTION_PROLOG_1(area, extra, vec);                           \
-       EXCEPTION_PROLOG_PSERIES_1(label, h);
-
 #define __KVMTEST(h, n)                                                        \
        lbz     r10,HSTATE_IN_GUEST(r13);                               \
        cmpwi   r10,0;                                                  \
@@ -256,11 +262,6 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
        ld      r9,area+EX_R9(r13);                                     \
        bctr
 
-#define BRANCH_TO_KVM(reg, label)                                      \
-       __LOAD_FAR_HANDLER(reg, label);                                 \
-       mtctr   reg;                                                    \
-       bctr
-
 #else
 #define BRANCH_TO_COMMON(reg, label)                                   \
        b       label
@@ -268,15 +269,18 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 #define BRANCH_LINK_TO_FAR(label)                                      \
        bl      label
 
-#define BRANCH_TO_KVM(reg, label)                                      \
-       b       label
-
 #define __BRANCH_TO_KVM_EXIT(area, label)                              \
        ld      r9,area+EX_R9(r13);                                     \
        b       label
 
 #endif
 
+/* Do not enable RI */
+#define EXCEPTION_PROLOG_PSERIES_NORI(area, label, h, extra, vec)      \
+       EXCEPTION_PROLOG_0(area);                                       \
+       EXCEPTION_PROLOG_1(area, extra, vec);                           \
+       EXCEPTION_PROLOG_PSERIES_1_NORI(label, h);
+
 
 #define __KVM_HANDLER(area, h, n)                                      \
        BEGIN_FTR_SECTION_NESTED(947)                                   \
@@ -325,6 +329,15 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 
 #define NOTEST(n)
 
+#define EXCEPTION_PROLOG_COMMON_1()                                       \
+       std     r9,_CCR(r1);            /* save CR in stackframe        */ \
+       std     r11,_NIP(r1);           /* save SRR0 in stackframe      */ \
+       std     r12,_MSR(r1);           /* save SRR1 in stackframe      */ \
+       std     r10,0(r1);              /* make stack chain pointer     */ \
+       std     r0,GPR0(r1);            /* save r0 in stackframe        */ \
+       std     r10,GPR1(r1);           /* save r1 in stackframe        */ \
+
+
 /*
  * The common exception prolog is used for all except a few exceptions
  * such as a segment miss on a kernel address.  We have to be prepared
@@ -349,12 +362,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
        addi    r3,r13,area;            /* r3 -> where regs are saved*/    \
        RESTORE_CTR(r1, area);                                             \
        b       bad_stack;                                                 \
-3:     std     r9,_CCR(r1);            /* save CR in stackframe        */ \
-       std     r11,_NIP(r1);           /* save SRR0 in stackframe      */ \
-       std     r12,_MSR(r1);           /* save SRR1 in stackframe      */ \
-       std     r10,0(r1);              /* make stack chain pointer     */ \
-       std     r0,GPR0(r1);            /* save r0 in stackframe        */ \
-       std     r10,GPR1(r1);           /* save r1 in stackframe        */ \
+3:     EXCEPTION_PROLOG_COMMON_1();                                       \
        beq     4f;                     /* if from kernel mode          */ \
        ACCOUNT_CPU_USER_ENTRY(r13, r9, r10);                              \
        SAVE_PPR(area, r9, r10);                                           \
@@ -522,7 +530,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 
 #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label)                    \
        EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec);            \
-       EXCEPTION_PROLOG_PSERIES_1(label, EXC_HV)
+       EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_HV)
 
 /*
  * Our exception common code can be passed various "additions"
@@ -547,26 +555,39 @@ BEGIN_FTR_SECTION                         \
        beql    ppc64_runlatch_on_trampoline;   \
 END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
 
-#define EXCEPTION_COMMON(trap, label, hdlr, ret, additions)    \
-       EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);              \
+#define EXCEPTION_COMMON(area, trap, label, hdlr, ret, additions) \
+       EXCEPTION_PROLOG_COMMON(trap, area);                    \
        /* Volatile regs are potentially clobbered here */      \
        additions;                                              \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
        bl      hdlr;                                           \
        b       ret
 
+/*
+ * Exception where stack is already set in r1, r1 is saved in r10, and it
+ * continues rather than returns.
+ */
+#define EXCEPTION_COMMON_NORET_STACK(area, trap, label, hdlr, additions) \
+       EXCEPTION_PROLOG_COMMON_1();                            \
+       EXCEPTION_PROLOG_COMMON_2(area);                        \
+       EXCEPTION_PROLOG_COMMON_3(trap);                        \
+       /* Volatile regs are potentially clobbered here */      \
+       additions;                                              \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+       bl      hdlr
+
 #define STD_EXCEPTION_COMMON(trap, label, hdlr)                        \
-       EXCEPTION_COMMON(trap, label, hdlr, ret_from_except,    \
-                        ADD_NVGPRS;ADD_RECONCILE)
+       EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr,         \
+               ret_from_except, ADD_NVGPRS;ADD_RECONCILE)
 
 /*
  * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
  * in the idle task and therefore need the special idle handling
  * (finish nap and runlatch)
  */
-#define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)            \
-       EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
-                        FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)
+#define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)          \
+       EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr,         \
+               ret_from_except_lite, FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)
 
 /*
  * When the idle code in power4_idle puts the CPU into NAP mode,