lkml.org 
[lkml]   [2024]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v12 13/29] KVM: SEV: Add support to handle GHCB GPA register VMGEXIT
    Date
    From: Brijesh Singh <brijesh.singh@amd.com>

    SEV-SNP guests are required to perform a GHCB GPA registration. Before
    using a GHCB GPA for a vCPU the first time, a guest must register the
    vCPU GHCB GPA. If hypervisor can work with the guest requested GPA then
    it must respond back with the same GPA otherwise return -1.

    On VMEXIT, verify that the GHCB GPA matches with the registered value.
    If a mismatch is detected, then abort the guest.

    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
    Signed-off-by: Michael Roth <michael.roth@amd.com>
    ---
    arch/x86/include/asm/sev-common.h | 8 ++++++++
    arch/x86/kvm/svm/sev.c | 27 +++++++++++++++++++++++++++
    arch/x86/kvm/svm/svm.h | 7 +++++++
    3 files changed, 42 insertions(+)

    diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
    index 5a8246dd532f..1006bfffe07a 100644
    --- a/arch/x86/include/asm/sev-common.h
    +++ b/arch/x86/include/asm/sev-common.h
    @@ -59,6 +59,14 @@
    #define GHCB_MSR_AP_RESET_HOLD_RESULT_POS 12
    #define GHCB_MSR_AP_RESET_HOLD_RESULT_MASK GENMASK_ULL(51, 0)

    +/* Preferred GHCB GPA Request */
    +#define GHCB_MSR_PREF_GPA_REQ 0x010
    +#define GHCB_MSR_GPA_VALUE_POS 12
    +#define GHCB_MSR_GPA_VALUE_MASK GENMASK_ULL(51, 0)
    +
    +#define GHCB_MSR_PREF_GPA_RESP 0x011
    +#define GHCB_MSR_PREF_GPA_NONE 0xfffffffffffff
    +
    /* GHCB GPA Register */
    #define GHCB_MSR_REG_GPA_REQ 0x012
    #define GHCB_MSR_REG_GPA_REQ_VAL(v) \
    diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
    index 3d6c030091c2..b882f72a940a 100644
    --- a/arch/x86/kvm/svm/sev.c
    +++ b/arch/x86/kvm/svm/sev.c
    @@ -3474,6 +3474,26 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
    set_ghcb_msr_bits(svm, GHCB_MSR_HV_FT_RESP,
    GHCB_MSR_INFO_MASK, GHCB_MSR_INFO_POS);
    break;
    + case GHCB_MSR_PREF_GPA_REQ:
    + set_ghcb_msr_bits(svm, GHCB_MSR_PREF_GPA_NONE, GHCB_MSR_GPA_VALUE_MASK,
    + GHCB_MSR_GPA_VALUE_POS);
    + set_ghcb_msr_bits(svm, GHCB_MSR_PREF_GPA_RESP, GHCB_MSR_INFO_MASK,
    + GHCB_MSR_INFO_POS);
    + break;
    + case GHCB_MSR_REG_GPA_REQ: {
    + u64 gfn;
    +
    + gfn = get_ghcb_msr_bits(svm, GHCB_MSR_GPA_VALUE_MASK,
    + GHCB_MSR_GPA_VALUE_POS);
    +
    + svm->sev_es.ghcb_registered_gpa = gfn_to_gpa(gfn);
    +
    + set_ghcb_msr_bits(svm, gfn, GHCB_MSR_GPA_VALUE_MASK,
    + GHCB_MSR_GPA_VALUE_POS);
    + set_ghcb_msr_bits(svm, GHCB_MSR_REG_GPA_RESP, GHCB_MSR_INFO_MASK,
    + GHCB_MSR_INFO_POS);
    + break;
    + }
    case GHCB_MSR_TERM_REQ: {
    u64 reason_set, reason_code;

    @@ -3537,6 +3557,13 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
    trace_kvm_vmgexit_enter(vcpu->vcpu_id, svm->sev_es.ghcb);

    sev_es_sync_from_ghcb(svm);
    +
    + /* SEV-SNP guest requires that the GHCB GPA must be registered */
    + if (sev_snp_guest(svm->vcpu.kvm) && !ghcb_gpa_is_registered(svm, ghcb_gpa)) {
    + vcpu_unimpl(&svm->vcpu, "vmgexit: GHCB GPA [%#llx] is not registered.\n", ghcb_gpa);
    + return -EINVAL;
    + }
    +
    ret = sev_es_validate_vmgexit(svm);
    if (ret)
    return ret;
    diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
    index a3c190642c57..bb04d63012b4 100644
    --- a/arch/x86/kvm/svm/svm.h
    +++ b/arch/x86/kvm/svm/svm.h
    @@ -208,6 +208,8 @@ struct vcpu_sev_es_state {
    u32 ghcb_sa_len;
    bool ghcb_sa_sync;
    bool ghcb_sa_free;
    +
    + u64 ghcb_registered_gpa;
    };

    struct vcpu_svm {
    @@ -361,6 +363,11 @@ static __always_inline bool sev_snp_guest(struct kvm *kvm)
    #endif
    }

    +static inline bool ghcb_gpa_is_registered(struct vcpu_svm *svm, u64 val)
    +{
    + return svm->sev_es.ghcb_registered_gpa == val;
    +}
    +
    static inline void vmcb_mark_all_dirty(struct vmcb *vmcb)
    {
    vmcb->control.clean = 0;
    --
    2.25.1

    \
     
     \ /
      Last update: 2024-05-27 16:17    [W:6.734 / U:0.096 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site