From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: seanjc@google.com, michael.roth@amd.com
Subject: [PATCH 00/12] KVM: guest_memfd: lazy preparation of pages + prefault support for SEV-SNP
Date: Thu, 11 Jul 2024 18:27:43 -0400 [thread overview]
Message-ID: <20240711222755.57476-1-pbonzini@redhat.com> (raw)
There are a few issues with the implementation of SEV page "preparation"
and KVM_SEV_SNP_LAUNCH_UPDATE:
- doing fallocate() before KVM_SEV_SNP_LAUNCH_UPDATE will cause the latter to fail.
- checking that only private pages are passed to KVM_SEV_SNP_LAUNCH_UPDATE
is done in the guts of vendor code, as is the check that pages are not
passed twice. This goes against the idea of putting as much common
code as possible in kvm_gmem_populate(), for example it returns -EINVAL
if the page is already assigned.
- clearing the page is unnecessary if the firmware will overwrite it
- the "prepare" bool argument is kinda gross
The important observation here is that the two paths that initialize the
contents of the folio are mutually exclusive: either the folio is populated
with unencrypted data by userspace, or it is zeroed because userspace did
not do anything beyond fallocate(). But in the latter there's no need to
zero and prepare the page at the time of fallocate(): it can be done instead
when the guest actually uses the page.
Pulling all the zero-and-prepare code into kvm_gmem_get_pfn() separates the
flows more clearly, but how do you recognize folios that haven't been
prepared yet? The answer is to use the up-to-date flag; there is a
limited attempt to use it right now, but it only concerns itself with
the folio having been cleared. Instead after this series the flag is set
for folios that went through either kvm_gmem_populate() or that have been
mapped into the guest once (and thus went through kvm_arch_gmem_prepare(),
on architectures where that is a thing).
As a bonus, KVM knows exactly which guest is mapping a page, and thus
the preparation code does not have to iterate through all bound
instances of "struct kvm".
There is an easy way vendor-independent way to obtain the previous
behavior if desired, and that is simply to do KVM_PRE_FAULT_MEMORY after
KVM_SEV_SNP_LAUNCH_FINISH.
(Credit for the idea goes to Sean Christopherson, though none of his
tentative implementation is in these patches).
The bulk of the changes is in patches 6, 9 and 12. Everything else is
small preparatory changes; many patches in the first half for example try
to use struct folio more instead of struct page and pfns, which is useful
when we finally extend the code region before folio_unlock() into callers
of kvm_gmem_get_folio(). There's also a couple cleanup in the middle,
mostly patches 4 and 8.
Sorry about the delay sending these out. This should probably be in 6.11
but will not necessarily go in during the merge window, depending on how
review goes.
Tested with the SEV-SNP smoke test that was just posted, and by booting
a Linux guest.
Paolo
Paolo Bonzini (12):
KVM: guest_memfd: return folio from __kvm_gmem_get_pfn()
KVM: guest_memfd: delay folio_mark_uptodate() until after successful
preparation
KVM: guest_memfd: do not go through struct page
KVM: rename CONFIG_HAVE_KVM_GMEM_* to CONFIG_HAVE_KVM_ARCH_GMEM_*
KVM: guest_memfd: return locked folio from __kvm_gmem_get_pfn
KVM: guest_memfd: delay kvm_gmem_prepare_folio() until the memory is
passed to the guest
KVM: guest_memfd: make kvm_gmem_prepare_folio() operate on a single
struct kvm
KVM: remove kvm_arch_gmem_prepare_needed()
KVM: guest_memfd: move check for already-populated page to common code
KVM: cleanup and add shortcuts to kvm_range_has_memory_attributes()
KVM: extend kvm_range_has_memory_attributes() to check subset of
attributes
KVM: guest_memfd: let kvm_gmem_populate() operate only on private gfns
arch/x86/kvm/Kconfig | 4 +-
arch/x86/kvm/mmu/mmu.c | 2 +-
arch/x86/kvm/svm/sev.c | 9 +-
arch/x86/kvm/x86.c | 9 +-
include/linux/kvm_host.h | 9 +-
virt/kvm/Kconfig | 4 +-
virt/kvm/guest_memfd.c | 209 +++++++++++++++++++++++----------------
virt/kvm/kvm_main.c | 73 +++++++-------
8 files changed, 171 insertions(+), 148 deletions(-)
--
2.43.0
next reply other threads:[~2024-07-11 22:28 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-11 22:27 Paolo Bonzini [this message]
2024-07-11 22:27 ` [PATCH 01/12] KVM: guest_memfd: return folio from __kvm_gmem_get_pfn() Paolo Bonzini
2024-07-15 22:26 ` Michael Roth
2024-07-11 22:27 ` [PATCH 02/12] KVM: guest_memfd: delay folio_mark_uptodate() until after successful preparation Paolo Bonzini
2024-07-15 22:32 ` Michael Roth
2024-07-11 22:27 ` [PATCH 03/12] KVM: guest_memfd: do not go through struct page Paolo Bonzini
2024-07-15 22:36 ` Michael Roth
2024-07-11 22:27 ` [PATCH 04/12] KVM: rename CONFIG_HAVE_KVM_GMEM_* to CONFIG_HAVE_KVM_ARCH_GMEM_* Paolo Bonzini
2024-07-15 22:40 ` Michael Roth
2024-07-11 22:27 ` [PATCH 05/12] KVM: guest_memfd: return locked folio from __kvm_gmem_get_pfn Paolo Bonzini
2024-07-15 23:55 ` Michael Roth
2024-07-11 22:27 ` [PATCH 06/12] KVM: guest_memfd: delay kvm_gmem_prepare_folio() until the memory is passed to the guest Paolo Bonzini
2024-07-17 21:28 ` Michael Roth
2024-07-11 22:27 ` [PATCH 07/12] KVM: guest_memfd: make kvm_gmem_prepare_folio() operate on a single struct kvm Paolo Bonzini
2024-07-17 21:34 ` Michael Roth
2024-07-11 22:27 ` [PATCH 08/12] KVM: remove kvm_arch_gmem_prepare_needed() Paolo Bonzini
2024-07-17 21:42 ` Michael Roth
2024-07-11 22:27 ` [PATCH 09/12] KVM: guest_memfd: move check for already-populated page to common code Paolo Bonzini
2024-07-13 1:28 ` Edgecombe, Rick P
2024-07-13 10:10 ` Paolo Bonzini
2024-07-13 20:25 ` Edgecombe, Rick P
2024-07-14 5:32 ` Michael Roth
2024-07-15 16:08 ` Paolo Bonzini
2024-07-15 21:47 ` Michael Roth
2024-07-15 22:57 ` Edgecombe, Rick P
2024-07-16 0:13 ` Michael Roth
2024-07-17 6:42 ` Michael Roth
2024-07-17 21:53 ` Michael Roth
2024-07-11 22:27 ` [PATCH 10/12] KVM: cleanup and add shortcuts to kvm_range_has_memory_attributes() Paolo Bonzini
2024-07-17 22:23 ` Michael Roth
2024-07-11 22:27 ` [PATCH 11/12] KVM: extend kvm_range_has_memory_attributes() to check subset of attributes Paolo Bonzini
2024-07-17 22:32 ` Michael Roth
2024-07-11 22:27 ` [PATCH 12/12] KVM: guest_memfd: let kvm_gmem_populate() operate only on private gfns Paolo Bonzini
2024-07-17 22:49 ` Michael Roth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240711222755.57476-1-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=seanjc@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox