Re: [PATCH Part2 RFC v4 01/40] KVM: SVM: Add support to handle AP reset MSR protocol
From: Sean Christopherson <seanjc@google.com>
Date: 2021-07-14 20:17:39
Also in:
kvm, linux-coco, linux-crypto, linux-mm, lkml, platform-driver-x86
On Wed, Jul 07, 2021, Brijesh Singh wrote:
From: Tom Lendacky <thomas.lendacky@amd.com> 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@amd.com> Signed-off-by: Brijesh Singh <redacted> ---
...
quoted hunk ↗ jump to hunk
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);
quoted hunk ↗ jump to hunk
+ 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