Re: [PATCH v3 04/10] KVM: x86/xen: Punt singleshot timer hcalls to userspace if Xen vCPU ID isn't set

From: Sean Christopherson

Date: Fri Jun 26 2026 - 10:28:18 EST


On Fri, Jun 26, 2026, David Woodhouse wrote:
> On Thu, 2026-06-25 at 15:36 -0700, Sean Christopherson wrote:
> > Explicitly invalidate KVM's internal Xen vCPU ID during vCPU creation
> > instead of *trying* to set the Xen ID to the vCPU index by default, and
> > forward singleshot timer hypercalls to userspace if the VMM hasn't set the
> > Xen ID via KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID.  Using the vCPU's index as its
> > default Xen ID is reasonable in concept, but in practice is horribly flawed
> > as the index is left as '0' until after vCPU initialization completes, i.e.
> > every vCPU gets a Xen ID of '0' by default.
> >
> > Forward hypercalls to userspace instead of trying to salvage any kind of
> > default behavior, as all userspace implementations that support multiple
> > vCPUs either don't enable the timer, are guaranteed to set Xen ID, or work
> > only because *all* guests also screw up the singleshot timer hypercalls.
> > The last scenarios is extremely unlikely given that Linux-as-a-guest uses
> > the actual Xen vCPU ID when making timer hypercalls.  In other words, for
> > all intents and purposes, KVM's ABI is already that userspace must set the
> > Xen vCPU ID, so just commit to that ABI.
> >
> > Note, KVM's handling of KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID restricts the ID to
> > KVM_MAX_VCPUS, so there's no chance of a valid ID colliding with -1u.
>
> Nit: XEN_VCPU_ID_INVALID isn't -1u; it's U32_MAX.
>
> I'd have been slightly happier if you'd used an explicit -1U, perhaps
> with a name of its own (although I guess we wouldn't want to call it
> KVM_VCPU_IDX_INVALID in the *Xen* part).

Ya, I was 50/50 on having KVM define its own INVALID macro versus reusing what
the Xen-the-guest has. I didn't want to open code the literal, because that
would require open coding a somewhat magical value in multiple locations. And
having XEN_VCPU_ID_INVALID and KVM_XEN_VCPU_ID_INVALID, with the same value,
seemed even worse than reusing a macro that isn't strictly owned by KVM.

What if I also add a compile-timer assertion? In the end, KVM doesn't care what
value XEN_VCPU_ID_INVALID uses, so long as it can't colled with what is allowed
by KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID.

diff --git arch/x86/kvm/xen.c arch/x86/kvm/xen.c
index 3ed6686e0a1a..5c60ed9ef2cc 100644
--- arch/x86/kvm/xen.c
+++ arch/x86/kvm/xen.c
@@ -1103,6 +1103,8 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
break;

case KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID:
+ BUILD_BUG_ON(XEN_VCPU_ID_INVALID < KVM_MAX_VCPUS);
+
if (data->u.vcpu_id >= KVM_MAX_VCPUS)
r = -EINVAL;
else {