From: "Edgecombe, Rick P" <rick.p.edgecombe@intel.com>
To: "pbonzini@redhat.com" <pbonzini@redhat.com>,
"michael.roth@amd.com" <michael.roth@amd.com>
Cc: "kvm@vger.kernel.org" <kvm@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"seanjc@google.com" <seanjc@google.com>
Subject: Re: [PATCH 09/12] KVM: guest_memfd: move check for already-populated page to common code
Date: Mon, 15 Jul 2024 22:57:35 +0000 [thread overview]
Message-ID: <00f105e249b7def9f5631fb2b0fa699688ece4c2.camel@intel.com> (raw)
In-Reply-To: <i4gor4ugezj5ma4l6rnfqanylw6qsvh6rvlqk72ezuadxq6dkn@yqgr5iq3dqed>
On Mon, 2024-07-15 at 16:47 -0500, Michael Roth wrote:
> Makes sense.
>
> If we document mutual exclusion between ranges touched by
> gmem_populate() vs ranges touched by actual userspace issuance of
> KVM_PRE_FAULT_MEMORY (and make sure nothing too crazy happens if users
> don't abide by the documentation), then I think most problems go away...
>
> But there is still at least one awkward constraint for SNP:
> KVM_PRE_FAULT_MEMORY cannot be called for private GPA ranges until after
> SNP_LAUNCH_START is called. This is true even if the GPA range is not
> one of the ranges that will get passed to
> gmem_populate()/SNP_LAUNCH_UPDATE. The reason for this is that when
> binding the ASID to the SNP context as part of SNP_LAUNCH_START, firmware
> will perform checks to make sure that ASID is not already being used in
> the RMP table, and that check will fail if KVM_PRE_FAULT_MEMORY triggered
> for a private page before calling SNP_LAUNCH_START.
>
> So we have this constraint that KVM_PRE_FAULT_MEMORY can't be issued
> before SNP_LAUNCH_START. So it makes me wonder if we should just broaden
> that constraint and for now just disallow KVM_PRE_FAULT_MEMORY prior to
> finalizing a guest, since it'll be easier to lift that restriction later
> versus discovering some other sort of edge case and need to
> retroactively place restrictions.
>
> I've taken Isaku's original pre_fault_memory_test and added a new
> x86-specific coco_pre_fault_memory_test to try to better document and
> exercise these corner cases for SEV and SNP, but I'm hoping it could
> also be useful for TDX (hence the generic name). These are based on
> Pratik's initial SNP selftests (which are in turn based on kvm/queue +
> these patches):
>
> https://github.com/mdroth/linux/commits/snp-uptodate0-kst/
>
> https://github.com/mdroth/linux/commit/dd7d4b1983ceeb653132cfd54ad63f597db85f74
>
>
From the TDX side it wouldn't be horrible to not have to worry about userspace
mucking around with the mirrored page tables in unexpected ways during the
special period. TDX already has its own "finalized" state in kvm_tdx, is there
something similar on the SEV side we could unify with?
I looked at moving from kvm_arch_vcpu_pre_fault_memory() to directly calling
kvm_tdp_map_page(), so we could potentially put whatever check in
kvm_arch_vcpu_pre_fault_memory(). It required a couple exports:
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 03737f3aaeeb..9004ac597a85 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -277,6 +277,7 @@ extern bool tdp_mmu_enabled;
#endif
int kvm_tdp_mmu_get_walk_mirror_pfn(struct kvm_vcpu *vcpu, u64 gpa, kvm_pfn_t
*pfn);
+int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code, u8
*level);
static inline bool kvm_memslots_have_rmaps(struct kvm *kvm)
{
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 7bb6b17b455f..4a3e471ec9fe 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -4721,8 +4721,7 @@ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct
kvm_page_fault *fault)
return direct_page_fault(vcpu, fault);
}
-static int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code,
- u8 *level)
+int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code, u8
*level)
{
int r;
@@ -4759,6 +4758,7 @@ static int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t
gpa, u64 error_code,
return -EIO;
}
}
+EXPORT_SYMBOL_GPL(kvm_tdp_map_page);
long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
struct kvm_pre_fault_memory *range)
@@ -5770,6 +5770,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu)
out:
return r;
}
+EXPORT_SYMBOL_GPL(kvm_mmu_load);
void kvm_mmu_unload(struct kvm_vcpu *vcpu)
{
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 9ac0821eb44b..7161ef68f3da 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -2809,11 +2809,13 @@ struct tdx_gmem_post_populate_arg {
static int tdx_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
void __user *src, int order, void *_arg)
{
+ u64 error_code = PFERR_GUEST_FINAL_MASK | PFERR_PRIVATE_ACCESS;
struct kvm_tdx *kvm_tdx = to_kvm_tdx(kvm);
struct tdx_gmem_post_populate_arg *arg = _arg;
struct kvm_vcpu *vcpu = arg->vcpu;
struct kvm_memory_slot *slot;
gpa_t gpa = gfn_to_gpa(gfn);
+ u8 level = PG_LEVEL_4K;
struct page *page;
kvm_pfn_t mmu_pfn;
int ret, i;
@@ -2832,6 +2834,10 @@ static int tdx_gmem_post_populate(struct kvm *kvm, gfn_t
gfn, kvm_pfn_t pfn,
goto out_put_page;
}
+ ret = kvm_tdp_map_page(vcpu, gpa, error_code, &level);
+ if (ret < 0)
+ goto out_put_page;
+
read_lock(&kvm->mmu_lock);
ret = kvm_tdp_mmu_get_walk_mirror_pfn(vcpu, gpa, &mmu_pfn);
@@ -2910,6 +2916,7 @@ static int tdx_vcpu_init_mem_region(struct kvm_vcpu *vcpu,
struct kvm_tdx_cmd *c
mutex_lock(&kvm->slots_lock);
idx = srcu_read_lock(&kvm->srcu);
+ kvm_mmu_reload(vcpu);
ret = 0;
while (region.nr_pages) {
if (signal_pending(current)) {
next prev parent reply other threads:[~2024-07-15 22:57 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-11 22:27 [PATCH 00/12] KVM: guest_memfd: lazy preparation of pages + prefault support for SEV-SNP Paolo Bonzini
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 [this message]
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=00f105e249b7def9f5631fb2b0fa699688ece4c2.camel@intel.com \
--to=rick.p.edgecombe@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.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