DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
        DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
        DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
+       DEFINE(VCPU_CRIT_SAVE, offsetof(struct kvm_vcpu, arch.crit_save));
 #endif /* CONFIG_PPC_BOOK3S */
 #endif /* CONFIG_KVM */
 
 
                        (1<<BOOKE_INTERRUPT_DTLB_MISS) | \
                        (1<<BOOKE_INTERRUPT_ALIGNMENT))
 
-.macro KVM_HANDLER ivor_nr scratch srr0
-_GLOBAL(kvmppc_handler_\ivor_nr)
+.macro __KVM_HANDLER ivor_nr scratch srr0
        /* Get pointer to vcpu and record exit number. */
        mtspr   \scratch , r4
        mfspr   r4, SPRN_SPRG_THREAD
        bctr
 .endm
 
+.macro KVM_HANDLER ivor_nr scratch srr0
+_GLOBAL(kvmppc_handler_\ivor_nr)
+       __KVM_HANDLER \ivor_nr \scratch \srr0
+.endm
+
+.macro KVM_DBG_HANDLER ivor_nr scratch srr0
+_GLOBAL(kvmppc_handler_\ivor_nr)
+       mtspr   \scratch, r4
+       mfspr   r4, SPRN_SPRG_THREAD
+       lwz     r4, THREAD_KVM_VCPU(r4)
+       stw     r3, VCPU_CRIT_SAVE(r4)
+       mfcr    r3
+       mfspr   r4, SPRN_CSRR1
+       andi.   r4, r4, MSR_PR
+       bne     1f
+       /* debug interrupt happened in enter/exit path */
+       mfspr   r4, SPRN_CSRR1
+       rlwinm  r4, r4, 0, ~MSR_DE
+       mtspr   SPRN_CSRR1, r4
+       lis     r4, 0xffff
+       ori     r4, r4, 0xffff
+       mtspr   SPRN_DBSR, r4
+       mfspr   r4, SPRN_SPRG_THREAD
+       lwz     r4, THREAD_KVM_VCPU(r4)
+       mtcr    r3
+       lwz     r3, VCPU_CRIT_SAVE(r4)
+       mfspr   r4, \scratch
+       rfci
+1:     /* debug interrupt happened in guest */
+       mtcr    r3
+       mfspr   r4, SPRN_SPRG_THREAD
+       lwz     r4, THREAD_KVM_VCPU(r4)
+       lwz     r3, VCPU_CRIT_SAVE(r4)
+       mfspr   r4, \scratch
+       __KVM_HANDLER \ivor_nr \scratch \srr0
+.endm
+
 .macro KVM_HANDLER_ADDR ivor_nr
        .long   kvmppc_handler_\ivor_nr
 .endm
 KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
 KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS SPRN_SPRG_RSCRATCH0 SPRN_SRR0
-KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
+KVM_DBG_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0