]> Pileus Git - ~andy/linux/blobdiff - arch/powerpc/kernel/head_booke.h
KVM: PPC: booke: category E.HV (GS-mode) support
[~andy/linux] / arch / powerpc / kernel / head_booke.h
index 0e4175388f478af5456d7095a860a2d621e3ad3c..5f051eeb93a278cb33c823c722582fb4652566f5 100644 (file)
@@ -2,6 +2,9 @@
 #define __HEAD_BOOKE_H__
 
 #include <asm/ptrace.h>        /* for STACK_FRAME_REGS_MARKER */
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
+
 /*
  * Macros used for common Book-e exception handling
  */
  */
 #define THREAD_NORMSAVE(offset)        (THREAD_NORMSAVES + (offset * 4))
 
-#define NORMAL_EXCEPTION_PROLOG                                                     \
+#define NORMAL_EXCEPTION_PROLOG(intno)                                              \
        mtspr   SPRN_SPRG_WSCRATCH0, r10;       /* save one register */      \
        mfspr   r10, SPRN_SPRG_THREAD;                                       \
        stw     r11, THREAD_NORMSAVE(0)(r10);                                \
        stw     r13, THREAD_NORMSAVE(2)(r10);                                \
        mfcr    r13;                    /* save CR in r13 for now          */\
-       mfspr   r11,SPRN_SRR1;          /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
+       mfspr   r11, SPRN_SRR1;                                              \
+       DO_KVM  BOOKE_INTERRUPT_##intno SPRN_SRR1;                           \
+       andi.   r11, r11, MSR_PR;       /* check whether user or kernel    */\
        mr      r11, r1;                                                     \
        beq     1f;                                                          \
        /* if from user, start at top of this thread's kernel stack */       \
  * registers as the normal prolog above. Instead we use a portion of the
  * critical/machine check exception stack at low physical addresses.
  */
-#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
+#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, intno, exc_level_srr0, exc_level_srr1) \
        mtspr   SPRN_SPRG_WSCRATCH_##exc_level,r8;                           \
        BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
        stw     r9,GPR9(r8);            /* save various registers          */\
        stw     r10,GPR10(r8);                                               \
        stw     r11,GPR11(r8);                                               \
        stw     r9,_CCR(r8);            /* save CR on stack                */\
-       mfspr   r10,exc_level_srr1;     /* check whether user or kernel    */\
-       andi.   r10,r10,MSR_PR;                                              \
+       mfspr   r11,exc_level_srr1;     /* check whether user or kernel    */\
+       DO_KVM  BOOKE_INTERRUPT_##intno exc_level_srr1;                      \
+       andi.   r11,r11,MSR_PR;                                              \
        mfspr   r11,SPRN_SPRG_THREAD;   /* if from user, start at top of   */\
        lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
        addi    r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame    */\
        SAVE_4GPRS(3, r11);                                                  \
        SAVE_2GPRS(7, r11)
 
-#define CRITICAL_EXCEPTION_PROLOG \
-               EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
+#define CRITICAL_EXCEPTION_PROLOG(intno) \
+               EXC_LEVEL_EXCEPTION_PROLOG(CRIT, intno, SPRN_CSRR0, SPRN_CSRR1)
 #define DEBUG_EXCEPTION_PROLOG \
-               EXC_LEVEL_EXCEPTION_PROLOG(DBG, SPRN_DSRR0, SPRN_DSRR1)
+               EXC_LEVEL_EXCEPTION_PROLOG(DBG, DEBUG, SPRN_DSRR0, SPRN_DSRR1)
 #define MCHECK_EXCEPTION_PROLOG \
-               EXC_LEVEL_EXCEPTION_PROLOG(MC, SPRN_MCSRR0, SPRN_MCSRR1)
+               EXC_LEVEL_EXCEPTION_PROLOG(MC, MACHINE_CHECK, \
+                       SPRN_MCSRR0, SPRN_MCSRR1)
+
+/*
+ * Guest Doorbell -- this is a bit odd in that uses GSRR0/1 despite
+ * being delivered to the host.  This exception can only happen
+ * inside a KVM guest -- so we just handle up to the DO_KVM rather
+ * than try to fit this into one of the existing prolog macros.
+ */
+#define GUEST_DOORBELL_EXCEPTION \
+       START_EXCEPTION(GuestDoorbell);                                      \
+       mtspr   SPRN_SPRG_WSCRATCH0, r10;       /* save one register */      \
+       mfspr   r10, SPRN_SPRG_THREAD;                                       \
+       stw     r11, THREAD_NORMSAVE(0)(r10);                                \
+       mfspr   r11, SPRN_SRR1;                                              \
+       stw     r13, THREAD_NORMSAVE(2)(r10);                                \
+       mfcr    r13;                    /* save CR in r13 for now          */\
+       DO_KVM  BOOKE_INTERRUPT_GUEST_DBELL SPRN_GSRR1;                      \
+       trap
 
 /*
  * Exception vectors.
@@ -181,16 +204,16 @@ label:
        .long   func;                                           \
        .long   ret_from_except_full
 
-#define EXCEPTION(n, label, hdlr, xfer)                                \
+#define EXCEPTION(n, intno, label, hdlr, xfer)                 \
        START_EXCEPTION(label);                                 \
-       NORMAL_EXCEPTION_PROLOG;                                \
+       NORMAL_EXCEPTION_PROLOG(intno);                         \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
        xfer(n, hdlr)
 
-#define CRITICAL_EXCEPTION(n, label, hdlr)                     \
-       START_EXCEPTION(label);                                 \
-       CRITICAL_EXCEPTION_PROLOG;                              \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+#define CRITICAL_EXCEPTION(n, intno, label, hdlr)                      \
+       START_EXCEPTION(label);                                         \
+       CRITICAL_EXCEPTION_PROLOG(intno);                               \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                             \
        EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
                          NOCOPY, crit_transfer_to_handler, \
                          ret_from_crit_exc)
@@ -302,7 +325,7 @@ label:
 
 #define DEBUG_CRIT_EXCEPTION                                                 \
        START_EXCEPTION(DebugCrit);                                           \
-       CRITICAL_EXCEPTION_PROLOG;                                            \
+       CRITICAL_EXCEPTION_PROLOG(DEBUG);                                     \
                                                                              \
        /*                                                                    \
         * If there is a single step or branch-taken exception in an          \
@@ -355,7 +378,7 @@ label:
 
 #define DATA_STORAGE_EXCEPTION                                               \
        START_EXCEPTION(DataStorage)                                          \
-       NORMAL_EXCEPTION_PROLOG;                                              \
+       NORMAL_EXCEPTION_PROLOG(DATA_STORAGE);                \
        mfspr   r5,SPRN_ESR;            /* Grab the ESR and save it */        \
        stw     r5,_ESR(r11);                                                 \
        mfspr   r4,SPRN_DEAR;           /* Grab the DEAR */                   \
@@ -363,7 +386,7 @@ label:
 
 #define INSTRUCTION_STORAGE_EXCEPTION                                        \
        START_EXCEPTION(InstructionStorage)                                   \
-       NORMAL_EXCEPTION_PROLOG;                                              \
+       NORMAL_EXCEPTION_PROLOG(INST_STORAGE);                \
        mfspr   r5,SPRN_ESR;            /* Grab the ESR and save it */        \
        stw     r5,_ESR(r11);                                                 \
        mr      r4,r12;                 /* Pass SRR0 as arg2 */               \
@@ -372,7 +395,7 @@ label:
 
 #define ALIGNMENT_EXCEPTION                                                  \
        START_EXCEPTION(Alignment)                                            \
-       NORMAL_EXCEPTION_PROLOG;                                              \
+       NORMAL_EXCEPTION_PROLOG(ALIGNMENT);                   \
        mfspr   r4,SPRN_DEAR;           /* Grab the DEAR and save it */       \
        stw     r4,_DEAR(r11);                                                \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
@@ -380,7 +403,7 @@ label:
 
 #define PROGRAM_EXCEPTION                                                    \
        START_EXCEPTION(Program)                                              \
-       NORMAL_EXCEPTION_PROLOG;                                              \
+       NORMAL_EXCEPTION_PROLOG(PROGRAM);                     \
        mfspr   r4,SPRN_ESR;            /* Grab the ESR and save it */        \
        stw     r4,_ESR(r11);                                                 \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
@@ -388,7 +411,7 @@ label:
 
 #define DECREMENTER_EXCEPTION                                                \
        START_EXCEPTION(Decrementer)                                          \
-       NORMAL_EXCEPTION_PROLOG;                                              \
+       NORMAL_EXCEPTION_PROLOG(DECREMENTER);                 \
        lis     r0,TSR_DIS@h;           /* Setup the DEC interrupt mask */    \
        mtspr   SPRN_TSR,r0;            /* Clear the DEC interrupt */         \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
@@ -396,7 +419,7 @@ label:
 
 #define FP_UNAVAILABLE_EXCEPTION                                             \
        START_EXCEPTION(FloatingPointUnavailable)                             \
-       NORMAL_EXCEPTION_PROLOG;                                              \
+       NORMAL_EXCEPTION_PROLOG(FP_UNAVAIL);                  \
        beq     1f;                                                           \
        bl      load_up_fpu;            /* if from user, just load it up */   \
        b       fast_exception_return;                                        \