#define LOAD_HANDLER(reg, label)                                       \
        addi    reg,reg,(label)-_stext; /* virt addr of handler ... */
 
-#define EXCEPTION_PROLOG_1(area)                                       \
+/* Exception register prefixes */
+#define EXC_HV H
+#define EXC_STD
+
+#define __EXCEPTION_PROLOG_1(area, h)                                  \
        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);                                   \
-       mfspr   r9,SPRN_SPRG_SCRATCH0;                                  \
+       mfspr   r9,SPRN_SPRG_##h##SCRATCH0;                             \
        std     r9,area+EX_R13(r13);                                    \
        mfcr    r9
+#define EXCEPTION_PROLOG_1(area, h) __EXCEPTION_PROLOG_1(area, h)
 
-#define EXCEPTION_PROLOG_PSERIES_1(label)                              \
+#define __EXCEPTION_PROLOG_PSERIES_1(label, h)                         \
        ld      r12,PACAKBASE(r13);     /* get high part of &label */   \
        ld      r10,PACAKMSR(r13);      /* get MSR value for kernel */  \
-       mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
+       mfspr   r11,SPRN_##h##SRR0;     /* save SRR0 */                 \
        LOAD_HANDLER(r12,label)                                         \
-       mtspr   SPRN_SRR0,r12;                                          \
-       mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
-       mtspr   SPRN_SRR1,r10;                                          \
-       rfid;                                                           \
+       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(label, h) \
+       __EXCEPTION_PROLOG_PSERIES_1(label, h)
 
-#define EXCEPTION_PROLOG_PSERIES(area, label)                          \
-       EXCEPTION_PROLOG_1(area);                                       \
-       EXCEPTION_PROLOG_PSERIES_1(label);
+#define EXCEPTION_PROLOG_PSERIES(area, label, h)                       \
+       EXCEPTION_PROLOG_1(area, h);                                    \
+       EXCEPTION_PROLOG_PSERIES_1(label, h);
 
 /*
  * The common exception prolog is used for all except a few exceptions
        HMT_MEDIUM;                                     \
        DO_KVM  n;                                      \
        mtspr   SPRN_SPRG_SCRATCH0,r13;         /* save r13 */  \
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD)
 
 #define HSTD_EXCEPTION_PSERIES(n, label)               \
        . = n;                                          \
        .globl label##_pSeries;                         \
 label##_pSeries:                                       \
        HMT_MEDIUM;                                     \
-       mtspr   SPRN_SPRG_SCRATCH0,r20; /* save r20 */  \
-       mfspr   r20,SPRN_HSRR0;         /* copy HSRR0 to SRR0 */ \
-       mtspr   SPRN_SRR0,r20;                          \
-       mfspr   r20,SPRN_HSRR1;         /* copy HSRR0 to SRR0 */ \
-       mtspr   SPRN_SRR1,r20;                          \
-       mfspr   r20,SPRN_SPRG_SCRATCH0; /* restore r20 */ \
-       mtspr   SPRN_SPRG_SCRATCH0,r13;         /* save r13 */  \
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+       DO_KVM  n;                                      \
+       mtspr   SPRN_SPRG_HSCRATCH0,r13;/* save r13 */  \
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV)
 
 
-#define MASKABLE_EXCEPTION_PSERIES(n, label)                           \
-       . = n;                                                          \
-       .globl label##_pSeries;                                         \
-label##_pSeries:                                                       \
+#define __MASKABLE_EXCEPTION_PSERIES(n, label, h)                      \
        HMT_MEDIUM;                                                     \
        DO_KVM  n;                                                      \
-       mtspr   SPRN_SPRG_SCRATCH0,r13; /* save r13 */                  \
+       mtspr   SPRN_SPRG_##h##SCRATCH0,r13;    /* save r13 */          \
        GET_PACA(r13);                                                  \
        std     r9,PACA_EXGEN+EX_R9(r13);       /* save r9, r10 */      \
        std     r10,PACA_EXGEN+EX_R10(r13);                             \
        lbz     r10,PACASOFTIRQEN(r13);                                 \
        mfcr    r9;                                                     \
        cmpwi   r10,0;                                                  \
-       beq     masked_interrupt;                                       \
-       mfspr   r10,SPRN_SPRG_SCRATCH0;                                 \
+       beq     masked_##h##interrupt;                                  \
+       mfspr   r10,SPRN_SPRG_##h##SCRATCH0;                            \
        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_SRR0;          /* save SRR0 */                 \
+       mfspr   r11,SPRN_##h##SRR0;     /* save SRR0 */                 \
        LOAD_HANDLER(r12,label##_common)                                \
-       mtspr   SPRN_SRR0,r12;                                          \
-       mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
-       mtspr   SPRN_SRR1,r10;                                          \
-       rfid;                                                           \
+       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(n, label, h)                                \
+       __MASKABLE_EXCEPTION_PSERIES(n, label, h)
 
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS                           \
 
 #define BOOK3S_INTERRUPT_INST_SEGMENT  0x480
 #define BOOK3S_INTERRUPT_EXTERNAL      0x500
 #define BOOK3S_INTERRUPT_EXTERNAL_LEVEL        0x501
+#define BOOK3S_INTERRUPT_EXTERNAL_HV   0x502
 #define BOOK3S_INTERRUPT_ALIGNMENT     0x600
 #define BOOK3S_INTERRUPT_PROGRAM       0x700
 #define BOOK3S_INTERRUPT_FP_UNAVAIL    0x800
 
            (\intno == BOOK3S_INTERRUPT_DATA_SEGMENT) || \
            (\intno == BOOK3S_INTERRUPT_INST_SEGMENT) || \
            (\intno == BOOK3S_INTERRUPT_EXTERNAL) || \
+           (\intno == BOOK3S_INTERRUPT_EXTERNAL_HV) || \
            (\intno == BOOK3S_INTERRUPT_ALIGNMENT) || \
            (\intno == BOOK3S_INTERRUPT_PROGRAM) || \
            (\intno == BOOK3S_INTERRUPT_FP_UNAVAIL) || \
 
 __init_LPCR:
        /* Setup a sane LPCR:
         *
-        *   LPES = 0b11 (SRR0/1 used for 0x500)
+        *   LPES = 0b01 (HSRR0/1 used for 0x500)
         *   PECE = 0b111
         *
         * Other bits untouched for now
         */
        mfspr   r3,SPRN_LPCR
        ori     r3,r3,(LPCR_LPES0|LPCR_LPES1)
+       xori    r3,r3, LPCR_LPES0
        ori     r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
        mtspr   SPRN_LPCR,r3
        isync
 
        HMT_MEDIUM
        DO_KVM  0x200
        mtspr   SPRN_SPRG_SCRATCH0,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
 
        . = 0x300
        .globl data_access_pSeries
        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)
+       EXCEPTION_PROLOG_PSERIES_1(data_access_common, EXC_STD)
 FTR_SECTION_ELSE
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD)
 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB)
 
        . = 0x380
        bctr
 #endif
 
-       MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
+       . = 0x500;
+       .globl hardware_interrupt_pSeries
+hardware_interrupt_pSeries:
+       BEGIN_FTR_SECTION
+       MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD)
+       FTR_SECTION_ELSE
+       MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV)
+       ALT_FTR_SECTION_END_IFCLR(CPU_FTR_HVMODE_206)
+
        STD_EXCEPTION_PSERIES(0x600, alignment)
        STD_EXCEPTION_PSERIES(0x700, program_check)
        STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
-       MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
+
+       . = 0x900;
+       .globl decrementer_pSeries
+decrementer_pSeries:
+       MASKABLE_EXCEPTION_PSERIES(0x900, decrementer, EXC_STD)
+
        STD_EXCEPTION_PSERIES(0xa00, trap_0a)
        STD_EXCEPTION_PSERIES(0xb00, trap_0b)
 
        b       vsx_unavailable_pSeries
 
 #ifdef CONFIG_CBE_RAS
-       HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
+       HSTD_EXCEPTION_PSERIES(0x1202, cbe_system_error)
 #endif /* CONFIG_CBE_RAS */
        STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
 #ifdef CONFIG_CBE_RAS
-       HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
+       HSTD_EXCEPTION_PSERIES(0x1602, cbe_maintenance)
 #endif /* CONFIG_CBE_RAS */
        STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
 #ifdef CONFIG_CBE_RAS
-       HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
+       HSTD_EXCEPTION_PSERIES(0x1802, cbe_thermal)
 #endif /* CONFIG_CBE_RAS */
 
        . = 0x3000
        rfid
        b       .
 
+masked_Hinterrupt:
+       stb     r10,PACAHARDIRQEN(r13)
+       mtcrf   0x80,r9
+       ld      r9,PACA_EXGEN+EX_R9(r13)
+       mfspr   r10,SPRN_HSRR1
+       rldicl  r10,r10,48,1            /* clear MSR_EE */
+       rotldi  r10,r10,16
+       mtspr   SPRN_HSRR1,r10
+       ld      r10,PACA_EXGEN+EX_R10(r13)
+       mfspr   r13,SPRN_SPRG_HSCRATCH0
+       hrfid
+       b       .
+
        .align  7
 do_stab_bolted_pSeries:
        std     r11,PACA_EXSLB+EX_R11(r13)
        std     r12,PACA_EXSLB+EX_R12(r13)
        mfspr   r10,SPRN_SPRG_SCRATCH0
        std     r10,PACA_EXSLB+EX_R13(r13)
-       EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted)
+       EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
 
 #ifdef CONFIG_PPC_PSERIES
 /*
 system_reset_fwnmi:
        HMT_MEDIUM
        mtspr   SPRN_SPRG_SCRATCH0,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
 
        .globl machine_check_fwnmi
       .align 7
 machine_check_fwnmi:
        HMT_MEDIUM
        mtspr   SPRN_SPRG_SCRATCH0,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
 
 #endif /* CONFIG_PPC_PSERIES */
 
 
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_DATA_STORAGE
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_INST_STORAGE
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_EXTERNAL
+INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_EXTERNAL_HV
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_ALIGNMENT
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_PROGRAM
 INTERRUPT_TRAMPOLINE   BOOK3S_INTERRUPT_FP_UNAVAIL
 
        PPC_LL  r2, (SHADOW_VCPU_OFF + SVCPU_HOST_R2)(r13)
 
        /* Save guest PC and MSR */
-       mfsrr0  r3
+       andi.   r0,r12,0x2
+       beq     1f
+       mfspr   r3,SPRN_HSRR0
+       mfspr   r4,SPRN_HSRR1
+       andi.   r12,r12,0x3ffd
+       b       2f
+1:     mfsrr0  r3
        mfsrr1  r4
-
+2:
        PPC_STL r3, (SHADOW_VCPU_OFF + SVCPU_PC)(r13)
        PPC_STL r4, (SHADOW_VCPU_OFF + SVCPU_SHADOW_SRR1)(r13)
 
 
        std     r12,PACA_EXGEN+EX_R13(r13)
        EXCEPTION_PROLOG_ISERIES_1
 FTR_SECTION_ELSE
-       EXCEPTION_PROLOG_1(PACA_EXGEN)
+       EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_STD)
        EXCEPTION_PROLOG_ISERIES_1
 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB)
        b       data_access_common
 
 label##_iSeries:                                                       \
        HMT_MEDIUM;                                                     \
        mtspr   SPRN_SPRG_SCRATCH0,r13; /* save r13 */                  \
-       EXCEPTION_PROLOG_1(area);                                       \
+       EXCEPTION_PROLOG_1(area, EXC_STD);                              \
        EXCEPTION_PROLOG_ISERIES_1;                                     \
        b       label##_common
 
 label##_iSeries:                                                       \
        HMT_MEDIUM;                                                     \
        mtspr   SPRN_SPRG_SCRATCH0,r13; /* save r13 */                  \
-       EXCEPTION_PROLOG_1(PACA_EXGEN);                                 \
+       EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_STD);                        \
        lbz     r10,PACASOFTIRQEN(r13);                                 \
        cmpwi   0,r10,0;                                                \
        beq-    label##_iSeries_masked;                                 \