mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: mhal@rbox.co, seanjc@google.com
Subject: [PATCH 03/16] KVM: x86: set gfn-to-pfn cache length consistently with VM word size
Date: Thu, 27 Oct 2022 12:18:36 -0400	[thread overview]
Message-ID: <20221027161849.2989332-4-pbonzini@redhat.com> (raw)
In-Reply-To: <20221027161849.2989332-1-pbonzini@redhat.com>

KVM unconditionally uses the "full" size of the Xen shared info page when
activating the cache in kvm_xen_vcpu_set_attr(), but using the current
mode matches what Xen does.  While KVM did always use the 64-bit size
when activating the cache, what matters is that Xen does not look
beyond the size of the 32-bit struct if the vCPU was initialized in
32-bit mode.  If the guest sets up the runstate info of a 32-bit
VM so that the struct ends at the end of a page, the 64-bit struct
size passed to kvm_gpc_activate() will cause the ioctl or hypercall
to fail, because gfn-to-pfn caches can only be set up for data that fits
in a single page.

Nevertheless, keeping the Xen word size constant throughout the life
of the gpc cache, i.e. not using a different size at check()+refresh()
than at activate(), is desirable because it makes the length/size of
the cache immutable.  This in turn yields a cleaner set of APIs and
avoids potential bugs that could occur if check() were invoked with
a different size than refresh().

So, use the short size at activation time as well.  This means
re-activating the cache if the guest requests the hypercall page
multiple times with different word sizes (this can happen when
kexec-ing, for example).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/xen.c | 47 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index b2be60c6efa4..512b4afa6785 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -198,6 +198,37 @@ static void kvm_xen_update_runstate(struct kvm_vcpu *v, int state)
 	vx->runstate_entry_time = now;
 }
 
+static inline size_t kvm_xen_runstate_info_size(struct kvm *kvm)
+{
+	if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode)
+		return sizeof(struct vcpu_runstate_info);
+	else
+		return sizeof(struct compat_vcpu_runstate_info);
+}
+
+static int kvm_xen_activate_runstate_gpc(struct kvm_vcpu *vcpu, unsigned long gpa)
+{
+	size_t user_len = kvm_xen_runstate_info_size(vcpu->kvm);
+	return kvm_gpc_activate(vcpu->kvm, &vcpu->arch.xen.runstate_cache,
+				NULL, KVM_HOST_USES_PFN, gpa, user_len);
+}
+
+static int kvm_xen_reactivate_runstate_gpcs(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	unsigned long i;
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (vcpu->arch.xen.runstate_cache.active) {
+			int r = kvm_xen_activate_runstate_gpc(vcpu,
+					vcpu->arch.xen.runstate_cache.gpa);
+			if (r < 0)
+				return r;
+		}
+	}
+	return 0;
+}
+
 void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
 {
 	struct kvm_vcpu_xen *vx = &v->arch.xen;
@@ -212,11 +243,7 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
 	if (!vx->runstate_cache.active)
 		return;
 
-	if (IS_ENABLED(CONFIG_64BIT) && v->kvm->arch.xen.long_mode)
-		user_len = sizeof(struct vcpu_runstate_info);
-	else
-		user_len = sizeof(struct compat_vcpu_runstate_info);
-
+	user_len = kvm_xen_runstate_info_size(v->kvm);
 	read_lock_irqsave(&gpc->lock, flags);
 	while (!kvm_gfn_to_pfn_cache_check(v->kvm, gpc, gpc->gpa,
 					   user_len)) {
@@ -461,7 +488,7 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 			mutex_lock(&kvm->lock);
 			kvm->arch.xen.long_mode = !!data->u.long_mode;
 			mutex_unlock(&kvm->lock);
-			r = 0;
+			r = kvm_xen_reactivate_runstate_gpcs(kvm);
 		}
 		break;
 
@@ -596,9 +623,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
 			break;
 		}
 
-		r = kvm_gpc_activate(vcpu->kvm, &vcpu->arch.xen.runstate_cache,
-				     NULL, KVM_HOST_USES_PFN, data->u.gpa,
-				     sizeof(struct vcpu_runstate_info));
+		r = kvm_xen_activate_runstate_gpc(vcpu, data->u.gpa);
 		break;
 
 	case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT:
@@ -843,9 +868,13 @@ int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
 	u32 page_num = data & ~PAGE_MASK;
 	u64 page_addr = data & PAGE_MASK;
 	bool lm = is_long_mode(vcpu);
+	int r;
 
 	/* Latch long_mode for shared_info pages etc. */
 	vcpu->kvm->arch.xen.long_mode = lm;
+	r = kvm_xen_reactivate_runstate_gpcs(kvm);
+	if (r < 0)
+		return 1;
 
 	/*
 	 * If Xen hypercall intercept is enabled, fill the hypercall
-- 
2.31.1



  parent reply	other threads:[~2022-10-27 16:19 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-27 16:18 [PATCH v3 00/16] KVM: x86: Always use non-compat vcpu_runstate_info size for gfn=>pfn cache Paolo Bonzini
2022-10-27 16:18 ` [PATCH 01/16] KVM: Initialize gfn_to_pfn_cache locks in dedicated helper Paolo Bonzini
2022-10-27 16:18 ` [PATCH 02/16] KVM: Reject attempts to consume or refresh inactive gfn_to_pfn_cache Paolo Bonzini
2022-10-27 16:18 ` Paolo Bonzini [this message]
2022-10-27 17:22   ` [PATCH 03/16] KVM: x86: set gfn-to-pfn cache length consistently with VM word size Sean Christopherson
2022-10-28 11:36     ` Paolo Bonzini
2022-10-28 16:31       ` Sean Christopherson
2022-11-13 13:32       ` David Woodhouse
2022-11-13 13:36         ` David Woodhouse
2022-11-14 11:27           ` Durrant, Paul
2022-11-15  0:16             ` David Woodhouse
2022-11-16 22:49               ` David Woodhouse
     [not found]         ` <994314051112513787cc4bd0c7d2694e15190d0f.camel@amazon.co.uk>
2022-11-14 16:33           ` Sean Christopherson
2022-11-14 17:36             ` [EXTERNAL][PATCH " David Woodhouse
2022-11-14 16:58           ` [PATCH " Paolo Bonzini
2022-10-27 16:18 ` [PATCH 04/16] KVM: Shorten gfn_to_pfn_cache function names Paolo Bonzini
2022-10-27 16:18 ` [PATCH 05/16] KVM: x86: Remove unused argument in gpc_unmap_khva() Paolo Bonzini
2022-10-27 16:18 ` [PATCH 06/16] KVM: Store immutable gfn_to_pfn_cache properties Paolo Bonzini
2022-10-27 16:18 ` [PATCH 07/16] KVM: Store gfn_to_pfn_cache length at activation time Paolo Bonzini
2022-10-27 16:18 ` [PATCH 08/16] KVM: Use gfn_to_pfn_cache's immutable "kvm" in kvm_gpc_check() Paolo Bonzini
2022-10-27 16:18 ` [PATCH 09/16] KVM: Clean up hva_to_pfn_retry() Paolo Bonzini
2022-10-27 16:18 ` [PATCH 10/16] KVM: Use gfn_to_pfn_cache's immutable "kvm" in kvm_gpc_refresh() Paolo Bonzini
2022-10-27 16:18 ` [PATCH 11/16] KVM: Drop KVM's API to allow temprorarily unmapping gfn=>pfn cache Paolo Bonzini
2022-10-27 16:18 ` [PATCH 12/16] KVM: Do not partially reinitialize gfn=>pfn cache during activation Paolo Bonzini
2022-10-27 16:18 ` [PATCH 13/16] KVM: Drop @gpa from exported gfn=>pfn cache check() and refresh() helpers Paolo Bonzini
2022-10-27 16:18 ` [PATCH 14/16] KVM: Skip unnecessary "unmap" if gpc is already valid during refresh Paolo Bonzini
2022-10-27 16:18 ` [PATCH 15/16] KVM: selftests: Add tests in xen_shinfo_test to detect lock races Paolo Bonzini
2022-10-27 16:18 ` [PATCH 16/16] KVM: selftests: Mark "guest_saw_irq" as volatile in xen_shinfo_test Paolo Bonzini

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=20221027161849.2989332-4-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhal@rbox.co \
    --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

all inboxes | Powered by JetHome®