summaryrefslogtreecommitdiff
path: root/virt/kvm
diff options
context:
space:
mode:
authorAckerley Tng <ackerleytng@google.com>2026-09-10 16:55:44 -0700
committerSean Christopherson <seanjc@google.com>2026-09-22 07:28:31 -0700
commitcb0544296a33f8dae0d60b24cfb4de839b332b98 (patch)
tree868a97fc613770c7a2b58459add78789aeabba6d /virt/kvm
parent856852ef2108fd4e70f29d450487fe15324c647c (diff)
downloadlinux-next-cb0544296a33f8dae0d60b24cfb4de839b332b98.tar.gz
linux-next-cb0544296a33f8dae0d60b24cfb4de839b332b98.zip
KVM: guest_memfd: Zero page while getting pfn
Move the folio initialization logic from kvm_gmem_get_pfn() into __kvm_gmem_get_pfn() to also zero pages if the page is to be used in kvm_gmem_populate(). With in-place conversion, the existing data in a guest_memfd page can be populated into guest memory through platform-specific ioctls. Without first zeroing the page obtained using __kvm_gmem_get_pfn(), it might contain uninitialized host memory, which would leak to the guest if the populate completes. guest_memfd pages are zeroed at most once in the page's entire lifetime with guest_memfd, and that is tracked using the uptodate flag. Zeroing the page in __kvm_gmem_get_pfn() is chosen over zeroing in kvm_gmem_get_folio() since other flows, such as a future write() syscall, can get a page, write to the page and then set page uptodate without zeroing. There may be some performance penalty due to redundant zeroing, but this would pale in comparison to the cost of actually assigning the page to the VM. This aligns with the concept of zeroing before first use - the other place where zeroing happens is in kvm_gmem_fault_user_mapping(). On populate failure, the page is not re-zeroed, since on SNP, if firmware rejects a CPUID page, the expected CPUID values provided by firmware are returned to userspace via page contents. More generally, page contents may be modified on populate failure. Don't mark the page uptodate again after populating, since the page would already be marked uptodate before the post_populate() call. Signed-off-by: Ackerley Tng <ackerleytng@google.com> Tested-by: Shivank Garg <shivankg@amd.com> Reviewed-by: Fuad Tabba <tabba@google.com> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Tested-by: Yan Zhao <yan.y.zhao@intel.com> Link: https://patch.msgid.link/20260910-gmem-inplace-conversion-v13-18-dd6fbf94f4e1@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/guest_memfd.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 8eedff42a96f..a13445c26d9d 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -1154,6 +1154,11 @@ static struct folio *__kvm_gmem_get_pfn(struct file *file,
return ERR_PTR(-EHWPOISON);
}
+ if (!folio_test_uptodate(folio)) {
+ clear_highpage(folio_page(folio, 0));
+ folio_mark_uptodate(folio);
+ }
+
*pfn = folio_file_pfn(folio, index);
if (max_order)
*max_order = 0;
@@ -1182,11 +1187,6 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
goto out;
}
- if (!folio_test_uptodate(folio)) {
- clear_highpage(folio_page(folio, 0));
- folio_mark_uptodate(folio);
- }
-
if (kvm_arch_has_gmem_convert() &&
kvm_gmem_is_private_mem(file_inode(file), index))
r = kvm_arch_gmem_make_private(kvm, gfn, *pfn,
@@ -1228,8 +1228,6 @@ static long __kvm_gmem_populate(struct kvm *kvm, struct kvm_memory_slot *slot,
}
ret = post_populate(kvm, gfn, pfn, src_page, opaque);
- if (!ret)
- folio_mark_uptodate(folio);
out_put_folio:
folio_put(folio);