/* #define DEBUG_EXT */
 
 static void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
+static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
+                            ulong msr);
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "exits",       VCPU_STAT(sum_exits) },
        kvmppc_recalc_shadow_msr(vcpu);
 }
 
+static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
+{
+       ulong srr0 = vcpu->arch.pc;
+       int ret;
+
+       /* Need to do paired single emulation? */
+       if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
+               return EMULATE_DONE;
+
+       /* Read out the instruction */
+       ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &vcpu->arch.last_inst, false);
+       if (ret == -ENOENT) {
+               vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1);
+               vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0);
+               vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+               kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
+       } else if(ret == EMULATE_DONE) {
+               /* Need to emulate */
+               return EMULATE_FAIL;
+       }
+
+       return EMULATE_AGAIN;
+}
+
 /* Handle external providers (FPU, Altivec, VSX) */
 static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
                             ulong msr)
                enum emulation_result er;
                ulong flags;
 
+program_interrupt:
                flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
 
                if (vcpu->arch.msr & MSR_PR) {
                r = RESUME_GUEST;
                break;
        case BOOK3S_INTERRUPT_FP_UNAVAIL:
-               r = kvmppc_handle_ext(vcpu, exit_nr, MSR_FP);
-               break;
        case BOOK3S_INTERRUPT_ALTIVEC:
-               r = kvmppc_handle_ext(vcpu, exit_nr, MSR_VEC);
-               break;
        case BOOK3S_INTERRUPT_VSX:
-               r = kvmppc_handle_ext(vcpu, exit_nr, MSR_VSX);
+       {
+               int ext_msr = 0;
+
+               switch (exit_nr) {
+               case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP;  break;
+               case BOOK3S_INTERRUPT_ALTIVEC:    ext_msr = MSR_VEC; break;
+               case BOOK3S_INTERRUPT_VSX:        ext_msr = MSR_VSX; break;
+               }
+
+               switch (kvmppc_check_ext(vcpu, exit_nr)) {
+               case EMULATE_DONE:
+                       /* everything ok - let's enable the ext */
+                       r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
+                       break;
+               case EMULATE_FAIL:
+                       /* we need to emulate this instruction */
+                       goto program_interrupt;
+                       break;
+               default:
+                       /* nothing to worry about - go again */
+                       break;
+               }
                break;
+       }
        case BOOK3S_INTERRUPT_MACHINE_CHECK:
        case BOOK3S_INTERRUPT_TRACE:
                kvmppc_book3s_queue_irqprio(vcpu, exit_nr);