module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444);
 static u64 sev_supported_vmsa_features;
 
+#define AP_RESET_HOLD_NONE             0
+#define AP_RESET_HOLD_NAE_EVENT                1
+#define AP_RESET_HOLD_MSR_PROTO                2
+
 static u8 sev_enc_bit;
 static DECLARE_RWSEM(sev_deactivate_lock);
 static DEFINE_MUTEX(sev_bitmap_lock);
 
 void sev_es_unmap_ghcb(struct vcpu_svm *svm)
 {
+       /* Clear any indication that the vCPU is in a type of AP Reset Hold */
+       svm->sev_es.ap_reset_hold_type = AP_RESET_HOLD_NONE;
+
        if (!svm->sev_es.ghcb)
                return;
 
                                  GHCB_MSR_INFO_POS);
                break;
        }
+       case GHCB_MSR_AP_RESET_HOLD_REQ:
+               svm->sev_es.ap_reset_hold_type = AP_RESET_HOLD_MSR_PROTO;
+               ret = kvm_emulate_ap_reset_hold(&svm->vcpu);
+
+               /*
+                * Preset the result to a non-SIPI return and then only set
+                * the result to non-zero when delivering a SIPI.
+                */
+               set_ghcb_msr_bits(svm, 0,
+                                 GHCB_MSR_AP_RESET_HOLD_RESULT_MASK,
+                                 GHCB_MSR_AP_RESET_HOLD_RESULT_POS);
+
+               set_ghcb_msr_bits(svm, GHCB_MSR_AP_RESET_HOLD_RESP,
+                                 GHCB_MSR_INFO_MASK,
+                                 GHCB_MSR_INFO_POS);
+               break;
        case GHCB_MSR_TERM_REQ: {
                u64 reason_set, reason_code;
 
                ret = 1;
                break;
        case SVM_VMGEXIT_AP_HLT_LOOP:
+               svm->sev_es.ap_reset_hold_type = AP_RESET_HOLD_NAE_EVENT;
                ret = kvm_emulate_ap_reset_hold(vcpu);
                break;
        case SVM_VMGEXIT_AP_JUMP_TABLE: {
                return;
        }
 
-       /*
-        * Subsequent SIPI: Return from an AP Reset Hold VMGEXIT, where
-        * the guest will set the CS and RIP. Set SW_EXIT_INFO_2 to a
-        * non-zero value.
-        */
-       if (!svm->sev_es.ghcb)
-               return;
+       /* Subsequent SIPI */
+       switch (svm->sev_es.ap_reset_hold_type) {
+       case AP_RESET_HOLD_NAE_EVENT:
+               /*
+                * Return from an AP Reset Hold VMGEXIT, where the guest will
+                * set the CS and RIP. Set SW_EXIT_INFO_2 to a non-zero value.
+                */
+               ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, 1);
+               break;
+       case AP_RESET_HOLD_MSR_PROTO:
+               /*
+                * Return from an AP Reset Hold VMGEXIT, where the guest will
+                * set the CS and RIP. Set GHCB data field to a non-zero value.
+                */
+               set_ghcb_msr_bits(svm, 1,
+                                 GHCB_MSR_AP_RESET_HOLD_RESULT_MASK,
+                                 GHCB_MSR_AP_RESET_HOLD_RESULT_POS);
 
-       ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, 1);
+               set_ghcb_msr_bits(svm, GHCB_MSR_AP_RESET_HOLD_RESP,
+                                 GHCB_MSR_INFO_MASK,
+                                 GHCB_MSR_INFO_POS);
+               break;
+       default:
+               break;
+       }
 }
 
 struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu)