From: Sean Christopherson <seanjc@google.com>
To: David Woodhouse <dwmw2@infradead.org>
Cc: Paul Durrant <paul@xen.org>, Hyunwoo Kim <imv4bel@gmail.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Thomas Gleixner <tglx@kernel.org>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 7/8] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
Date: Wed, 8 Jul 2026 08:48:06 -0700 [thread overview]
Message-ID: <ak5xNubAIov1QT6T@google.com> (raw)
In-Reply-To: <20260605143034.3603-8-dwmw2@infradead.org>
On Fri, Jun 05, 2026, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Replace test_and_set_bit() on vcpu_info->evtchn_pending_sel with an
> explicit 'lock btsl' in kvm_xen_set_evtchn_fast(). The generic
> test_and_set_bit() uses a 64-bit locked operation ('lock btsq') on
> x86-64,
x86-64, and the address of the per-vCPU info is guest-controlled and
only required to be 32-bit aligned.
I would also add somewhere:
Note, KVM reuses the local gpc. The atomic accesses to pending_bits is
on the page-aligned per-VM shared_info structure, i.e. doesn't need the
same treatment as the access is guarantee to be 64-bit aligned.
Because without that knowledge it's very difficult to understand why the
test_and_set_bit(xe->port, pending_bits) is fine but the one the event channel
is not.
> which requires 8-byte alignment to avoid split-lock #AC
> exceptions.
>
> Since evtchn_pending_sel is at most 64 bits wide and port_word_bit
> ranges 0-63, a 32-bit 'lock btsl' suffices for both native and compat
> vcpu_info layouts, and only requires the 4-byte alignment that is
> already guaranteed by the registration path.
>
> This also eliminates the bogus cast of compat_vcpu_info's 32-bit
> evtchn_pending_sel to 'unsigned long *' which was the original source
> of the split-lock hazard.
>
> Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
> Reported-by: sashiko-bot@kernel.org
Please add the Closes: link for publicly reported issues, especially for flaws
reported by review bots, as such "bugs" are generally unproven.
Closes: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org
> Assisted-by: Kiro:claude-opus-4.6-1m
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 42 ++++++++++++++++++++++++++++--------------
> 1 file changed, 28 insertions(+), 14 deletions(-)
>
> diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
> index ae0713718367..24e939ef5d64 100644
> --- a/arch/x86/kvm/xen.c
> +++ b/arch/x86/kvm/xen.c
> @@ -1811,7 +1811,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
> {
> struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
> bool has_64bit_shinfo = kvm_xen_has_64bit_shinfo(kvm);
> - unsigned long *pending_bits, *mask_bits;
> + unsigned long *pending_bits, *mask_bits, vi_pending_sel_ofs;
> struct kvm_vcpu *vcpu;
> unsigned long flags;
> int port_word_bit;
> @@ -1844,11 +1844,18 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
> pending_bits = (unsigned long *)&shinfo->evtchn_pending;
> mask_bits = (unsigned long *)&shinfo->evtchn_mask;
> port_word_bit = xe->port / 64;
> +
> + vi_pending_sel_ofs = offsetof(struct vcpu_info, evtchn_pending_sel);
> } else {
> struct compat_shared_info *shinfo = gpc->khva;
> pending_bits = (unsigned long *)&shinfo->evtchn_pending;
> mask_bits = (unsigned long *)&shinfo->evtchn_mask;
> port_word_bit = xe->port / 32;
> +
> + vi_pending_sel_ofs = offsetof(struct compat_vcpu_info, evtchn_pending_sel);
> +
> + /* test_and_set_bit() needs 64-bit alignment, but that's OK */
> + BUILD_BUG_ON(offsetof(struct compat_shared_info, evtchn_pending) & 7);
BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct compat_shared_info, evtchn_pending),
sizeof(unsigned long)));
> }
>
> /*
> @@ -1864,6 +1871,8 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
> rc = -ENOTCONN; /* Masked */
> kvm_xen_check_poller(vcpu, xe->port);
> } else {
> + bool old;
> +
> rc = 1; /* Delivered to the bitmap in shared_info. */
> /* Now switch to the vCPU's vcpu_info to set the index and pending_sel */
> read_unlock_irqrestore(&gpc->lock, flags);
> @@ -1880,19 +1889,24 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
> goto out_rcu;
> }
>
> - if (has_64bit_shinfo) {
> - struct vcpu_info *vcpu_info = gpc->khva;
> - if (!test_and_set_bit(port_word_bit, &vcpu_info->evtchn_pending_sel)) {
> - WRITE_ONCE(vcpu_info->evtchn_upcall_pending, 1);
> - kick_vcpu = true;
> - }
> - } else {
> - struct compat_vcpu_info *vcpu_info = gpc->khva;
> - if (!test_and_set_bit(port_word_bit,
> - (unsigned long *)&vcpu_info->evtchn_pending_sel)) {
> - WRITE_ONCE(vcpu_info->evtchn_upcall_pending, 1);
> - kick_vcpu = true;
> - }
> + /*
> + * Explicitly use btsl instead of test_and_set_bit() because
> + * a 32-bit guest is not required to align to 64 bits, and
> + * that might cause splitlock exceptions.
> + */
> + asm volatile(LOCK_PREFIX "btsl %[bit], %[sel]"
> + : [sel] "+m" (*(u32 *)(gpc->khva + vi_pending_sel_ofs)),
> + "=@ccc" (old)
> + : [bit] "Ir" (port_word_bit) : "memory");
Use GEN_BINARY_RMWcc() to make this less ugly? It'll still be ugly, but slightly
less so. Completely untested, but I think it's this?
old = GEN_BINARY_RMWcc(LOCK_PREFIX "btsl",
*(u32 *)(gpc->khva + vi_pending_sel_ofs),
c, "Ir", port_word_bit);
> + if (!old) {
> + struct vcpu_info *vi = gpc->khva;
> +
> + /* No need for compat handling */
> + BUILD_BUG_ON(offsetof(struct vcpu_info, evtchn_upcall_pending) !=
> + offsetof(struct compat_vcpu_info, evtchn_upcall_pending));
> +
> + WRITE_ONCE(vi->evtchn_upcall_pending, 1);
> + kick_vcpu = true;
> }
>
> /* For the per-vCPU lapic vector, deliver it as MSI. */
> --
> 2.54.0
>
next prev parent reply other threads:[~2026-07-08 15:48 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 14:17 [PATCH 0/8] KVM: x86/xen: Clean up 32-bit vs. 64-bit shared info mode handling David Woodhouse
2026-06-05 14:17 ` [PATCH 1/8] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling David Woodhouse
2026-06-05 14:17 ` [PATCH 2/8] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro David Woodhouse
2026-06-06 9:30 ` David Laight
2026-06-06 9:35 ` David Woodhouse
2026-06-06 11:11 ` David Laight
2026-06-06 11:22 ` David Woodhouse
2026-06-05 14:17 ` [PATCH 3/8] KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port() David Woodhouse
2026-06-05 14:17 ` [PATCH 4/8] KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast() David Woodhouse
2026-06-05 14:17 ` [PATCH 5/8] KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll() David Woodhouse
2026-06-05 14:17 ` [PATCH 6/8] KVM: x86/xen: Enforce alignment of vcpu_info registration David Woodhouse
2026-06-05 14:44 ` sashiko-bot
2026-06-05 15:07 ` David Woodhouse
2026-06-05 14:17 ` [PATCH 7/8] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel David Woodhouse
2026-07-08 15:48 ` Sean Christopherson [this message]
2026-06-05 14:17 ` [PATCH 8/8] KVM: x86/xen: Use 32-bit locked ops in kvm_xen_inject_pending_events() David Woodhouse
2026-07-08 15:23 ` Sean Christopherson
2026-07-08 15:41 ` David Woodhouse
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=ak5xNubAIov1QT6T@google.com \
--to=seanjc@google.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=dwmw2@infradead.org \
--cc=hpa@zytor.com \
--cc=imv4bel@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=paul@xen.org \
--cc=pbonzini@redhat.com \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.