On Wed, Jul 07, 2021, Brijesh Singh wrote: > From: Tom Lendacky <thomas.lendacky@xxxxxxx> > > Add support for AP Reset Hold being invoked using the GHCB MSR protocol, > available in version 2 of the GHCB specification. Please provide a brief overview of the protocol, and why it's needed. I assume it's to allow AP wakeup without a shared GHCB? > Signed-off-by: Tom Lendacky <thomas.lendacky@xxxxxxx> > Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> > --- ... > static u8 sev_enc_bit; > static DECLARE_RWSEM(sev_deactivate_lock); > static DEFINE_MUTEX(sev_bitmap_lock); > @@ -2199,6 +2203,9 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) > > void sev_es_unmap_ghcb(struct vcpu_svm *svm) > { > + /* Clear any indication that the vCPU is in a type of AP Reset Hold */ > + svm->ap_reset_hold_type = AP_RESET_HOLD_NONE; > + > if (!svm->ghcb) > return; > > @@ -2404,6 +2411,22 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm) > GHCB_MSR_INFO_POS); > break; > } > + case GHCB_MSR_AP_RESET_HOLD_REQ: > + svm->ap_reset_hold_type = AP_RESET_HOLD_MSR_PROTO; > + ret = kvm_emulate_ap_reset_hold(&svm->vcpu); The hold type feels like it should be a param to kvm_emulate_ap_reset_hold(). > + > + /* > + * 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); It looks like all uses set an arbitrary value and then the response. I think folding the response into the helper would improve both readability and robustness. I also suspect the helper needs to do WRITE_ONCE() to guarantee the guest sees what it's supposed to see, though memory ordering is not my strong suit. Might even be able to squeeze in a build-time assertion. Also, do the guest-provided contents actually need to be preserved? That seems somewhat odd. E.g. can it be static void set_ghcb_msr_response(struct vcpu_svm *svm, u64 response, u64 value, u64 mask, unsigned int pos) { u64 val = (response << GHCB_MSR_INFO_POS) | (val << pos); WRITE_ONCE(svm->vmcb->control.ghcb_gpa |= (value & mask) << pos; } and set_ghcb_msr_response(svm, GHCB_MSR_AP_RESET_HOLD_RESP, GHCB_MSR_AP_RESET_HOLD_RESULT_MASK, GHCB_MSR_AP_RESET_HOLD_RESULT_POS); > + break; > case GHCB_MSR_TERM_REQ: { > u64 reason_set, reason_code; > > @@ -2491,6 +2514,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) > ret = svm_invoke_exit_handler(vcpu, SVM_EXIT_IRET); > break; > case SVM_VMGEXIT_AP_HLT_LOOP: > + svm->ap_reset_hold_type = AP_RESET_HOLD_NAE_EVENT; > ret = kvm_emulate_ap_reset_hold(vcpu); > break; > case SVM_VMGEXIT_AP_JUMP_TABLE: { > @@ -2628,13 +2652,29 @@ void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector) > 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->ghcb) > - return; > + /* Subsequent SIPI */ > + switch (svm->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->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->ghcb, 1); > + set_ghcb_msr_bits(svm, GHCB_MSR_AP_RESET_HOLD_RESP, > + GHCB_MSR_INFO_MASK, > + GHCB_MSR_INFO_POS); > + break; > + default: > + break; > + } > } > diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h > index 0b89aee51b74..ad12ca26b2d8 100644 > --- a/arch/x86/kvm/svm/svm.h > +++ b/arch/x86/kvm/svm/svm.h > @@ -174,6 +174,7 @@ struct vcpu_svm { > struct ghcb *ghcb; > struct kvm_host_map ghcb_map; > bool received_first_sipi; > + unsigned int ap_reset_hold_type; Can't this be a u8? > > /* SEV-ES scratch area support */ > void *ghcb_sa; > -- > 2.17.1 >