Skip to content

Commit 2e2409a

Browse files
tlendackybonzini
authored andcommitted
KVM: SVM: Issue WBINVD after deactivating an SEV guest
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 33af3a7 ("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: 33af3a7 ("KVM: SVM: Reduce WBINVD/DF_FLUSH invocations") Signed-off-by: Tom Lendacky <[email protected]> Message-Id: <c8bf9087ca3711c5770bdeaafa3e45b717dc5ef4.1584720426.git.thomas.lendacky@amd.com> Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 2da1ed6 commit 2e2409a

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

arch/x86/kvm/svm.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,14 +1933,6 @@ static void sev_clflush_pages(struct page *pages[], unsigned long npages)
19331933
static void __unregister_enc_region_locked(struct kvm *kvm,
19341934
struct enc_region *region)
19351935
{
1936-
/*
1937-
* The guest may change the memory encryption attribute from C=0 -> C=1
1938-
* or vice versa for this memory range. Lets make sure caches are
1939-
* flushed to ensure that guest data gets written into memory with
1940-
* correct C-bit.
1941-
*/
1942-
sev_clflush_pages(region->pages, region->npages);
1943-
19441936
sev_unpin_memory(kvm, region->pages, region->npages);
19451937
list_del(&region->list);
19461938
kfree(region);
@@ -1970,6 +1962,13 @@ static void sev_vm_destroy(struct kvm *kvm)
19701962

19711963
mutex_lock(&kvm->lock);
19721964

1965+
/*
1966+
* Ensure that all guest tagged cache entries are flushed before
1967+
* releasing the pages back to the system for use. CLFLUSH will
1968+
* not do this, so issue a WBINVD.
1969+
*/
1970+
wbinvd_on_all_cpus();
1971+
19731972
/*
19741973
* if userspace was terminated before unregistering the memory regions
19751974
* then lets unpin all the registered memory.
@@ -7288,6 +7287,13 @@ static int svm_unregister_enc_region(struct kvm *kvm,
72887287
goto failed;
72897288
}
72907289

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

72937299
mutex_unlock(&kvm->lock);

0 commit comments

Comments
 (0)