lkml.org 
[lkml]   [2022]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 03/34] KVM: x86: hyper-v: Add helper to read hypercall data for array
    Date
    From: Sean Christopherson <seanjc@google.com>

    Move the guts of kvm_get_sparse_vp_set() to a helper so that the code for
    reading a guest-provided array can be reused in the future, e.g. for
    getting a list of virtual addresses whose TLB entries need to be flushed.

    Opportunisticaly swap the order of the data and XMM adjustment so that
    the XMM/gpa offsets are bundled together.

    No functional change intended.

    Signed-off-by: Sean Christopherson <seanjc@google.com>
    Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
    ---
    arch/x86/kvm/hyperv.c | 53 +++++++++++++++++++++++++++----------------
    1 file changed, 33 insertions(+), 20 deletions(-)

    diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
    index fb716cf919ed..d66c27fd1e8a 100644
    --- a/arch/x86/kvm/hyperv.c
    +++ b/arch/x86/kvm/hyperv.c
    @@ -1758,38 +1758,51 @@ struct kvm_hv_hcall {
    sse128_t xmm[HV_HYPERCALL_MAX_XMM_REGISTERS];
    };

    -static u64 kvm_get_sparse_vp_set(struct kvm *kvm, struct kvm_hv_hcall *hc,
    - int consumed_xmm_halves,
    - u64 *sparse_banks, gpa_t offset)
    -{
    - u16 var_cnt;
    - int i;

    - if (hc->var_cnt > 64)
    - return -EINVAL;
    -
    - /* Ignore banks that cannot possibly contain a legal VP index. */
    - var_cnt = min_t(u16, hc->var_cnt, KVM_HV_MAX_SPARSE_VCPU_SET_BITS);
    +static int kvm_hv_get_hc_data(struct kvm *kvm, struct kvm_hv_hcall *hc,
    + u16 orig_cnt, u16 cnt_cap, u64 *data,
    + int consumed_xmm_halves, gpa_t offset)
    +{
    + /*
    + * Preserve the original count when ignoring entries via a "cap", KVM
    + * still needs to validate the guest input (though the non-XMM path
    + * punts on the checks).
    + */
    + u16 cnt = min(orig_cnt, cnt_cap);
    + int i, j;

    if (hc->fast) {
    /*
    * Each XMM holds two sparse banks, but do not count halves that
    * have already been consumed for hypercall parameters.
    */
    - if (hc->var_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - consumed_xmm_halves)
    + if (orig_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - consumed_xmm_halves)
    return HV_STATUS_INVALID_HYPERCALL_INPUT;
    - for (i = 0; i < var_cnt; i++) {
    - int j = i + consumed_xmm_halves;
    +
    + for (i = 0; i < cnt; i++) {
    + j = i + consumed_xmm_halves;
    if (j % 2)
    - sparse_banks[i] = sse128_hi(hc->xmm[j / 2]);
    + data[i] = sse128_hi(hc->xmm[j / 2]);
    else
    - sparse_banks[i] = sse128_lo(hc->xmm[j / 2]);
    + data[i] = sse128_lo(hc->xmm[j / 2]);
    }
    return 0;
    }

    - return kvm_read_guest(kvm, hc->ingpa + offset, sparse_banks,
    - var_cnt * sizeof(*sparse_banks));
    + return kvm_read_guest(kvm, hc->ingpa + offset, data,
    + cnt * sizeof(*data));
    +}
    +
    +static u64 kvm_get_sparse_vp_set(struct kvm *kvm, struct kvm_hv_hcall *hc,
    + u64 *sparse_banks, int consumed_xmm_halves,
    + gpa_t offset)
    +{
    + if (hc->var_cnt > 64)
    + return -EINVAL;
    +
    + /* Cap var_cnt to ignore banks that cannot contain a legal VP index. */
    + return kvm_hv_get_hc_data(kvm, hc, hc->var_cnt, KVM_HV_MAX_SPARSE_VCPU_SET_BITS,
    + sparse_banks, consumed_xmm_halves, offset);
    }

    static inline int hv_tlb_flush_ring_free(struct kvm_vcpu_hv *hv_vcpu,
    @@ -1937,7 +1950,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
    if (!hc->var_cnt)
    goto ret_success;

    - if (kvm_get_sparse_vp_set(kvm, hc, 2, sparse_banks,
    + if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks, 2,
    offsetof(struct hv_tlb_flush_ex,
    hv_vp_set.bank_contents)))
    return HV_STATUS_INVALID_HYPERCALL_INPUT;
    @@ -2048,7 +2061,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
    if (!hc->var_cnt)
    goto ret_success;

    - if (kvm_get_sparse_vp_set(kvm, hc, 1, sparse_banks,
    + if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks, 1,
    offsetof(struct hv_send_ipi_ex,
    vp_set.bank_contents)))
    return HV_STATUS_INVALID_HYPERCALL_INPUT;
    --
    2.35.1
    \
     
     \ /
      Last update: 2022-04-14 16:06    [W:3.772 / U:0.128 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site