Merge branch 'for-upstream' of git://openrisc.net/jonas/linux
[pandora-kernel.git] / arch / powerpc / include / asm / exception-64s.h
index f5dfe34..8057f4f 100644 (file)
 #define EXC_HV H
 #define EXC_STD
 
-#define EXCEPTION_PROLOG_1(area)                                       \
+#define __EXCEPTION_PROLOG_1(area, extra, vec)                         \
        GET_PACA(r13);                                                  \
        std     r9,area+EX_R9(r13);     /* save r9 - r12 */             \
        std     r10,area+EX_R10(r13);                                   \
-       std     r11,area+EX_R11(r13);                                   \
-       std     r12,area+EX_R12(r13);                                   \
        BEGIN_FTR_SECTION_NESTED(66);                                   \
        mfspr   r10,SPRN_CFAR;                                          \
        std     r10,area+EX_CFAR(r13);                                  \
        END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);         \
-       GET_SCRATCH0(r9);                                               \
-       std     r9,area+EX_R13(r13);                                    \
-       mfcr    r9
+       mfcr    r9;                                                     \
+       extra(vec);                                                     \
+       std     r11,area+EX_R11(r13);                                   \
+       std     r12,area+EX_R12(r13);                                   \
+       GET_SCRATCH0(r10);                                              \
+       std     r10,area+EX_R13(r13)
+#define EXCEPTION_PROLOG_1(area, extra, vec)                           \
+       __EXCEPTION_PROLOG_1(area, extra, vec)
 
 #define __EXCEPTION_PROLOG_PSERIES_1(label, h)                         \
        ld      r12,PACAKBASE(r13);     /* get high part of &label */   \
        mtspr   SPRN_##h##SRR1,r10;                                     \
        h##rfid;                                                        \
        b       .       /* prevent speculative execution */
-#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
+#define EXCEPTION_PROLOG_PSERIES_1(label, h)                           \
        __EXCEPTION_PROLOG_PSERIES_1(label, h)
 
-#define EXCEPTION_PROLOG_PSERIES(area, label, h)                       \
-       EXCEPTION_PROLOG_1(area);                                       \
+#define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec)           \
+       EXCEPTION_PROLOG_1(area, extra, vec);                           \
        EXCEPTION_PROLOG_PSERIES_1(label, h);
 
+#define __KVMTEST(n)                                                   \
+       lbz     r10,HSTATE_IN_GUEST(r13);                       \
+       cmpwi   r10,0;                                                  \
+       bne     do_kvm_##n
+
+#define __KVM_HANDLER(area, h, n)                                      \
+do_kvm_##n:                                                            \
+       ld      r10,area+EX_R10(r13);                                   \
+       stw     r9,HSTATE_SCRATCH1(r13);                        \
+       ld      r9,area+EX_R9(r13);                                     \
+       std     r12,HSTATE_SCRATCH0(r13);                       \
+       li      r12,n;                                                  \
+       b       kvmppc_interrupt
+
+#define __KVM_HANDLER_SKIP(area, h, n)                                 \
+do_kvm_##n:                                                            \
+       cmpwi   r10,KVM_GUEST_MODE_SKIP;                                \
+       ld      r10,area+EX_R10(r13);                                   \
+       beq     89f;                                                    \
+       stw     r9,HSTATE_SCRATCH1(r13);                        \
+       ld      r9,area+EX_R9(r13);                                     \
+       std     r12,HSTATE_SCRATCH0(r13);                       \
+       li      r12,n;                                                  \
+       b       kvmppc_interrupt;                                       \
+89:    mtocrf  0x80,r9;                                                \
+       ld      r9,area+EX_R9(r13);                                     \
+       b       kvmppc_skip_##h##interrupt
+
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#define KVMTEST(n)                     __KVMTEST(n)
+#define KVM_HANDLER(area, h, n)                __KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_SKIP(area, h, n)   __KVM_HANDLER_SKIP(area, h, n)
+
+#else
+#define KVMTEST(n)
+#define KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_SKIP(area, h, n)
+#endif
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+#define KVMTEST_PR(n)                  __KVMTEST(n)
+#define KVM_HANDLER_PR(area, h, n)     __KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_PR_SKIP(area, h, n)        __KVM_HANDLER_SKIP(area, h, n)
+
+#else
+#define KVMTEST_PR(n)
+#define KVM_HANDLER_PR(area, h, n)
+#define KVM_HANDLER_PR_SKIP(area, h, n)
+#endif
+
+#define NOTEST(n)
+
 /*
  * 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
        .globl label##_pSeries;                         \
 label##_pSeries:                                       \
        HMT_MEDIUM;                                     \
-       DO_KVM  vec;                                    \
        SET_SCRATCH0(r13);              /* save r13 */          \
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,    \
+                                EXC_STD, KVMTEST_PR, vec)
 
 #define STD_EXCEPTION_HV(loc, vec, label)              \
        . = loc;                                        \
        .globl label##_hv;                              \
 label##_hv:                                            \
        HMT_MEDIUM;                                     \
-       DO_KVM  vec;                                    \
-       SET_SCRATCH0(r13);      /* save r13 */          \
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV)
+       SET_SCRATCH0(r13);      /* save r13 */                  \
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,    \
+                                EXC_HV, KVMTEST, vec)
 
-#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h)                    \
-       HMT_MEDIUM;                                                     \
-       DO_KVM  vec;                                                    \
-       SET_SCRATCH0(r13);    /* save r13 */                            \
-       GET_PACA(r13);                                                  \
-       std     r9,PACA_EXGEN+EX_R9(r13);       /* save r9, r10 */      \
-       std     r10,PACA_EXGEN+EX_R10(r13);                             \
+#define __SOFTEN_TEST(h)                                               \
        lbz     r10,PACASOFTIRQEN(r13);                                 \
-       mfcr    r9;                                                     \
        cmpwi   r10,0;                                                  \
-       beq     masked_##h##interrupt;                                  \
-       GET_SCRATCH0(r10);                                              \
-       std     r10,PACA_EXGEN+EX_R13(r13);                             \
-       std     r11,PACA_EXGEN+EX_R11(r13);                             \
-       std     r12,PACA_EXGEN+EX_R12(r13);                             \
-       ld      r12,PACAKBASE(r13);     /* get high part of &label */   \
-       ld      r10,PACAKMSR(r13);      /* get MSR value for kernel */  \
-       mfspr   r11,SPRN_##h##SRR0;     /* save SRR0 */                 \
-       LOAD_HANDLER(r12,label##_common)                                \
-       mtspr   SPRN_##h##SRR0,r12;                                     \
-       mfspr   r12,SPRN_##h##SRR1;     /* and SRR1 */                  \
-       mtspr   SPRN_##h##SRR1,r10;                                     \
-       h##rfid;                                                        \
-       b       .       /* prevent speculative execution */
-#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h)                     \
-       __MASKABLE_EXCEPTION_PSERIES(vec, label, h)
+       beq     masked_##h##interrupt
+#define _SOFTEN_TEST(h)        __SOFTEN_TEST(h)
+
+#define SOFTEN_TEST_PR(vec)                                            \
+       KVMTEST_PR(vec);                                                \
+       _SOFTEN_TEST(EXC_STD)
+
+#define SOFTEN_TEST_HV(vec)                                            \
+       KVMTEST(vec);                                                   \
+       _SOFTEN_TEST(EXC_HV)
+
+#define SOFTEN_TEST_HV_201(vec)                                                \
+       KVMTEST(vec);                                                   \
+       _SOFTEN_TEST(EXC_STD)
+
+#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)             \
+       HMT_MEDIUM;                                                     \
+       SET_SCRATCH0(r13);    /* save r13 */                            \
+       __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec);           \
+       EXCEPTION_PROLOG_PSERIES_1(label##_common, h);
+#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)              \
+       __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)
 
 #define MASKABLE_EXCEPTION_PSERIES(loc, vec, label)                    \
        . = loc;                                                        \
        .globl label##_pSeries;                                         \
 label##_pSeries:                                                       \
-       _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_STD)
+       _MASKABLE_EXCEPTION_PSERIES(vec, label,                         \
+                                   EXC_STD, SOFTEN_TEST_PR)
 
 #define MASKABLE_EXCEPTION_HV(loc, vec, label)                         \
        . = loc;                                                        \
        .globl label##_hv;                                              \
 label##_hv:                                                            \
-       _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_HV)
+       _MASKABLE_EXCEPTION_PSERIES(vec, label,                         \
+                                   EXC_HV, SOFTEN_TEST_HV)
 
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS                           \