lkml.org 
[lkml]   [2020]   [Mar]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.5 094/170] KVM: SVM: Issue WBINVD after deactivating an SEV guest
    Date
    From: Tom Lendacky <thomas.lendacky@amd.com>

    commit 2e2409afe5f0c284c7dfe5504058e8d115806a7d upstream.

    Currently, CLFLUSH is used to flush SEV guest memory before the guest is
    terminated (or a memory hotplug region is removed). However, CLFLUSH is
    not enough to ensure that SEV guest tagged data is flushed from the cache.

    With 33af3a7ef9e6 ("KVM: SVM: Reduce WBINVD/DF_FLUSH invocations"), the
    original WBINVD was removed. This then exposed crashes at random times
    because of a cache flush race with a page that had both a hypervisor and
    a guest tag in the cache.

    Restore the WBINVD when destroying an SEV guest and add a WBINVD to the
    svm_unregister_enc_region() function to ensure hotplug memory is flushed
    when removed. The DF_FLUSH can still be avoided at this point.

    Fixes: 33af3a7ef9e6 ("KVM: SVM: Reduce WBINVD/DF_FLUSH invocations")
    Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
    Message-Id: <c8bf9087ca3711c5770bdeaafa3e45b717dc5ef4.1584720426.git.thomas.lendacky@amd.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/kvm/svm.c | 22 ++++++++++++++--------
    1 file changed, 14 insertions(+), 8 deletions(-)

    --- a/arch/x86/kvm/svm.c
    +++ b/arch/x86/kvm/svm.c
    @@ -1920,14 +1920,6 @@ static void sev_clflush_pages(struct pag
    static void __unregister_enc_region_locked(struct kvm *kvm,
    struct enc_region *region)
    {
    - /*
    - * The guest may change the memory encryption attribute from C=0 -> C=1
    - * or vice versa for this memory range. Lets make sure caches are
    - * flushed to ensure that guest data gets written into memory with
    - * correct C-bit.
    - */
    - sev_clflush_pages(region->pages, region->npages);
    -
    sev_unpin_memory(kvm, region->pages, region->npages);
    list_del(&region->list);
    kfree(region);
    @@ -1958,6 +1950,13 @@ static void sev_vm_destroy(struct kvm *k
    mutex_lock(&kvm->lock);

    /*
    + * Ensure that all guest tagged cache entries are flushed before
    + * releasing the pages back to the system for use. CLFLUSH will
    + * not do this, so issue a WBINVD.
    + */
    + wbinvd_on_all_cpus();
    +
    + /*
    * if userspace was terminated before unregistering the memory regions
    * then lets unpin all the registered memory.
    */
    @@ -7212,6 +7211,13 @@ static int svm_unregister_enc_region(str
    goto failed;
    }

    + /*
    + * Ensure that all guest tagged cache entries are flushed before
    + * releasing the pages back to the system for use. CLFLUSH will
    + * not do this, so issue a WBINVD.
    + */
    + wbinvd_on_all_cpus();
    +
    __unregister_enc_region_locked(kvm, region);

    mutex_unlock(&kvm->lock);

    \
     
     \ /
      Last update: 2020-03-31 11:07    [W:4.023 / U:0.116 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site