powerpc, KVM: Rework KVM checks in first-level interrupt handlers
authorPaul Mackerras <paulus@samba.org>
Wed, 29 Jun 2011 00:18:26 +0000 (00:18 +0000)
committerAvi Kivity <avi@redhat.com>
Tue, 12 Jul 2011 10:16:48 +0000 (13:16 +0300)
Instead of branching out-of-line with the DO_KVM macro to check if we
are in a KVM guest at the time of an interrupt, this moves the KVM
check inline in the first-level interrupt handlers.  This speeds up
the non-KVM case and makes sure that none of the interrupt handlers
are missing the check.

Because the first-level interrupt handlers are now larger, some things
had to be move out of line in exceptions-64s.S.

This all necessitated some minor changes to the interrupt entry code
in KVM.  This also streamlines the book3s_32 KVM test.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/book3s_segment.S
arch/powerpc/platforms/iseries/exception.S
arch/powerpc/platforms/iseries/exception.h

index f5dfe3411f64d3bf74dbcf7c6b4a331c8cac0809..b6a3a443fbde04ccbf5a1edc95f5d94f1019cbf3 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,PACA_KVM_SVCPU+SVCPU_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,PACA_KVM_SVCPU+SVCPU_SCRATCH1(r13);                  \
+       ld      r9,area+EX_R9(r13);                                     \
+       std     r12,PACA_KVM_SVCPU+SVCPU_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,PACA_KVM_SVCPU+SVCPU_SCRATCH1(r13);                  \
+       ld      r9,area+EX_R9(r13);                                     \
+       std     r12,PACA_KVM_SVCPU+SVCPU_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
+
+#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, 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(vec)                                               \
+       KVMTEST(vec);                                                   \
+       _SOFTEN_TEST(EXC_STD)
+
+#define SOFTEN_TEST_HV(vec)                                            \
+       KVMTEST(vec);                                                   \
+       _SOFTEN_TEST(EXC_HV)
+
+#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)
 
 #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                           \
index a85f4874cba771fca11887ce4be593bde2c5728a..e76472cbf3b5877d8b366a902c5c0fae68ca633f 100644 (file)
@@ -40,7 +40,6 @@ __start_interrupts:
        .globl system_reset_pSeries;
 system_reset_pSeries:
        HMT_MEDIUM;
-       DO_KVM  0x100;
        SET_SCRATCH0(r13)
 #ifdef CONFIG_PPC_P7_NAP
 BEGIN_FTR_SECTION
@@ -65,67 +64,45 @@ BEGIN_FTR_SECTION
        beq     .
 END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206)
 #endif /* CONFIG_PPC_P7_NAP */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+                                NOTEST, 0x100)
 
        . = 0x200
-_machine_check_pSeries:
-       HMT_MEDIUM
-       DO_KVM  0x200
-       SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
+machine_check_pSeries_1:
+       /* This is moved out of line as it can be patched by FW, but
+        * some code path might still want to branch into the original
+        * vector
+        */
+       b       machine_check_pSeries
 
        . = 0x300
        .globl data_access_pSeries
 data_access_pSeries:
        HMT_MEDIUM
-       DO_KVM  0x300
        SET_SCRATCH0(r13)
+#ifndef CONFIG_POWER4_ONLY
 BEGIN_FTR_SECTION
-       GET_PACA(r13)
-       std     r9,PACA_EXSLB+EX_R9(r13)
-       std     r10,PACA_EXSLB+EX_R10(r13)
-       mfspr   r10,SPRN_DAR
-       mfspr   r9,SPRN_DSISR
-       srdi    r10,r10,60
-       rlwimi  r10,r9,16,0x20
-       mfcr    r9
-       cmpwi   r10,0x2c
-       beq     do_stab_bolted_pSeries
-       ld      r10,PACA_EXSLB+EX_R10(r13)
-       std     r11,PACA_EXGEN+EX_R11(r13)
-       ld      r11,PACA_EXSLB+EX_R9(r13)
-       std     r12,PACA_EXGEN+EX_R12(r13)
-       GET_SCRATCH0(r12)
-       std     r10,PACA_EXGEN+EX_R10(r13)
-       std     r11,PACA_EXGEN+EX_R9(r13)
-       std     r12,PACA_EXGEN+EX_R13(r13)
-       EXCEPTION_PROLOG_PSERIES_1(data_access_common, EXC_STD)
-FTR_SECTION_ELSE
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD)
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
+       b       data_access_check_stab
+data_access_not_stab:
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
+#endif
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
+                                KVMTEST, 0x300)
 
        . = 0x380
        .globl data_access_slb_pSeries
 data_access_slb_pSeries:
        HMT_MEDIUM
-       DO_KVM  0x380
        SET_SCRATCH0(r13)
-       GET_PACA(r13)
+       EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380)
        std     r3,PACA_EXSLB+EX_R3(r13)
        mfspr   r3,SPRN_DAR
-       std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
-       mfcr    r9
 #ifdef __DISABLED__
        /* Keep that around for when we re-implement dynamic VSIDs */
        cmpdi   r3,0
        bge     slb_miss_user_pseries
 #endif /* __DISABLED__ */
-       std     r10,PACA_EXSLB+EX_R10(r13)
-       std     r11,PACA_EXSLB+EX_R11(r13)
-       std     r12,PACA_EXSLB+EX_R12(r13)
-       GET_SCRATCH0(r10)
-       std     r10,PACA_EXSLB+EX_R13(r13)
-       mfspr   r12,SPRN_SRR1           /* and SRR1 */
+       mfspr   r12,SPRN_SRR1
 #ifndef CONFIG_RELOCATABLE
        b       .slb_miss_realmode
 #else
@@ -147,24 +124,16 @@ data_access_slb_pSeries:
        .globl instruction_access_slb_pSeries
 instruction_access_slb_pSeries:
        HMT_MEDIUM
-       DO_KVM  0x480
        SET_SCRATCH0(r13)
-       GET_PACA(r13)
+       EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x480)
        std     r3,PACA_EXSLB+EX_R3(r13)
        mfspr   r3,SPRN_SRR0            /* SRR0 is faulting address */
-       std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
-       mfcr    r9
 #ifdef __DISABLED__
        /* Keep that around for when we re-implement dynamic VSIDs */
        cmpdi   r3,0
        bge     slb_miss_user_pseries
 #endif /* __DISABLED__ */
-       std     r10,PACA_EXSLB+EX_R10(r13)
-       std     r11,PACA_EXSLB+EX_R11(r13)
-       std     r12,PACA_EXSLB+EX_R12(r13)
-       GET_SCRATCH0(r10)
-       std     r10,PACA_EXSLB+EX_R13(r13)
-       mfspr   r12,SPRN_SRR1           /* and SRR1 */
+       mfspr   r12,SPRN_SRR1
 #ifndef CONFIG_RELOCATABLE
        b       .slb_miss_realmode
 #else
@@ -184,26 +153,46 @@ instruction_access_slb_pSeries:
 hardware_interrupt_pSeries:
 hardware_interrupt_hv:
        BEGIN_FTR_SECTION
-               _MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD)
+               _MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt,
+                                           EXC_STD, SOFTEN_TEST)
+               KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x500)
        FTR_SECTION_ELSE
-               _MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV)
+               _MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt,
+                                           EXC_HV, SOFTEN_TEST_HV)
+               KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x502)
        ALT_FTR_SECTION_END_IFCLR(CPU_FTR_HVMODE_206)
 
        STD_EXCEPTION_PSERIES(0x600, 0x600, alignment)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x600)
+
        STD_EXCEPTION_PSERIES(0x700, 0x700, program_check)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x700)
+
        STD_EXCEPTION_PSERIES(0x800, 0x800, fp_unavailable)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x800)
 
        MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer)
-       MASKABLE_EXCEPTION_HV(0x980, 0x980, decrementer)
+       MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer)
 
        STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xa00)
+
        STD_EXCEPTION_PSERIES(0xb00, 0xb00, trap_0b)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xb00)
 
        . = 0xc00
        .globl  system_call_pSeries
 system_call_pSeries:
        HMT_MEDIUM
-       DO_KVM  0xc00
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+       SET_SCRATCH0(r13)
+       GET_PACA(r13)
+       std     r9,PACA_EXGEN+EX_R9(r13)
+       std     r10,PACA_EXGEN+EX_R10(r13)
+       mfcr    r9
+       KVMTEST(0xc00)
+       GET_SCRATCH0(r13)
+#endif
 BEGIN_FTR_SECTION
        cmpdi   r0,0x1ebe
        beq-    1f
@@ -220,6 +209,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
        rfid
        b       .       /* prevent speculative execution */
 
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xc00)
+
 /* Fast LE/BE switch system call */
 1:     mfspr   r12,SPRN_SRR1
        xori    r12,r12,MSR_LE
@@ -228,6 +219,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
        b       .
 
        STD_EXCEPTION_PSERIES(0xd00, 0xd00, single_step)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xd00)
 
        /* At 0xe??? we have a bunch of hypervisor exceptions, we branch
         * out of line to handle them
@@ -262,30 +254,93 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
 #endif /* CONFIG_CBE_RAS */
+
        STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
+
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
 #endif /* CONFIG_CBE_RAS */
+
        STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x1700)
+
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
 #endif /* CONFIG_CBE_RAS */
 
        . = 0x3000
 
 /*** Out of line interrupts support ***/
 
+       /* moved from 0x200 */
+machine_check_pSeries:
+       .globl machine_check_fwnmi
+machine_check_fwnmi:
+       HMT_MEDIUM
+       SET_SCRATCH0(r13)               /* save r13 */
+       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common,
+                                EXC_STD, KVMTEST, 0x200)
+       KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
+
+#ifndef CONFIG_POWER4_ONLY
+       /* moved from 0x300 */
+data_access_check_stab:
+       GET_PACA(r13)
+       std     r9,PACA_EXSLB+EX_R9(r13)
+       std     r10,PACA_EXSLB+EX_R10(r13)
+       mfspr   r10,SPRN_DAR
+       mfspr   r9,SPRN_DSISR
+       srdi    r10,r10,60
+       rlwimi  r10,r9,16,0x20
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+       lbz     r9,PACA_KVM_SVCPU+SVCPU_IN_GUEST(r13)
+       rlwimi  r10,r9,8,0x300
+#endif
+       mfcr    r9
+       cmpwi   r10,0x2c
+       beq     do_stab_bolted_pSeries
+       mtcrf   0x80,r9
+       ld      r9,PACA_EXSLB+EX_R9(r13)
+       ld      r10,PACA_EXSLB+EX_R10(r13)
+       b       data_access_not_stab
+do_stab_bolted_pSeries:
+       std     r11,PACA_EXSLB+EX_R11(r13)
+       std     r12,PACA_EXSLB+EX_R12(r13)
+       GET_SCRATCH0(r10)
+       std     r10,PACA_EXSLB+EX_R13(r13)
+       EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
+#endif /* CONFIG_POWER4_ONLY */
+
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
+       KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x400)
+       KVM_HANDLER(PACA_EXSLB, EXC_STD, 0x480)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x900)
+       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
+
+       .align  7
        /* moved from 0xe00 */
-       STD_EXCEPTION_HV(., 0xe00, h_data_storage)
-       STD_EXCEPTION_HV(., 0xe20, h_instr_storage)
-       STD_EXCEPTION_HV(., 0xe40, emulation_assist)
-       STD_EXCEPTION_HV(., 0xe60, hmi_exception) /* need to flush cache ? */
+       STD_EXCEPTION_HV(., 0xe02, h_data_storage)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02)
+       STD_EXCEPTION_HV(., 0xe22, h_instr_storage)
+       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22)
+       STD_EXCEPTION_HV(., 0xe42, emulation_assist)
+       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42)
+       STD_EXCEPTION_HV(., 0xe62, hmi_exception) /* need to flush cache ? */
+       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62)
 
        /* moved from 0xf00 */
        STD_EXCEPTION_PSERIES(., 0xf00, performance_monitor)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xf00)
        STD_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xf20)
        STD_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable)
+       KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xf40)
 
 /*
  * An interrupt came in while soft-disabled; clear EE in SRR1,
@@ -317,14 +372,6 @@ masked_Hinterrupt:
        hrfid
        b       .
 
-       .align  7
-do_stab_bolted_pSeries:
-       std     r11,PACA_EXSLB+EX_R11(r13)
-       std     r12,PACA_EXSLB+EX_R12(r13)
-       GET_SCRATCH0(r10)
-       std     r10,PACA_EXSLB+EX_R13(r13)
-       EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
-
 #ifdef CONFIG_PPC_PSERIES
 /*
  * Vectors for the FWNMI option.  Share common code.
@@ -334,14 +381,8 @@ do_stab_bolted_pSeries:
 system_reset_fwnmi:
        HMT_MEDIUM
        SET_SCRATCH0(r13)               /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
-
-       .globl machine_check_fwnmi
-      .align 7
-machine_check_fwnmi:
-       HMT_MEDIUM
-       SET_SCRATCH0(r13)               /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+                                NOTEST, 0x100)
 
 #endif /* CONFIG_PPC_PSERIES */
 
index 5f5d07475c9154c36cf7d3b124e6ddf839e635fb..dd03689fc609a750c798004106c4055251f5d75d 100644 (file)
 #define MSR_NOIRQ              MSR_KERNEL & ~(MSR_IR | MSR_DR)
 #define FUNC(name)             GLUE(.,name)
 
-#elif defined(CONFIG_PPC_BOOK3S_32)
+kvmppc_skip_interrupt:
+       /*
+        * Here all GPRs are unchanged from when the interrupt happened
+        * except for r13, which is saved in SPRG_SCRATCH0.
+        */
+       mfspr   r13, SPRN_SRR0
+       addi    r13, r13, 4
+       mtspr   SPRN_SRR0, r13
+       GET_SCRATCH0(r13)
+       rfid
+       b       .
+
+kvmppc_skip_Hinterrupt:
+       /*
+        * Here all GPRs are unchanged from when the interrupt happened
+        * except for r13, which is saved in SPRG_SCRATCH0.
+        */
+       mfspr   r13, SPRN_HSRR0
+       addi    r13, r13, 4
+       mtspr   SPRN_HSRR0, r13
+       GET_SCRATCH0(r13)
+       hrfid
+       b       .
 
-#define LOAD_SHADOW_VCPU(reg)                                          \
-       mfspr   reg, SPRN_SPRG_THREAD;                                  \
-       lwz     reg, THREAD_KVM_SVCPU(reg);                             \
-       /* PPC32 can have a NULL pointer - let's check for that */      \
-       mtspr   SPRN_SPRG_SCRATCH1, r12;        /* Save r12 */          \
-       mfcr    r12;                                                    \
-       cmpwi   reg, 0;                                                 \
-       bne     1f;                                                     \
-       mfspr   reg, SPRN_SPRG_SCRATCH0;                                \
-       mtcr    r12;                                                    \
-       mfspr   r12, SPRN_SPRG_SCRATCH1;                                \
-       b       kvmppc_resume_\intno;                                   \
-1:;                                                                    \
-       mtcr    r12;                                                    \
-       mfspr   r12, SPRN_SPRG_SCRATCH1;                                \
-       tophys(reg, reg)
+#elif defined(CONFIG_PPC_BOOK3S_32)
 
 #define SHADOW_VCPU_OFF                0
 #define MSR_NOIRQ              MSR_KERNEL
 #define FUNC(name)             name
 
-#endif
-
 .macro INTERRUPT_TRAMPOLINE intno
 
 .global kvmppc_trampoline_\intno
 kvmppc_trampoline_\intno:
 
-       SET_SCRATCH0(r13)               /* Save r13 */
+       mtspr   SPRN_SPRG_SCRATCH0, r13         /* Save r13 */
 
        /*
         * First thing to do is to find out if we're coming
@@ -78,19 +83,28 @@ kvmppc_trampoline_\intno:
         *
         * To distinguish, we check a magic byte in the PACA/current
         */
-       LOAD_SHADOW_VCPU(r13)
-       PPC_STL r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
+       mfspr   r13, SPRN_SPRG_THREAD
+       lwz     r13, THREAD_KVM_SVCPU(r13)
+       /* PPC32 can have a NULL pointer - let's check for that */
+       mtspr   SPRN_SPRG_SCRATCH1, r12         /* Save r12 */
        mfcr    r12
+       cmpwi   r13, 0
+       bne     1f
+2:     mtcr    r12
+       mfspr   r12, SPRN_SPRG_SCRATCH1
+       mfspr   r13, SPRN_SPRG_SCRATCH0         /* r13 = original r13 */
+       b       kvmppc_resume_\intno            /* Get back original handler */
+
+1:     tophys(r13, r13)
        stw     r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
+       mfspr   r12, SPRN_SPRG_SCRATCH1
+       stw     r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
        lbz     r12, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
        cmpwi   r12, KVM_GUEST_MODE_NONE
        bne     ..kvmppc_handler_hasmagic_\intno
        /* No KVM guest? Then jump back to the Linux handler! */
        lwz     r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
-       mtcr    r12
-       PPC_LL  r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
-       GET_SCRATCH0(r13)                       /* r13 = original r13 */
-       b       kvmppc_resume_\intno            /* Get back original handler */
+       b       2b
 
        /* Now we know we're handling a KVM guest */
 ..kvmppc_handler_hasmagic_\intno:
@@ -112,9 +126,6 @@ INTERRUPT_TRAMPOLINE        BOOK3S_INTERRUPT_MACHINE_CHECK
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_DATA_STORAGE
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_INST_STORAGE
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_EXTERNAL
-#ifdef CONFIG_PPC_BOOK3S_64
-INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_EXTERNAL_HV
-#endif
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_ALIGNMENT
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_PROGRAM
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_FP_UNAVAIL
@@ -124,14 +135,6 @@ INTERRUPT_TRAMPOLINE       BOOK3S_INTERRUPT_TRACE
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_PERFMON
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_ALTIVEC
 
-/* Those are only available on 64 bit machines */
-
-#ifdef CONFIG_PPC_BOOK3S_64
-INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_DATA_SEGMENT
-INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_INST_SEGMENT
-INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_VSX
-#endif
-
 /*
  * Bring us back to the faulting code, but skip the
  * faulting instruction.
@@ -163,6 +166,7 @@ kvmppc_handler_skip_ins:
 
        /* And get back into the code */
        RFI
+#endif
 
 /*
  * This trampoline brings us back to a real mode handler
index 451264274b8c1f7fec7b668e49dff04c0b02e735..4a623eb28a5324768762f9f97c6c74ea6e26d9e1 100644 (file)
@@ -125,6 +125,9 @@ kvmppc_handler_trampoline_enter_end:
 .global kvmppc_handler_trampoline_exit
 kvmppc_handler_trampoline_exit:
 
+.global kvmppc_interrupt
+kvmppc_interrupt:
+
        /* Register usage at this point:
         *
         * SPRG_SCRATCH0  = guest R13
@@ -155,12 +158,16 @@ kvmppc_handler_trampoline_exit:
        PPC_LL  r2, (SHADOW_VCPU_OFF + SVCPU_HOST_R2)(r13)
 
        /* Save guest PC and MSR */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
        andi.   r0,r12,0x2
        beq     1f
        mfspr   r3,SPRN_HSRR0
        mfspr   r4,SPRN_HSRR1
        andi.   r12,r12,0x3ffd
        b       2f
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206)
+#endif
 1:     mfsrr0  r3
        mfsrr1  r4
 2:
index 29c02f36b32f95c95ce2d12f193ce2f52fc63e9b..f519ee17ff7dd6f8d1c7509e6b400172cd79956f 100644 (file)
@@ -167,7 +167,7 @@ BEGIN_FTR_SECTION
        std     r12,PACA_EXGEN+EX_R13(r13)
        EXCEPTION_PROLOG_ISERIES_1
 FTR_SECTION_ELSE
-       EXCEPTION_PROLOG_1(PACA_EXGEN)
+       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0)
        EXCEPTION_PROLOG_ISERIES_1
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
        b       data_access_common
index bae3fba5ad8efdedd24bd7613ad45fe3cd47fc36..50271b550a998e5f1f447754a8b578faf837f7ec 100644 (file)
@@ -39,7 +39,7 @@
 label##_iSeries:                                                       \
        HMT_MEDIUM;                                                     \
        mtspr   SPRN_SPRG_SCRATCH0,r13; /* save r13 */                  \
-       EXCEPTION_PROLOG_1(area);                                       \
+       EXCEPTION_PROLOG_1(area, NOTEST, 0);                            \
        EXCEPTION_PROLOG_ISERIES_1;                                     \
        b       label##_common
 
@@ -48,7 +48,7 @@ label##_iSeries:                                                      \
 label##_iSeries:                                                       \
        HMT_MEDIUM;                                                     \
        mtspr   SPRN_SPRG_SCRATCH0,r13; /* save r13 */                  \
-       EXCEPTION_PROLOG_1(PACA_EXGEN);                                 \
+       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0);                      \
        lbz     r10,PACASOFTIRQEN(r13);                                 \
        cmpwi   0,r10,0;                                                \
        beq-    label##_iSeries_masked;                                 \