[PATCH 6/8] KVM: x86/xen: Enforce alignment of vcpu_info registration

From: David Woodhouse

Date: Fri Jun 05 2026 - 10:39:04 EST


From: David Woodhouse <dwmw@xxxxxxxxxxxx>

Xen enforces that the vcpu_info GPA is aligned to sizeof(xen_ulong_t)
(8 bytes in 64-bit mode, 4 bytes in 32-bit mode) in map_guest_area().

KVM has no such check, allowing a guest to register a vcpu_info at an
arbitrary byte alignment. This can cause split-lock #AC exceptions on
hosts with split_lock_detect=fatal, since the event channel delivery
paths use locked atomic operations on evtchn_pending_sel within the
vcpu_info.

Add the same alignment check that Xen performs at vcpu_info
registration time, based on the current long_mode state. Return -ENXIO
on failure, matching Xen's map_guest_area() behaviour for unaligned
requests.

Like Xen, this allows a guest to register vcpu_info at a 4-byte (but
not 8-byte) aligned address while in 32-bit mode and then switch to
64-bit mode. Xen copes with this because it only uses 32-bit atomics
on vcpu_info fields, which is what subsequent commits will do where
necessary for KVM too.

Originally observed in review of an unrelated patch:
https://lore.kernel.org/all/20260604193554.1BA311F00893@xxxxxxxxxxxxxxx/

Cc: stable@xxxxxxxxxxxxxxx
Fixes: 73e69a86347a ("KVM: x86/xen: register vcpu info")
Reported-by: sashiko-bot@xxxxxxxxxx
Assisted-by: Kiro:claude-opus-4.6-1m
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
arch/x86/kvm/xen.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index f9085612e7df..ae0713718367 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -926,6 +926,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
break;
}

+ r = -ENXIO;
+ if (!IS_ALIGNED(data->u.gpa,
+ kvm_xen_has_64bit_shinfo(vcpu->kvm) ?
+ sizeof(unsigned long) : sizeof(u32)))
+ break;
+
r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_info_cache,
data->u.gpa, sizeof(struct vcpu_info));
} else {
@@ -935,6 +941,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
break;
}

+ r = -ENXIO;
+ if (!IS_ALIGNED(data->u.hva,
+ kvm_xen_has_64bit_shinfo(vcpu->kvm) ?
+ sizeof(unsigned long) : sizeof(u32)))
+ break;
+
r = kvm_gpc_activate_hva(&vcpu->arch.xen.vcpu_info_cache,
data->u.hva, sizeof(struct vcpu_info));
}
--
2.54.0