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: 16+ 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: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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox