powerpc/booke64: Use SPRG0/3 scratch for bolted TLB miss & crit int
[firefly-linux-kernel-4.4.55.git] / arch / powerpc / kernel / exceptions-64e.S
index 98be7f0cd227019cbe6b6a07ad989327b8e36979..7476b0ae09fbb9816afc42b09e2ed1cb17ea39a9 100644 (file)
@@ -25,6 +25,8 @@
 #include <asm/ppc-opcode.h>
 #include <asm/mmu.h>
 #include <asm/hw_irq.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
 
 /* XXX This will ultimately add space for a special exception save
  *     structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
 #define        SPECIAL_EXC_FRAME_SIZE  INT_FRAME_SIZE
 
 /* Exception prolog code for all exceptions */
-#define EXCEPTION_PROLOG(n, type, addition)                                \
+#define EXCEPTION_PROLOG(n, intnum, type, addition)                        \
        mtspr   SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */   \
        mfspr   r13,SPRN_SPRG_PACA;     /* get PACA */                      \
        std     r10,PACA_EX##type+EX_R10(r13);                              \
        std     r11,PACA_EX##type+EX_R11(r13);                              \
+       PROLOG_STORE_RESTORE_SCRATCH_##type;                                \
        mfcr    r10;                    /* save CR */                       \
+       mfspr   r11,SPRN_##type##_SRR1;/* what are we coming from */        \
+       DO_KVM  intnum,SPRN_##type##_SRR1;    /* KVM hook */                \
+       stw     r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
        addition;                       /* additional code for that exc. */ \
        std     r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */  \
-       stw     r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
-       mfspr   r11,SPRN_##type##_SRR1;/* what are we coming from */        \
        type##_SET_KSTACK;              /* get special stack if necessary */\
        andi.   r10,r11,MSR_PR;         /* save stack pointer */            \
        beq     1f;                     /* branch around if supervisor */   \
 #define SPRN_GEN_SRR0  SPRN_SRR0
 #define SPRN_GEN_SRR1  SPRN_SRR1
 
+#define        GDBELL_SET_KSTACK       GEN_SET_KSTACK
+#define SPRN_GDBELL_SRR0       SPRN_GSRR0
+#define SPRN_GDBELL_SRR1       SPRN_GSRR1
+
 #define CRIT_SET_KSTACK                                                            \
        ld      r1,PACA_CRIT_STACK(r13);                                    \
        subi    r1,r1,SPECIAL_EXC_FRAME_SIZE;
 #define SPRN_MC_SRR0   SPRN_MCSRR0
 #define SPRN_MC_SRR1   SPRN_MCSRR1
 
-#define NORMAL_EXCEPTION_PROLOG(n, addition)                               \
-       EXCEPTION_PROLOG(n, GEN, addition##_GEN(n))
+#define NORMAL_EXCEPTION_PROLOG(n, intnum, addition)                       \
+       EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n))
 
-#define CRIT_EXCEPTION_PROLOG(n, addition)                                 \
-       EXCEPTION_PROLOG(n, CRIT, addition##_CRIT(n))
+#define CRIT_EXCEPTION_PROLOG(n, intnum, addition)                         \
+       EXCEPTION_PROLOG(n, intnum, CRIT, addition##_CRIT(n))
 
-#define DBG_EXCEPTION_PROLOG(n, addition)                                  \
-       EXCEPTION_PROLOG(n, DBG, addition##_DBG(n))
+#define DBG_EXCEPTION_PROLOG(n, intnum, addition)                          \
+       EXCEPTION_PROLOG(n, intnum, DBG, addition##_DBG(n))
 
-#define MC_EXCEPTION_PROLOG(n, addition)                                   \
-       EXCEPTION_PROLOG(n, MC, addition##_MC(n))
+#define MC_EXCEPTION_PROLOG(n, intnum, addition)                           \
+       EXCEPTION_PROLOG(n, intnum, MC, addition##_MC(n))
 
+#define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)                       \
+       EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
+
+/*
+ * Store user-visible scratch in PACA exception slots and restore proper value
+ */
+#define PROLOG_STORE_RESTORE_SCRATCH_GEN
+#define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
+#define PROLOG_STORE_RESTORE_SCRATCH_DBG
+#define PROLOG_STORE_RESTORE_SCRATCH_MC
+
+#define PROLOG_STORE_RESTORE_SCRATCH_CRIT                                  \
+       mfspr   r10,SPRN_SPRG_CRIT_SCRATCH;     /* get r13 */               \
+       std     r10,PACA_EXCRIT+EX_R13(r13)
 
 /* Variants of the "addition" argument for the prolog
  */
 #define PROLOG_ADDITION_NONE_GEN(n)
+#define PROLOG_ADDITION_NONE_GDBELL(n)
 #define PROLOG_ADDITION_NONE_CRIT(n)
 #define PROLOG_ADDITION_NONE_DBG(n)
 #define PROLOG_ADDITION_NONE_MC(n)
 
 #define PROLOG_ADDITION_MASKABLE_GEN(n)                                            \
-       lbz     r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
-       cmpwi   cr0,r11,0;              /* yes -> go out of line */         \
+       lbz     r10,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
+       cmpwi   cr0,r10,0;              /* yes -> go out of line */         \
        beq     masked_interrupt_book3e_##n
 
 #define PROLOG_ADDITION_2REGS_GEN(n)                                       \
@@ -233,9 +256,9 @@ exc_##n##_bad_stack:                                                            \
 1:
 
 
-#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack)                  \
+#define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)          \
        START_EXCEPTION(label);                                         \
-       NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE)      \
+       NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
        EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE)             \
        ack(r8);                                                        \
        CHECK_NAPPING();                                                \
@@ -286,7 +309,8 @@ interrupt_end_book3e:
 
 /* Critical Input Interrupt */
        START_EXCEPTION(critical_input);
-       CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -297,7 +321,8 @@ interrupt_end_book3e:
 
 /* Machine Check Interrupt */
        START_EXCEPTION(machine_check);
-       CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
+       MC_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_MACHINE_CHECK,
+                           PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
 //     bl      special_reg_save_mc
 //     addi    r3,r1,STACK_FRAME_OVERHEAD
@@ -308,7 +333,8 @@ interrupt_end_book3e:
 
 /* Data Storage Interrupt */
        START_EXCEPTION(data_storage)
-       NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS)
+       NORMAL_EXCEPTION_PROLOG(0x300, BOOKE_INTERRUPT_DATA_STORAGE,
+                               PROLOG_ADDITION_2REGS)
        mfspr   r14,SPRN_DEAR
        mfspr   r15,SPRN_ESR
        EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
@@ -316,18 +342,21 @@ interrupt_end_book3e:
 
 /* Instruction Storage Interrupt */
        START_EXCEPTION(instruction_storage);
-       NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS)
+       NORMAL_EXCEPTION_PROLOG(0x400, BOOKE_INTERRUPT_INST_STORAGE,
+                               PROLOG_ADDITION_2REGS)
        li      r15,0
        mr      r14,r10
        EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
        b       storage_fault_common
 
 /* External Input Interrupt */
-       MASKABLE_EXCEPTION(0x500, external_input, .do_IRQ, ACK_NONE)
+       MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
+                          external_input, .do_IRQ, ACK_NONE)
 
 /* Alignment */
        START_EXCEPTION(alignment);
-       NORMAL_EXCEPTION_PROLOG(0x600, PROLOG_ADDITION_2REGS)
+       NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
+                               PROLOG_ADDITION_2REGS)
        mfspr   r14,SPRN_DEAR
        mfspr   r15,SPRN_ESR
        EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP)
@@ -335,7 +364,8 @@ interrupt_end_book3e:
 
 /* Program Interrupt */
        START_EXCEPTION(program);
-       NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG)
+       NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
+                               PROLOG_ADDITION_1REG)
        mfspr   r14,SPRN_ESR
        EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
        std     r14,_DSISR(r1)
@@ -347,7 +377,8 @@ interrupt_end_book3e:
 
 /* Floating Point Unavailable Interrupt */
        START_EXCEPTION(fp_unavailable);
-       NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
+                               PROLOG_ADDITION_NONE)
        /* we can probably do a shorter exception entry for that one... */
        EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
        ld      r12,_MSR(r1)
@@ -362,14 +393,17 @@ interrupt_end_book3e:
        b       .ret_from_except
 
 /* Decrementer Interrupt */
-       MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC)
+       MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
+                          decrementer, .timer_interrupt, ACK_DEC)
 
 /* Fixed Interval Timer Interrupt */
-       MASKABLE_EXCEPTION(0x980, fixed_interval, .unknown_exception, ACK_FIT)
+       MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
+                          fixed_interval, .unknown_exception, ACK_FIT)
 
 /* Watchdog Timer Interrupt */
        START_EXCEPTION(watchdog);
-       CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -388,7 +422,8 @@ interrupt_end_book3e:
 
 /* Auxiliary Processor Unavailable Interrupt */
        START_EXCEPTION(ap_unavailable);
-       NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
        bl      .save_nvgprs
        addi    r3,r1,STACK_FRAME_OVERHEAD
@@ -397,7 +432,8 @@ interrupt_end_book3e:
 
 /* Debug exception as a critical interrupt*/
        START_EXCEPTION(debug_crit);
-       CRIT_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS)
+       CRIT_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+                             PROLOG_ADDITION_2REGS)
 
        /*
         * If there is a single step or branch-taken exception in an
@@ -431,7 +467,7 @@ interrupt_end_book3e:
        mtcr    r10
        ld      r10,PACA_EXCRIT+EX_R10(r13)     /* restore registers */
        ld      r11,PACA_EXCRIT+EX_R11(r13)
-       mfspr   r13,SPRN_SPRG_CRIT_SCRATCH
+       ld      r13,PACA_EXCRIT+EX_R13(r13)
        rfci
 
        /* Normal debug exception */
@@ -444,7 +480,7 @@ interrupt_end_book3e:
        /* Now we mash up things to make it look like we are coming on a
         * normal exception
         */
-       mfspr   r15,SPRN_SPRG_CRIT_SCRATCH
+       ld      r15,PACA_EXCRIT+EX_R13(r13)
        mtspr   SPRN_SPRG_GEN_SCRATCH,r15
        mfspr   r14,SPRN_DBSR
        EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
@@ -462,7 +498,8 @@ kernel_dbg_exc:
 
 /* Debug exception as a debug interrupt*/
        START_EXCEPTION(debug_debug);
-       DBG_EXCEPTION_PROLOG(0xd08, PROLOG_ADDITION_2REGS)
+       DBG_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+                                                PROLOG_ADDITION_2REGS)
 
        /*
         * If there is a single step or branch-taken exception in an
@@ -523,18 +560,21 @@ kernel_dbg_exc:
        b       .ret_from_except
 
        START_EXCEPTION(perfmon);
-       NORMAL_EXCEPTION_PROLOG(0x260, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .performance_monitor_exception
        b       .ret_from_except_lite
 
 /* Doorbell interrupt */
-       MASKABLE_EXCEPTION(0x280, doorbell, .doorbell_exception, ACK_NONE)
+       MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
+                          doorbell, .doorbell_exception, ACK_NONE)
 
 /* Doorbell critical Interrupt */
        START_EXCEPTION(doorbell_crit);
-       CRIT_EXCEPTION_PROLOG(0x2a0, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -543,12 +583,24 @@ kernel_dbg_exc:
 //     b       ret_from_crit_except
        b       .
 
-/* Guest Doorbell */
-       MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
+/*
+ *     Guest doorbell interrupt
+ *     This general exception use GSRRx save/restore registers
+ */
+       START_EXCEPTION(guest_doorbell);
+       GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
+                               PROLOG_ADDITION_NONE)
+       EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_KEEP)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .save_nvgprs
+       INTS_RESTORE_HARD
+       bl      .unknown_exception
+       b       .ret_from_except
 
 /* Guest Doorbell critical Interrupt */
        START_EXCEPTION(guest_doorbell_crit);
-       CRIT_EXCEPTION_PROLOG(0x2e0, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -559,7 +611,8 @@ kernel_dbg_exc:
 
 /* Hypervisor call */
        START_EXCEPTION(hypercall);
-       NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .save_nvgprs
@@ -569,7 +622,8 @@ kernel_dbg_exc:
 
 /* Embedded Hypervisor priviledged  */
        START_EXCEPTION(ehpriv);
-       NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .save_nvgprs
@@ -582,44 +636,42 @@ kernel_dbg_exc:
  * accordingly and if the interrupt is level sensitive, we hard disable
  */
 
+.macro masked_interrupt_book3e paca_irq full_mask
+       lbz     r10,PACAIRQHAPPENED(r13)
+       ori     r10,r10,\paca_irq
+       stb     r10,PACAIRQHAPPENED(r13)
+
+       .if \full_mask == 1
+       rldicl  r10,r11,48,1            /* clear MSR_EE */
+       rotldi  r11,r10,16
+       mtspr   SPRN_SRR1,r11
+       .endif
+
+       lwz     r11,PACA_EXGEN+EX_CR(r13)
+       mtcr    r11
+       ld      r10,PACA_EXGEN+EX_R10(r13)
+       ld      r11,PACA_EXGEN+EX_R11(r13)
+       mfspr   r13,SPRN_SPRG_GEN_SCRATCH
+       rfi
+       b       .
+.endm
+
 masked_interrupt_book3e_0x500:
-       /* XXX When adding support for EPR, use PACA_IRQ_EE_EDGE */
-       li      r11,PACA_IRQ_EE
-       b       masked_interrupt_book3e_full_mask
+       // XXX When adding support for EPR, use PACA_IRQ_EE_EDGE
+       masked_interrupt_book3e PACA_IRQ_EE 1
 
 masked_interrupt_book3e_0x900:
-       ACK_DEC(r11);
-       li      r11,PACA_IRQ_DEC
-       b       masked_interrupt_book3e_no_mask
+       ACK_DEC(r10);
+       masked_interrupt_book3e PACA_IRQ_DEC 0
+
 masked_interrupt_book3e_0x980:
-       ACK_FIT(r11);
-       li      r11,PACA_IRQ_DEC
-       b       masked_interrupt_book3e_no_mask
+       ACK_FIT(r10);
+       masked_interrupt_book3e PACA_IRQ_DEC 0
+
 masked_interrupt_book3e_0x280:
 masked_interrupt_book3e_0x2c0:
-       li      r11,PACA_IRQ_DBELL
-       b       masked_interrupt_book3e_no_mask
+       masked_interrupt_book3e PACA_IRQ_DBELL 0
 
-masked_interrupt_book3e_no_mask:
-       mtcr    r10
-       lbz     r10,PACAIRQHAPPENED(r13)
-       or      r10,r10,r11
-       stb     r10,PACAIRQHAPPENED(r13)
-       b       1f
-masked_interrupt_book3e_full_mask:
-       mtcr    r10
-       lbz     r10,PACAIRQHAPPENED(r13)
-       or      r10,r10,r11
-       stb     r10,PACAIRQHAPPENED(r13)
-       mfspr   r10,SPRN_SRR1
-       rldicl  r11,r10,48,1            /* clear MSR_EE */
-       rotldi  r10,r11,16
-       mtspr   SPRN_SRR1,r10
-1:     ld      r10,PACA_EXGEN+EX_R10(r13);
-       ld      r11,PACA_EXGEN+EX_R11(r13);
-       mfspr   r13,SPRN_SPRG_GEN_SCRATCH;
-       rfi
-       b       .
 /*
  * Called from arch_local_irq_enable when an interrupt needs
  * to be resent. r3 contains either 0x500,0x900,0x260 or 0x280