}
 
-static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
+                                          bool commit_side_effects)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
+       unsigned long old_rflags;
 
        /*
         * SEV-ES does not expose the next RIP. The RIP update is controlled by
        }
 
        if (!svm->next_rip) {
+               if (unlikely(!commit_side_effects))
+                       old_rflags = svm->vmcb->save.rflags;
+
                if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
                        return 0;
+
+               if (unlikely(!commit_side_effects))
+                       svm->vmcb->save.rflags = old_rflags;
        } else {
                kvm_rip_write(vcpu, svm->next_rip);
        }
 
 done:
-       svm_set_interrupt_shadow(vcpu, 0);
+       if (likely(commit_side_effects))
+               svm_set_interrupt_shadow(vcpu, 0);
 
        return 1;
 }
 
+static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       return __svm_skip_emulated_instruction(vcpu, true);
+}
+
+static int svm_update_soft_interrupt_rip(struct kvm_vcpu *vcpu)
+{
+       unsigned long rip, old_rip = kvm_rip_read(vcpu);
+       struct vcpu_svm *svm = to_svm(vcpu);
+
+       /*
+        * Due to architectural shortcomings, the CPU doesn't always provide
+        * NextRIP, e.g. if KVM intercepted an exception that occurred while
+        * the CPU was vectoring an INTO/INT3 in the guest.  Temporarily skip
+        * the instruction even if NextRIP is supported to acquire the next
+        * RIP so that it can be shoved into the NextRIP field, otherwise
+        * hardware will fail to advance guest RIP during event injection.
+        * Drop the exception/interrupt if emulation fails and effectively
+        * retry the instruction, it's the least awful option.  If NRIPS is
+        * in use, the skip must not commit any side effects such as clearing
+        * the interrupt shadow or RFLAGS.RF.
+        */
+       if (!__svm_skip_emulated_instruction(vcpu, !nrips))
+               return -EIO;
+
+       rip = kvm_rip_read(vcpu);
+
+       /*
+        * Save the injection information, even when using next_rip, as the
+        * VMCB's next_rip will be lost (cleared on VM-Exit) if the injection
+        * doesn't complete due to a VM-Exit occurring while the CPU is
+        * vectoring the event.   Decoding the instruction isn't guaranteed to
+        * work as there may be no backing instruction, e.g. if the event is
+        * being injected by L1 for L2, or if the guest is patching INT3 into
+        * a different instruction.
+        */
+       svm->soft_int_injected = true;
+       svm->soft_int_csbase = svm->vmcb->save.cs.base;
+       svm->soft_int_old_rip = old_rip;
+       svm->soft_int_next_rip = rip;
+
+       if (nrips)
+               kvm_rip_write(vcpu, old_rip);
+
+       if (static_cpu_has(X86_FEATURE_NRIPS))
+               svm->vmcb->control.next_rip = rip;
+
+       return 0;
+}
+
 static void svm_queue_exception(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
        kvm_deliver_exception_payload(vcpu);
 
-       if (nr == BP_VECTOR && !nrips) {
-               unsigned long rip, old_rip = kvm_rip_read(vcpu);
-
-               /*
-                * For guest debugging where we have to reinject #BP if some
-                * INT3 is guest-owned:
-                * Emulate nRIP by moving RIP forward. Will fail if injection
-                * raises a fault that is not intercepted. Still better than
-                * failing in all cases.
-                */
-               (void)svm_skip_emulated_instruction(vcpu);
-               rip = kvm_rip_read(vcpu);
-
-               if (boot_cpu_has(X86_FEATURE_NRIPS))
-                       svm->vmcb->control.next_rip = rip;
-
-               svm->int3_rip = rip + svm->vmcb->save.cs.base;
-               svm->int3_injected = rip - old_rip;
-       }
+       if (kvm_exception_is_soft(nr) &&
+           svm_update_soft_interrupt_rip(vcpu))
+               return;
 
        svm->vmcb->control.event_inj = nr
                | SVM_EVTINJ_VALID
        svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
 }
 
+static void svm_complete_soft_interrupt(struct kvm_vcpu *vcpu, u8 vector,
+                                       int type)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+
+       /*
+        * If NRIPS is enabled, KVM must snapshot the pre-VMRUN next_rip that's
+        * associated with the original soft exception/interrupt.  next_rip is
+        * cleared on all exits that can occur while vectoring an event, so KVM
+        * needs to manually set next_rip for re-injection.  Unlike the !nrips
+        * case below, this needs to be done if and only if KVM is re-injecting
+        * the same event, i.e. if the event is a soft exception/interrupt,
+        * otherwise next_rip is unused on VMRUN.
+        */
+       if (nrips && type == SVM_EXITINTINFO_TYPE_EXEPT &&
+           kvm_exception_is_soft(vector) &&
+           kvm_is_linear_rip(vcpu, svm->soft_int_old_rip + svm->soft_int_csbase))
+               svm->vmcb->control.next_rip = svm->soft_int_next_rip;
+       /*
+        * If NRIPS isn't enabled, KVM must manually advance RIP prior to
+        * injecting the soft exception/interrupt.  That advancement needs to
+        * be unwound if vectoring didn't complete.  Note, the new event may
+        * not be the injected event, e.g. if KVM injected an INTn, the INTn
+        * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will
+        * be the reported vectored event, but RIP still needs to be unwound.
+        */
+       else if (!nrips && type == SVM_EXITINTINFO_TYPE_EXEPT &&
+                kvm_is_linear_rip(vcpu, svm->soft_int_next_rip + svm->soft_int_csbase))
+               kvm_rip_write(vcpu, svm->soft_int_old_rip);
+}
+
 static void svm_complete_interrupts(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
        u8 vector;
        int type;
        u32 exitintinfo = svm->vmcb->control.exit_int_info;
-       unsigned int3_injected = svm->int3_injected;
+       bool soft_int_injected = svm->soft_int_injected;
 
-       svm->int3_injected = 0;
+       svm->soft_int_injected = false;
 
        /*
         * If we've made progress since setting HF_IRET_MASK, we've
        vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
        type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
 
-       /*
-        * If NextRIP isn't enabled, KVM must manually advance RIP prior to
-        * injecting the soft exception/interrupt.  That advancement needs to
-        * be unwound if vectoring didn't complete.  Note, the new event may
-        * not be the injected event, e.g. if KVM injected an INTn, the INTn
-        * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will
-        * be the reported vectored event, but RIP still needs to be unwound.
-        */
-       if (int3_injected && type == SVM_EXITINTINFO_TYPE_EXEPT &&
-          kvm_is_linear_rip(vcpu, svm->int3_rip))
-               kvm_rip_write(vcpu, kvm_rip_read(vcpu) - int3_injected);
+       if (soft_int_injected)
+               svm_complete_soft_interrupt(vcpu, vector, type);
 
        switch (type) {
        case SVM_EXITINTINFO_TYPE_NMI:
                if (vector == X86_TRAP_VC)
                        break;
 
-               /*
-                * In case of software exceptions, do not reinject the vector,
-                * but re-execute the instruction instead.
-                */
-               if (kvm_exception_is_soft(vector))
-                       break;
-
                if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
                        u32 err = svm->vmcb->control.exit_int_info_err;
                        kvm_requeue_exception_e(vcpu, vector, err);