* [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:18 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 02/13] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro David Woodhouse
` (12 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
Rename the local 'longmode' variable and function parameter to
'is_64bit' throughout the Xen hypercall handling code. This
distinguishes it from the VM-wide kvm->arch.xen.long_mode which
represents the Xen shared_info layout mode.
The 'is_64bit' parameter indicates whether the vCPU was in 64-bit
mode when it made the hypercall, which determines how to parse the
hypercall arguments. The UAPI field name (vcpu->run->xen.u.hcall.longmode)
is unchanged.
Assisted-by: Kiro:claude-opus-4.6-1m
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 998cdcb6aa30..8eda3a71462e 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1485,7 +1485,7 @@ static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
return ret;
}
-static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
+static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
u64 param, u64 *r)
{
struct sched_poll sched_poll;
@@ -1497,7 +1497,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
!(vcpu->kvm->arch.xen.hvm_config.flags & KVM_XEN_HVM_CONFIG_EVTCHN_SEND))
return false;
- if (IS_ENABLED(CONFIG_64BIT) && !longmode) {
+ if (IS_ENABLED(CONFIG_64BIT) && !is_64bit) {
struct compat_sched_poll sp32;
/* Sanity check that the compat struct definition is correct */
@@ -1594,12 +1594,12 @@ static void cancel_evtchn_poll(struct timer_list *t)
kvm_vcpu_kick(vcpu);
}
-static bool kvm_xen_hcall_sched_op(struct kvm_vcpu *vcpu, bool longmode,
+static bool kvm_xen_hcall_sched_op(struct kvm_vcpu *vcpu, bool is_64bit,
int cmd, u64 param, u64 *r)
{
switch (cmd) {
case SCHEDOP_poll:
- if (kvm_xen_schedop_poll(vcpu, longmode, param, r))
+ if (kvm_xen_schedop_poll(vcpu, is_64bit, param, r))
return true;
fallthrough;
case SCHEDOP_yield:
@@ -1618,7 +1618,7 @@ struct compat_vcpu_set_singleshot_timer {
uint32_t flags;
} __attribute__((packed));
-static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool longmode, int cmd,
+static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool is_64bit, int cmd,
int vcpu_id, u64 param, u64 *r)
{
struct vcpu_set_singleshot_timer oneshot;
@@ -1662,7 +1662,7 @@ static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool longmode, int cmd,
BUILD_BUG_ON(sizeof_field(struct compat_vcpu_set_singleshot_timer, flags) !=
sizeof_field(struct vcpu_set_singleshot_timer, flags));
- if (kvm_read_guest_virt(vcpu, param, &oneshot, longmode ? sizeof(oneshot) :
+ if (kvm_read_guest_virt(vcpu, param, &oneshot, is_64bit ? sizeof(oneshot) :
sizeof(struct compat_vcpu_set_singleshot_timer), &e)) {
*r = -EFAULT;
return true;
@@ -1694,7 +1694,7 @@ static bool kvm_xen_hcall_set_timer_op(struct kvm_vcpu *vcpu, uint64_t timeout,
int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
{
- bool longmode;
+ bool is_64bit;
u64 input, params[6], r = -ENOSYS;
bool handled = false;
u8 cpl;
@@ -1704,8 +1704,8 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
kvm_hv_hypercall_enabled(vcpu))
return kvm_hv_hypercall(vcpu);
- longmode = is_64_bit_hypercall(vcpu);
- if (!longmode) {
+ is_64bit = is_64_bit_hypercall(vcpu);
+ if (!is_64bit) {
input = kvm_eax_read(vcpu);
params[0] = kvm_ebx_read(vcpu);
params[1] = kvm_ecx_read(vcpu);
@@ -1751,17 +1751,17 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
handled = kvm_xen_hcall_evtchn_send(vcpu, params[1], &r);
break;
case __HYPERVISOR_sched_op:
- handled = kvm_xen_hcall_sched_op(vcpu, longmode, params[0],
+ handled = kvm_xen_hcall_sched_op(vcpu, is_64bit, params[0],
params[1], &r);
break;
case __HYPERVISOR_vcpu_op:
- handled = kvm_xen_hcall_vcpu_op(vcpu, longmode, params[0], params[1],
+ handled = kvm_xen_hcall_vcpu_op(vcpu, is_64bit, params[0], params[1],
params[2], &r);
break;
case __HYPERVISOR_set_timer_op: {
u64 timeout = params[0];
/* In 32-bit mode, the 64-bit timeout is in two 32-bit params. */
- if (!longmode)
+ if (!is_64bit)
timeout |= params[1] << 32;
handled = kvm_xen_hcall_set_timer_op(vcpu, timeout, &r);
break;
@@ -1776,7 +1776,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
handle_in_userspace:
vcpu->run->exit_reason = KVM_EXIT_XEN;
vcpu->run->xen.type = KVM_EXIT_XEN_HCALL;
- vcpu->run->xen.u.hcall.longmode = longmode;
+ vcpu->run->xen.u.hcall.longmode = is_64bit;
vcpu->run->xen.u.hcall.cpl = cpl;
vcpu->run->xen.u.hcall.input = input;
vcpu->run->xen.u.hcall.params[0] = params[0];
base-commit: 76671054f9a1ff6abb976583cd8da37650acdc97
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling
2026-08-31 21:26 ` [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling David Woodhouse
@ 2026-09-02 12:18 ` Paul Durrant
2026-09-02 18:24 ` David Woodhouse
0 siblings, 1 reply; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:18 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Rename the local 'longmode' variable and function parameter to
> 'is_64bit' throughout the Xen hypercall handling code. This
> distinguishes it from the VM-wide kvm->arch.xen.long_mode which
> represents the Xen shared_info layout mode.
>
> The 'is_64bit' parameter indicates whether the vCPU was in 64-bit
> mode when it made the hypercall, which determines how to parse the
> hypercall arguments. The UAPI field name (vcpu->run->xen.u.hcall.longmode)
> is unchanged.
>
Given that 'longmode' is the term used in the UAPI I'm not sure I really
see the point in this change (particularly since there is not even a
name clash with 'long_mode').
> Assisted-by: Kiro:claude-opus-4.6-1m
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 26 +++++++++++++-------------
> 1 file changed, 13 insertions(+), 13 deletions(-)
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling
2026-09-02 12:18 ` Paul Durrant
@ 2026-09-02 18:24 ` David Woodhouse
2026-09-02 18:57 ` Sean Christopherson
0 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-09-02 18:24 UTC (permalink / raw)
To: Paul Durrant, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
[-- Attachment #1: Type: text/plain, Size: 1168 bytes --]
On Wed, 2026-09-02 at 13:18 +0100, Paul Durrant wrote:
> On 31/08/2026 22:26, David Woodhouse wrote:
> > From: David Woodhouse <dwmw@amazon.co.uk>
> >
> > Rename the local 'longmode' variable and function parameter to
> > 'is_64bit' throughout the Xen hypercall handling code. This
> > distinguishes it from the VM-wide kvm->arch.xen.long_mode which
> > represents the Xen shared_info layout mode.
> >
> > The 'is_64bit' parameter indicates whether the vCPU was in 64-bit
> > mode when it made the hypercall, which determines how to parse the
> > hypercall arguments. The UAPI field name (vcpu->run->xen.u.hcall.longmode)
> > is unchanged.
> >
>
> Given that 'longmode' is the term used in the UAPI I'm not sure I really
> see the point in this change (particularly since there is not even a
> name clash with 'long_mode').
The difference between 'longmode' and 'long_mode' is subtle, and *has*
caused confusion which IIRC is what led to part of this series.
Having to keep 'longmode' in the UAPI for KVM_EXIT_XEN_HCALL is sad,
but at least the context is very clear there (xen.u.hcall.longmode).
The code itself avoids the confusion.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling
2026-09-02 18:24 ` David Woodhouse
@ 2026-09-02 18:57 ` Sean Christopherson
2026-09-02 22:00 ` David Woodhouse
0 siblings, 1 reply; 38+ messages in thread
From: Sean Christopherson @ 2026-09-02 18:57 UTC (permalink / raw)
To: David Woodhouse
Cc: Paul Durrant, pbonzini, joao.m.martins, boris.ostrovsky,
ankur.a.arora, tglx, mingo, bp, dave.hansen, hpa, x86,
syzbot+208f7f3e5f59c11aeb90, syzkaller-bugs, suryasaimadhu369,
lkp, nicoyip.dev, frn1furkan10, kvm, linux-kernel, imv4bel
On Wed, Sep 02, 2026, David Woodhouse wrote:
> On Wed, 2026-09-02 at 13:18 +0100, Paul Durrant wrote:
> > On 31/08/2026 22:26, David Woodhouse wrote:
> > > From: David Woodhouse <dwmw@amazon.co.uk>
> > >
> > > Rename the local 'longmode' variable and function parameter to
> > > 'is_64bit' throughout the Xen hypercall handling code. This
> > > distinguishes it from the VM-wide kvm->arch.xen.long_mode which
> > > represents the Xen shared_info layout mode.
> > >
> > > The 'is_64bit' parameter indicates whether the vCPU was in 64-bit
> > > mode when it made the hypercall, which determines how to parse the
> > > hypercall arguments. The UAPI field name (vcpu->run->xen.u.hcall.longmode)
> > > is unchanged.
> > >
> >
> > Given that 'longmode' is the term used in the UAPI I'm not sure I really
> > see the point in this change (particularly since there is not even a
> > name clash with 'long_mode').
>
> The difference between 'longmode' and 'long_mode' is subtle, and *has*
> caused confusion which IIRC is what led to part of this series.
>
> Having to keep 'longmode' in the UAPI for KVM_EXIT_XEN_HCALL is sad,
> but at least the context is very clear there (xen.u.hcall.longmode).
We can actually "fix" that, if we want. And given that the only "longmode"
reference left in KVM is one in kvm_hv_hypercall_set_result() that can and should
be nuked, I think it make sense to purge longmode from KVM's source.
We already did something very similar in e65733b5c59a ("KVM: x86: Redefine 'longmode'
as a flag for KVM_EXIT_HYPERCALL"). And if we expose both names to userspace, we can
even purge the misleading name from selftests without forcing existing VMMs to
rebuild.
E.g. (completely untested)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 718396340d3c..043a61e2409d 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1804,7 +1804,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
handle_in_userspace:
vcpu->run->exit_reason = KVM_EXIT_XEN;
vcpu->run->xen.type = KVM_EXIT_XEN_HCALL;
- vcpu->run->xen.u.hcall.longmode = is_64bit;
+ vcpu->run->xen.u.hcall.is_64bit = is_64bit;
vcpu->run->xen.u.hcall.cpl = cpl;
vcpu->run->xen.u.hcall.input = input;
vcpu->run->xen.u.hcall.params[0] = params[0];
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 9fc8dfdfd65f..5a74765732e3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -131,7 +131,12 @@ struct kvm_xen_exit {
__u32 type;
union {
struct {
- __u32 longmode;
+ union {
+#ifndef __KERNEL__
+ __u32 longmode;
+#endif
+ __u32 is_64bit;
+ };
__u32 cpl;
__u64 input;
__u64 result;
diff --git a/tools/testing/selftests/kvm/x86/xen_vmcall_test.c b/tools/testing/selftests/kvm/x86/xen_vmcall_test.c
index 2585087cdf5c..702920674b57 100644
--- a/tools/testing/selftests/kvm/x86/xen_vmcall_test.c
+++ b/tools/testing/selftests/kvm/x86/xen_vmcall_test.c
@@ -111,7 +111,7 @@ int main(int argc, char *argv[])
if (run->exit_reason == KVM_EXIT_XEN) {
TEST_ASSERT_EQ(run->xen.type, KVM_EXIT_XEN_HCALL);
TEST_ASSERT_EQ(run->xen.u.hcall.cpl, 0);
- TEST_ASSERT_EQ(run->xen.u.hcall.longmode, 1);
+ TEST_ASSERT_EQ(run->xen.u.hcall.is_64bit, 1);
TEST_ASSERT_EQ(run->xen.u.hcall.input, INPUTVALUE);
TEST_ASSERT_EQ(run->xen.u.hcall.params[0], ARGVALUE(1));
TEST_ASSERT_EQ(run->xen.u.hcall.params[1], ARGVALUE(2));
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling
2026-09-02 18:57 ` Sean Christopherson
@ 2026-09-02 22:00 ` David Woodhouse
0 siblings, 0 replies; 38+ messages in thread
From: David Woodhouse @ 2026-09-02 22:00 UTC (permalink / raw)
To: Sean Christopherson
Cc: Paul Durrant, pbonzini, joao.m.martins, boris.ostrovsky,
ankur.a.arora, tglx, mingo, bp, dave.hansen, hpa, x86,
syzbot+208f7f3e5f59c11aeb90, syzkaller-bugs, suryasaimadhu369,
lkp, nicoyip.dev, frn1furkan10, kvm, linux-kernel, imv4bel
[-- Attachment #1: Type: text/plain, Size: 3191 bytes --]
On Wed, 2026-09-02 at 11:57 -0700, Sean Christopherson wrote:
> On Wed, Sep 02, 2026, David Woodhouse wrote:
> > On Wed, 2026-09-02 at 13:18 +0100, Paul Durrant wrote:
> > > On 31/08/2026 22:26, David Woodhouse wrote:
> > > > From: David Woodhouse <dwmw@amazon.co.uk>
> > > >
> > > > Rename the local 'longmode' variable and function parameter to
> > > > 'is_64bit' throughout the Xen hypercall handling code. This
> > > > distinguishes it from the VM-wide kvm->arch.xen.long_mode which
> > > > represents the Xen shared_info layout mode.
> > > >
> > > > The 'is_64bit' parameter indicates whether the vCPU was in 64-bit
> > > > mode when it made the hypercall, which determines how to parse the
> > > > hypercall arguments. The UAPI field name (vcpu->run->xen.u.hcall.longmode)
> > > > is unchanged.
> > > >
> > >
> > > Given that 'longmode' is the term used in the UAPI I'm not sure I really
> > > see the point in this change (particularly since there is not even a
> > > name clash with 'long_mode').
> >
> > The difference between 'longmode' and 'long_mode' is subtle, and *has*
> > caused confusion which IIRC is what led to part of this series.
> >
> > Having to keep 'longmode' in the UAPI for KVM_EXIT_XEN_HCALL is sad,
> > but at least the context is very clear there (xen.u.hcall.longmode).
>
> We can actually "fix" that, if we want. And given that the only "longmode"
> reference left in KVM is one in kvm_hv_hypercall_set_result() that can and should
> be nuked, I think it make sense to purge longmode from KVM's source.
>
> We already did something very similar in e65733b5c59a ("KVM: x86: Redefine 'longmode'
> as a flag for KVM_EXIT_HYPERCALL"). And if we expose both names to userspace, we can
> even purge the misleading name from selftests without forcing existing VMMs to
> rebuild.
>
> E.g. (completely untested)
>
> diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
> index 718396340d3c..043a61e2409d 100644
> --- a/arch/x86/kvm/xen.c
> +++ b/arch/x86/kvm/xen.c
> @@ -1804,7 +1804,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
> handle_in_userspace:
> vcpu->run->exit_reason = KVM_EXIT_XEN;
> vcpu->run->xen.type = KVM_EXIT_XEN_HCALL;
> - vcpu->run->xen.u.hcall.longmode = is_64bit;
> + vcpu->run->xen.u.hcall.is_64bit = is_64bit;
> vcpu->run->xen.u.hcall.cpl = cpl;
> vcpu->run->xen.u.hcall.input = input;
> vcpu->run->xen.u.hcall.params[0] = params[0];
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 9fc8dfdfd65f..5a74765732e3 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -131,7 +131,12 @@ struct kvm_xen_exit {
> __u32 type;
> union {
> struct {
> - __u32 longmode;
> + union {
> +#ifndef __KERNEL__
> + __u32 longmode;
> +#endif
> + __u32 is_64bit;
> + };
> __u32 cpl;
> __u64 input;
> __u64 result;
I worry that this kind of thing would leave me grepping the kernel for
"what even *sets* longmode?" after seeing userspace consuming that
field. In the context of a structure that is explicitly about the
hypercall, I think the existing name is fine.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 02/13] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
2026-08-31 21:26 ` [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:21 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 03/13] KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port() David Woodhouse
` (11 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
Add a kvm_xen_has_64bit_shinfo() helper macro to replace the repeated
pattern of 'IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode'
throughout the Xen emulation code. The macro uses READ_ONCE() to
ensure a consistent snapshot of the flag, which can be changed by
another vCPU at any time.
This is the KVM equivalent of Xen's !has_32bit_shinfo().
Assisted-by: Kiro:claude-opus-4.6-1m
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 16 ++++++++--------
arch/x86/kvm/xen.h | 5 +++++
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 8eda3a71462e..b89c973c2730 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -73,7 +73,7 @@ static int kvm_xen_shared_info_init(struct kvm *kvm)
BUILD_BUG_ON(offsetof(struct shared_info, wc) != 0xc00);
BUILD_BUG_ON(offsetof(struct shared_info, wc_sec_hi) != 0xc0c);
- if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
+ if (kvm_xen_has_64bit_shinfo(kvm)) {
struct shared_info *shinfo = gpc->khva;
wc_sec_hi = &shinfo->wc_sec_hi;
@@ -389,7 +389,7 @@ static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic)
BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) !=
sizeof(vx->runstate_times));
- if (IS_ENABLED(CONFIG_64BIT) && v->kvm->arch.xen.long_mode) {
+ if (kvm_xen_has_64bit_shinfo(v->kvm)) {
user_len = sizeof(struct vcpu_runstate_info);
times_ofs = offsetof(struct vcpu_runstate_info,
state_entry_time);
@@ -676,7 +676,7 @@ void kvm_xen_inject_pending_events(struct kvm_vcpu *v)
}
/* Now gpc->khva is a valid kernel address for the vcpu_info */
- if (IS_ENABLED(CONFIG_64BIT) && v->kvm->arch.xen.long_mode) {
+ if (kvm_xen_has_64bit_shinfo(v->kvm)) {
struct vcpu_info *vi = gpc->khva;
asm volatile(LOCK_PREFIX "orq %0, %1\n"
@@ -993,7 +993,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
* address, that's actually OK. kvm_xen_update_runstate_guest()
* will cope.
*/
- if (IS_ENABLED(CONFIG_64BIT) && vcpu->kvm->arch.xen.long_mode)
+ if (kvm_xen_has_64bit_shinfo(vcpu->kvm))
sz = sizeof(struct vcpu_runstate_info);
else
sz = sizeof(struct compat_vcpu_runstate_info);
@@ -1441,7 +1441,7 @@ static int kvm_xen_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
static inline int max_evtchn_port(struct kvm *kvm)
{
- if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode)
+ if (kvm_xen_has_64bit_shinfo(kvm))
return EVTCHN_2L_NR_CHANNELS;
else
return COMPAT_EVTCHN_2L_NR_CHANNELS;
@@ -1463,7 +1463,7 @@ static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
goto out_rcu;
ret = false;
- if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
+ if (kvm_xen_has_64bit_shinfo(kvm)) {
struct shared_info *shinfo = gpc->khva;
pending_bits = (unsigned long *)&shinfo->evtchn_pending;
} else {
@@ -1844,7 +1844,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
if (!kvm_gpc_check(gpc, PAGE_SIZE))
goto out_rcu;
- if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
+ if (kvm_xen_has_64bit_shinfo(kvm)) {
struct shared_info *shinfo = gpc->khva;
pending_bits = (unsigned long *)&shinfo->evtchn_pending;
mask_bits = (unsigned long *)&shinfo->evtchn_mask;
@@ -1885,7 +1885,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
goto out_rcu;
}
- if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
+ if (kvm_xen_has_64bit_shinfo(kvm)) {
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);
diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h
index f372855857a8..9d04e350bdb1 100644
--- a/arch/x86/kvm/xen.h
+++ b/arch/x86/kvm/xen.h
@@ -235,6 +235,11 @@ struct compat_shared_info {
#define COMPAT_EVTCHN_2L_NR_CHANNELS (8 * \
sizeof_field(struct compat_shared_info, \
evtchn_pending))
+
+/* Latched VM-wide mode; the KVM equivalent of Xen's !has_32bit_shinfo(). */
+#define kvm_xen_has_64bit_shinfo(kvm) \
+ (IS_ENABLED(CONFIG_64BIT) && READ_ONCE((kvm)->arch.xen.long_mode))
+
struct compat_vcpu_runstate_info {
int state;
uint64_t state_entry_time;
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 02/13] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro
2026-08-31 21:26 ` [PATCH v3 02/13] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro David Woodhouse
@ 2026-09-02 12:21 ` Paul Durrant
2026-09-02 18:28 ` David Woodhouse
0 siblings, 1 reply; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:21 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Add a kvm_xen_has_64bit_shinfo() helper macro to replace the repeated
> pattern of 'IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode'
> throughout the Xen emulation code. The macro uses READ_ONCE() to
> ensure a consistent snapshot of the flag, which can be changed by
> another vCPU at any time.
>
> This is the KVM equivalent of Xen's !has_32bit_shinfo().
>
> Assisted-by: Kiro:claude-opus-4.6-1m
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 16 ++++++++--------
> arch/x86/kvm/xen.h | 5 +++++
> 2 files changed, 13 insertions(+), 8 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
...although adding kvm_xen_has_32bit_shinfo() for consistency with Xen
might be slightly neater.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 02/13] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro
2026-09-02 12:21 ` Paul Durrant
@ 2026-09-02 18:28 ` David Woodhouse
0 siblings, 0 replies; 38+ messages in thread
From: David Woodhouse @ 2026-09-02 18:28 UTC (permalink / raw)
To: Paul Durrant, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
[-- Attachment #1: Type: text/plain, Size: 1357 bytes --]
On Wed, 2026-09-02 at 13:21 +0100, Paul Durrant wrote:
> On 31/08/2026 22:26, David Woodhouse wrote:
> > From: David Woodhouse <dwmw@amazon.co.uk>
> >
> > Add a kvm_xen_has_64bit_shinfo() helper macro to replace the repeated
> > pattern of 'IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode'
> > throughout the Xen emulation code. The macro uses READ_ONCE() to
> > ensure a consistent snapshot of the flag, which can be changed by
> > another vCPU at any time.
> >
> > This is the KVM equivalent of Xen's !has_32bit_shinfo().
> >
> > Assisted-by: Kiro:claude-opus-4.6-1m
> > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> > ---
> > arch/x86/kvm/xen.c | 16 ++++++++--------
> > arch/x86/kvm/xen.h | 5 +++++
> > 2 files changed, 13 insertions(+), 8 deletions(-)
> >
> Reviewed-by: Paul Durrant <paul@xen.org>
>
> ...although adding kvm_xen_has_32bit_shinfo() for consistency with Xen
> might be slightly neater.
I did briefly ponder that, but *all* the existing callers that this
patch converts are of the if (64bit) form, so we'd end up negating both
the implementation *and* all the callers to achieve that consistency.
And frankly, I want "consistency with Xen" on a code level about as
much as I want to gouge my eyes out with a rusty spoon. There's a
*reason* all of this code exists... :)
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 03/13] KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port()
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
2026-08-31 21:26 ` [PATCH v3 01/13] KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling David Woodhouse
2026-08-31 21:26 ` [PATCH v3 02/13] KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:22 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 04/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast() David Woodhouse
` (10 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
Rename in preparation for adding a variant that takes a latched bool
argument for use in paths that need a consistent snapshot of the
shinfo mode.
No functional change.
Assisted-by: Kiro:claude-opus-4.6-1m
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index b89c973c2730..be3c4dbee435 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1439,7 +1439,7 @@ static int kvm_xen_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
return kvm_xen_hypercall_set_result(vcpu, run->xen.u.hcall.result);
}
-static inline int max_evtchn_port(struct kvm *kvm)
+static inline int kvm_max_evtchn_port(struct kvm *kvm)
{
if (kvm_xen_has_64bit_shinfo(kvm))
return EVTCHN_2L_NR_CHANNELS;
@@ -1546,7 +1546,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
}
for (i = 0; i < sched_poll.nr_ports; i++) {
- if (ports[i] >= max_evtchn_port(vcpu->kvm)) {
+ if (ports[i] >= kvm_max_evtchn_port(vcpu->kvm)) {
*r = -EINVAL;
goto out;
}
@@ -1833,7 +1833,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
WRITE_ONCE(xe->vcpu_idx, vcpu->vcpu_idx);
}
- if (xe->port >= max_evtchn_port(kvm))
+ if (xe->port >= kvm_max_evtchn_port(kvm))
return -EINVAL;
rc = -EWOULDBLOCK;
@@ -1995,7 +1995,7 @@ int kvm_xen_setup_evtchn(struct kvm *kvm,
struct kvm_vcpu *vcpu;
/*
- * Don't check for the port being within range of max_evtchn_port().
+ * Don't check for the port being within range of kvm_max_evtchn_port().
* Userspace can configure what ever targets it likes; events just won't
* be delivered if/while the target is invalid, just like userspace can
* configure MSIs which target non-existent APICs.
@@ -2004,8 +2004,8 @@ int kvm_xen_setup_evtchn(struct kvm *kvm,
* can be restored *independently* of other things like creating vCPUs,
* without imposing an ordering dependency on userspace. In this
* particular case, the problematic ordering would be with setting the
- * Xen 'long mode' flag, which changes max_evtchn_port() to allow 4096
- * instead of 1024 event channels.
+ * Xen 'long mode' flag, which changes kvm_max_evtchn_port() to allow
+ * 4096 instead of 1024 event channels.
*/
/* We only support 2 level event channels for now */
@@ -2042,7 +2042,7 @@ int kvm_xen_hvm_evtchn_send(struct kvm *kvm, struct kvm_irq_routing_xen_evtchn *
struct kvm_xen_evtchn e;
int ret;
- if (!uxe->port || uxe->port >= max_evtchn_port(kvm))
+ if (!uxe->port || uxe->port >= kvm_max_evtchn_port(kvm))
return -EINVAL;
/* We only support 2 level event channels for now */
@@ -2152,7 +2152,7 @@ static int kvm_xen_eventfd_assign(struct kvm *kvm,
case EVTCHNSTAT_interdomain:
if (data->u.evtchn.deliver.port.port) {
- if (data->u.evtchn.deliver.port.port >= max_evtchn_port(kvm))
+ if (data->u.evtchn.deliver.port.port >= kvm_max_evtchn_port(kvm))
goto out_noeventfd; /* -EINVAL */
} else {
eventfd = eventfd_ctx_fdget(data->u.evtchn.deliver.eventfd.fd);
@@ -2270,7 +2270,7 @@ static int kvm_xen_setattr_evtchn(struct kvm *kvm, struct kvm_xen_hvm_attr *data
if (data->u.evtchn.flags == KVM_XEN_EVTCHN_RESET)
return kvm_xen_eventfd_reset(kvm);
- if (!port || port >= max_evtchn_port(kvm))
+ if (!port || port >= kvm_max_evtchn_port(kvm))
return -EINVAL;
if (data->u.evtchn.flags == KVM_XEN_EVTCHN_DEASSIGN)
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 03/13] KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port()
2026-08-31 21:26 ` [PATCH v3 03/13] KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port() David Woodhouse
@ 2026-09-02 12:22 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:22 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Rename in preparation for adding a variant that takes a latched bool
> argument for use in paths that need a consistent snapshot of the
> shinfo mode.
>
> No functional change.
>
> Assisted-by: Kiro:claude-opus-4.6-1m
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 04/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast()
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (2 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 03/13] KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port() David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:25 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 05/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll() David Woodhouse
` (9 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: Hyunwoo Kim <imv4bel@gmail.com>
kvm_xen_set_evtchn_fast() assumes the port range check in
max_evtchn_port() and the bitmap layout selection observe the same
shinfo mode, but each calls kvm_xen_has_64bit_shinfo() separately.
If the guest changes the mode in between, a port accepted by the
64-bit range check is handled with the 32-bit layout, and
port_word_bit falls outside evtchn_pending_sel.
Latch kvm_xen_has_64bit_shinfo() once on entry so the range check
and both layout computations use the same value.
In practice this is harmless: the evtchn_pending bitmap is at the same
offset in both native and compat shared_info layouts, so a stale mode
just results in setting a bit in what the guest (in its new compat mode)
considers the evtchn_mask, wallclock, or the arch_shared_info fields
which follow it — all of which are in the guest's own page. Even with
this fix, the same corruption can occur if 64-bit mode is latched and
the guest switches to 32-bit mode immediately afterward. Like Xen, KVM
makes no attempt to *convert* when shinfo mode is changed. Only the
wallclock field is updated in the new location.
This fix is for internal consistency rather than correcting any
observable bug.
Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Closes: https://lore.kernel.org/all/aiHPPUk5DY7rH-zL@v4bel/
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
[dwmw2: Rework on top of long_mode/has_64bit_shinfo cleanups]
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index be3c4dbee435..a528fdbf1b94 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1439,14 +1439,19 @@ static int kvm_xen_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
return kvm_xen_hypercall_set_result(vcpu, run->xen.u.hcall.result);
}
-static inline int kvm_max_evtchn_port(struct kvm *kvm)
+static inline int max_evtchn_port(bool has_64bit_shinfo)
{
- if (kvm_xen_has_64bit_shinfo(kvm))
+ if (has_64bit_shinfo)
return EVTCHN_2L_NR_CHANNELS;
else
return COMPAT_EVTCHN_2L_NR_CHANNELS;
}
+static inline int kvm_max_evtchn_port(struct kvm *kvm)
+{
+ return max_evtchn_port(kvm_xen_has_64bit_shinfo(kvm));
+}
+
static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
evtchn_port_t *ports)
{
@@ -1816,8 +1821,9 @@ static void kvm_xen_check_poller(struct kvm_vcpu *vcpu, int port)
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;
- struct kvm_vcpu *vcpu;
+ bool has_64bit_shinfo = kvm_xen_has_64bit_shinfo(kvm);
unsigned long *pending_bits, *mask_bits;
+ struct kvm_vcpu *vcpu;
unsigned long flags;
int port_word_bit;
bool kick_vcpu = false;
@@ -1833,7 +1839,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
WRITE_ONCE(xe->vcpu_idx, vcpu->vcpu_idx);
}
- if (xe->port >= kvm_max_evtchn_port(kvm))
+ if (xe->port >= max_evtchn_port(has_64bit_shinfo))
return -EINVAL;
rc = -EWOULDBLOCK;
@@ -1844,7 +1850,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
if (!kvm_gpc_check(gpc, PAGE_SIZE))
goto out_rcu;
- if (kvm_xen_has_64bit_shinfo(kvm)) {
+ if (has_64bit_shinfo) {
struct shared_info *shinfo = gpc->khva;
pending_bits = (unsigned long *)&shinfo->evtchn_pending;
mask_bits = (unsigned long *)&shinfo->evtchn_mask;
@@ -1885,7 +1891,7 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
goto out_rcu;
}
- if (kvm_xen_has_64bit_shinfo(kvm)) {
+ 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);
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 04/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast()
2026-08-31 21:26 ` [PATCH v3 04/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast() David Woodhouse
@ 2026-09-02 12:25 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:25 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: Hyunwoo Kim <imv4bel@gmail.com>
>
> kvm_xen_set_evtchn_fast() assumes the port range check in
> max_evtchn_port() and the bitmap layout selection observe the same
> shinfo mode, but each calls kvm_xen_has_64bit_shinfo() separately.
> If the guest changes the mode in between, a port accepted by the
> 64-bit range check is handled with the 32-bit layout, and
> port_word_bit falls outside evtchn_pending_sel.
>
> Latch kvm_xen_has_64bit_shinfo() once on entry so the range check
> and both layout computations use the same value.
>
> In practice this is harmless: the evtchn_pending bitmap is at the same
> offset in both native and compat shared_info layouts, so a stale mode
> just results in setting a bit in what the guest (in its new compat mode)
> considers the evtchn_mask, wallclock, or the arch_shared_info fields
> which follow it — all of which are in the guest's own page. Even with
> this fix, the same corruption can occur if 64-bit mode is latched and
> the guest switches to 32-bit mode immediately afterward. Like Xen, KVM
> makes no attempt to *convert* when shinfo mode is changed. Only the
> wallclock field is updated in the new location.
>
> This fix is for internal consistency rather than correcting any
> observable bug.
>
> Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
> Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
> Closes: https://lore.kernel.org/all/aiHPPUk5DY7rH-zL@v4bel/
> Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
> [dwmw2: Rework on top of long_mode/has_64bit_shinfo cleanups]
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 18 ++++++++++++------
> 1 file changed, 12 insertions(+), 6 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 05/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll()
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (3 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 04/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast() David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:27 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 06/13] KVM: x86/xen: Enforce 4-byte alignment of vcpu_info registration David Woodhouse
` (8 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
kvm_xen_schedop_poll() validates port numbers against
kvm_max_evtchn_port() and then calls wait_pending_event() which reads
the shinfo mode again to select the bitmap layout.
Latch kvm_xen_has_64bit_shinfo() once and pass it to both
max_evtchn_port() and wait_pending_event().
As with the previous fix to kvm_xen_set_evtchn_fast(), this is
harmless in practice for the same reasons: the inconsistency can only
corrupt fields in the guest's own shared_info page, and the same
corruption can occur anyway if the mode changes immediately after the
latch.
Fixes: d518b9d0fc80 ("KVM: x86/xen: handle PV spinlocks slowpath")
Assisted-by: Kiro:claude-opus-4.6-1m
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index a528fdbf1b94..5eb23127e74e 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1452,8 +1452,8 @@ static inline int kvm_max_evtchn_port(struct kvm *kvm)
return max_evtchn_port(kvm_xen_has_64bit_shinfo(kvm));
}
-static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
- evtchn_port_t *ports)
+static bool wait_pending_event(struct kvm_vcpu *vcpu, bool has_64bit_shinfo,
+ int nr_ports, evtchn_port_t *ports)
{
struct kvm *kvm = vcpu->kvm;
struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
@@ -1468,7 +1468,7 @@ static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
goto out_rcu;
ret = false;
- if (kvm_xen_has_64bit_shinfo(kvm)) {
+ if (has_64bit_shinfo) {
struct shared_info *shinfo = gpc->khva;
pending_bits = (unsigned long *)&shinfo->evtchn_pending;
} else {
@@ -1493,6 +1493,7 @@ static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
u64 param, u64 *r)
{
+ bool has_64bit_shinfo = kvm_xen_has_64bit_shinfo(vcpu->kvm);
struct sched_poll sched_poll;
evtchn_port_t port, *ports;
struct x86_exception e;
@@ -1551,7 +1552,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
}
for (i = 0; i < sched_poll.nr_ports; i++) {
- if (ports[i] >= kvm_max_evtchn_port(vcpu->kvm)) {
+ if (ports[i] >= max_evtchn_port(has_64bit_shinfo)) {
*r = -EINVAL;
goto out;
}
@@ -1564,7 +1565,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
set_bit(vcpu->vcpu_idx, vcpu->kvm->arch.xen.poll_mask);
- if (!wait_pending_event(vcpu, sched_poll.nr_ports, ports)) {
+ if (!wait_pending_event(vcpu, has_64bit_shinfo, sched_poll.nr_ports, ports)) {
kvm_set_mp_state(vcpu, KVM_MP_STATE_HALTED);
if (sched_poll.timeout)
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 05/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll()
2026-08-31 21:26 ` [PATCH v3 05/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll() David Woodhouse
@ 2026-09-02 12:27 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:27 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> kvm_xen_schedop_poll() validates port numbers against
> kvm_max_evtchn_port() and then calls wait_pending_event() which reads
> the shinfo mode again to select the bitmap layout.
>
> Latch kvm_xen_has_64bit_shinfo() once and pass it to both
> max_evtchn_port() and wait_pending_event().
>
> As with the previous fix to kvm_xen_set_evtchn_fast(), this is
> harmless in practice for the same reasons: the inconsistency can only
> corrupt fields in the guest's own shared_info page, and the same
> corruption can occur anyway if the mode changes immediately after the
> latch.
>
> Fixes: d518b9d0fc80 ("KVM: x86/xen: handle PV spinlocks slowpath")
> Assisted-by: Kiro:claude-opus-4.6-1m
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 06/13] KVM: x86/xen: Enforce 4-byte alignment of vcpu_info registration
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (4 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 05/13] KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll() David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:29 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel David Woodhouse
` (7 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
Xen's map_guest_area() enforces that vcpu_info is aligned to
sizeof(xen_ulong_t). KVM has no such check, allowing a guest to
register vcpu_info at an arbitrary byte alignment.
Enforce unconditional 4-byte alignment regardless of the current
shinfo mode. This is sufficient because subsequent commits ensure
that all locked atomic operations on vcpu_info fields use at most
32-bit accesses. Return -ENXIO on failure, matching Xen's
map_guest_area() behaviour for unaligned requests.
Originally observed in review of an unrelated patch:
https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org/
Cc: stable@vger.kernel.org
Fixes: 73e69a86347a ("KVM: x86/xen: register vcpu info")
Reported-by: sashiko-bot@kernel.org
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 | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 5eb23127e74e..941099ed50c9 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -941,6 +941,10 @@ 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, sizeof(u32)))
+ break;
+
r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_info_cache,
data->u.gpa, sizeof(struct vcpu_info));
} else {
@@ -950,6 +954,10 @@ 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, sizeof(u32)))
+ break;
+
r = kvm_gpc_activate_hva(&vcpu->arch.xen.vcpu_info_cache,
data->u.hva, sizeof(struct vcpu_info));
}
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 06/13] KVM: x86/xen: Enforce 4-byte alignment of vcpu_info registration
2026-08-31 21:26 ` [PATCH v3 06/13] KVM: x86/xen: Enforce 4-byte alignment of vcpu_info registration David Woodhouse
@ 2026-09-02 12:29 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:29 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Xen's map_guest_area() enforces that vcpu_info is aligned to
> sizeof(xen_ulong_t). KVM has no such check, allowing a guest to
> register vcpu_info at an arbitrary byte alignment.
>
> Enforce unconditional 4-byte alignment regardless of the current
> shinfo mode. This is sufficient because subsequent commits ensure
> that all locked atomic operations on vcpu_info fields use at most
> 32-bit accesses. Return -ENXIO on failure, matching Xen's
> map_guest_area() behaviour for unaligned requests.
>
> Originally observed in review of an unrelated patch:
> https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org/
>
> Cc: stable@vger.kernel.org
> Fixes: 73e69a86347a ("KVM: x86/xen: register vcpu info")
> Reported-by: sashiko-bot@kernel.org
> 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 | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (5 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 06/13] KVM: x86/xen: Enforce 4-byte alignment of vcpu_info registration David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-08-31 22:50 ` sashiko-bot
2026-09-02 12:33 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 08/13] KVM: x86/xen: Use 32-bit atomics if vCPU's evtchn_pending_sel isn't aligned David Woodhouse
` (6 subsequent siblings)
13 siblings, 2 replies; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
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, and the address of the per-vCPU info is guest-controlled and
only required to be 32-bit aligned, so an 8-byte access can generate a
split-lock #AC exception.
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.
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 guaranteed to be 64-bit aligned.
Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Assisted-by: Claude:claude-mythos-5
---
arch/x86/kvm/xen.c | 47 ++++++++++++++++++++++++++++++++--------------
1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 941099ed50c9..aa49b45dd8dc 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1831,7 +1831,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;
@@ -1864,11 +1864,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);
}
/*
@@ -1884,6 +1891,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);
@@ -1900,19 +1909,29 @@ 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 a 32-bit btsl instead of test_and_set_bit(),
+ * which would use btsq on x86-64. The vcpu_info is guest-
+ * controlled and only required to be 32-bit aligned, so a
+ * 64-bit access could generate a split-lock #AC.
+ *
+ * Note, this does not apply to the test_and_set_bit() on
+ * pending_bits above: that is in the per-VM shared_info, which
+ * is page aligned, so the access is guaranteed to be 64-bit
+ * aligned.
+ */
+ 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.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
2026-08-31 21:26 ` [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel David Woodhouse
@ 2026-08-31 22:50 ` sashiko-bot
2026-08-31 23:18 ` David Woodhouse
2026-09-02 12:33 ` Paul Durrant
1 sibling, 1 reply; 38+ messages in thread
From: sashiko-bot @ 2026-08-31 22:50 UTC (permalink / raw)
To: David Woodhouse; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing dirty page logging for event channel injection breaks live migration.
--
commit 71bb4c7ed046d44bbf5b561e00bbc1a82294213c
Author: David Woodhouse <dwmw@amazon.co.uk>
Subject: KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
This commit replaces a 64-bit locked test-and-set with a 32-bit equivalent
for updating evtchn_pending_sel. This prevents a split-lock exception when
accessing a guest-controlled structure that is only 32-bit aligned.
Closes: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org
> diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
> --- a/arch/x86/kvm/xen.c
> +++ b/arch/x86/kvm/xen.c
[ ... ]
> @@ -1879,19 +1888,29 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe, struct kvm *kvm)
> goto out_rcu;
> }
>
> - if (has_64bit_shinfo) {
[ ... ]
> - } else {
[ ... ]
> - }
> + /*
> + * Explicitly use a 32-bit btsl instead of test_and_set_bit(),
> + * which would use btsq on x86-64. The vcpu_info is guest-
> + * controlled and only required to be 32-bit aligned, so a
> + * 64-bit access could generate a split-lock #AC.
> + *
> + * Note, this does not apply to the test_and_set_bit() on
> + * pending_bits above: that is in the per-VM shared_info, which
> + * is page aligned, so the access is guaranteed to be 64-bit
> + * aligned.
> + */
> + 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;
> }
[Severity: High]
This isn't a bug introduced by this patch, but is it possible that modifying
the guest memory here without dirtying the page breaks live migration?
Looking at kvm_xen_set_evtchn_fast(), it modifies both the shared_info
page (via test_and_set_bit on pending_bits earlier in the function) and
the vcpu_info page (via the new btsl inline asm on gpc->khva here).
Because gpc->khva uses the cached kernel address and bypasses guest page
tables, hardware A/D bits are not set.
If we don't call kvm_gpc_mark_dirty_in_slot(gpc) after modifying these
pages, KVM's dirty page tracking mechanism won't record the changes.
During the pre-copy phase of live migration, could this cause userspace to
skip re-transmitting the page, resulting in the destination VM resuming
with an outdated copy of the shared_info and vcpu_info pages where the
pending interrupt bits are missing?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831213632.81023-1-dwmw2@infradead.org?part=7
^ permalink raw reply [flat|nested] 38+ messages in thread* Re: [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
2026-08-31 22:50 ` sashiko-bot
@ 2026-08-31 23:18 ` David Woodhouse
0 siblings, 0 replies; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 23:18 UTC (permalink / raw)
To: sashiko-reviews; +Cc: kvm
[-- Attachment #1: Type: text/plain, Size: 1526 bytes --]
On Mon, 2026-08-31 at 22:50 +0000, sashiko-bot@kernel.org wrote:
>
> [Severity: High]
> This isn't a bug introduced by this patch, but is it possible that modifying
> the guest memory here without dirtying the page breaks live migration?
>
> Looking at kvm_xen_set_evtchn_fast(), it modifies both the shared_info
> page (via test_and_set_bit on pending_bits earlier in the function) and
> the vcpu_info page (via the new btsl inline asm on gpc->khva here).
>
> Because gpc->khva uses the cached kernel address and bypasses guest page
> tables, hardware A/D bits are not set.
>
> If we don't call kvm_gpc_mark_dirty_in_slot(gpc) after modifying these
> pages, KVM's dirty page tracking mechanism won't record the changes.
>
> During the pre-copy phase of live migration, could this cause userspace to
> skip re-transmitting the page, resulting in the destination VM resuming
> with an outdated copy of the shared_info and vcpu_info pages where the
> pending interrupt bits are missing?
No, the shared_info and vcpu_info are explicitly documented as not
being dirty tracked.
KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO
Sets the guest physical address of the vcpu_info for a given vCPU.
As with the shared_info page for the VM, the corresponding page may be
dirtied at any time if event channel interrupt delivery is enabled, so
userspace should always assume that the page is dirty without relying
on dirty logging. Setting the gpa to KVM_XEN_INVALID_GPA will disable
the vcpu_info.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
2026-08-31 21:26 ` [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel David Woodhouse
2026-08-31 22:50 ` sashiko-bot
@ 2026-09-02 12:33 ` Paul Durrant
1 sibling, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:33 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, 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, and the address of the per-vCPU info is guest-controlled and
> only required to be 32-bit aligned, so an 8-byte access can generate a
> split-lock #AC exception.
>
> 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.
>
> 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 guaranteed to be 64-bit aligned.
>
> Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
> Reported-by: sashiko-bot@kernel.org
> Closes: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> Assisted-by: Claude:claude-mythos-5
> ---
> arch/x86/kvm/xen.c | 47 ++++++++++++++++++++++++++++++++--------------
> 1 file changed, 33 insertions(+), 14 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 08/13] KVM: x86/xen: Use 32-bit atomics if vCPU's evtchn_pending_sel isn't aligned
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (6 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 07/13] KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:38 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents David Woodhouse
` (5 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: Sean Christopherson <seanjc@google.com>
When propagating pending Xen events from KVM's "cache" to the guest-visible
structure, use two 32-bit atomic operations to do the bitwise-OR into the
guest-controlled structure if the structure isn't 64-bit aligned, i.e. if
the guest registered its vcpu_info in 32-bit mode and then switched to
64-bit mode, in which case using a 64-bit atomic OR will generate a
split-lock #AC (if enabled).
Opportunistically isolate the clearing of the bits from KVM's cache, as
that structure is KVM-controlled, i.e. is guaranteed to be 64-bit aligned.
This will allow dropping the open-coded inline asm blobs in the future.
[dwmw2: Cast to u64 before shifting; evtchn_pending_sel is unsigned long,
so >> 32 is undefined on 32-bit even though the branch is
unreachable there]
Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202608071502.rYOi3Pg8-lkp@intel.com/
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index aa49b45dd8dc..b0fa74f2cbee 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -679,13 +679,28 @@ void kvm_xen_inject_pending_events(struct kvm_vcpu *v)
if (kvm_xen_has_64bit_shinfo(v->kvm)) {
struct vcpu_info *vi = gpc->khva;
- asm volatile(LOCK_PREFIX "orq %0, %1\n"
- "notq %0\n"
- LOCK_PREFIX "andq %0, %2\n"
- : "=r" (evtchn_pending_sel),
- "+m" (vi->evtchn_pending_sel),
- "+m" (v->arch.xen.evtchn_pending_sel)
- : "0" (evtchn_pending_sel));
+ if (IS_ALIGNED((unsigned long)&vi->evtchn_pending_sel, sizeof(u64)))
+ asm volatile(LOCK_PREFIX "orq %[src], %[dst]\n"
+ : [dst] "+m" (vi->evtchn_pending_sel)
+ : [src] "r" (evtchn_pending_sel));
+ else
+ /*
+ * The cast keeps the shift well-defined on 32-bit,
+ * where evtchn_pending_sel is 32 bits wide and this
+ * branch is unreachable anyway (this is inside
+ * kvm_xen_has_64bit_shinfo(), which is gated on
+ * IS_ENABLED(CONFIG_64BIT)).
+ */
+ asm volatile(LOCK_PREFIX "orl %[src_lo], %[dst_lo]\n"
+ LOCK_PREFIX "orl %[src_hi], %[dst_hi]\n"
+ : [dst_lo] "+m" (vi->evtchn_pending_sel),
+ [dst_hi] "+m" (*(((u32 *)&vi->evtchn_pending_sel) + 1))
+ : [src_lo] "r" ((u32)evtchn_pending_sel),
+ [src_hi] "r" ((u32)((u64)evtchn_pending_sel >> 32)));
+
+ asm volatile(LOCK_PREFIX "andq %1, %0\n"
+ : "+m" (v->arch.xen.evtchn_pending_sel)
+ : "r" (~evtchn_pending_sel));
WRITE_ONCE(vi->evtchn_upcall_pending, 1);
} else {
u32 evtchn_pending_sel32 = evtchn_pending_sel;
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 08/13] KVM: x86/xen: Use 32-bit atomics if vCPU's evtchn_pending_sel isn't aligned
2026-08-31 21:26 ` [PATCH v3 08/13] KVM: x86/xen: Use 32-bit atomics if vCPU's evtchn_pending_sel isn't aligned David Woodhouse
@ 2026-09-02 12:38 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:38 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: Sean Christopherson <seanjc@google.com>
>
> When propagating pending Xen events from KVM's "cache" to the guest-visible
> structure, use two 32-bit atomic operations to do the bitwise-OR into the
> guest-controlled structure if the structure isn't 64-bit aligned, i.e. if
> the guest registered its vcpu_info in 32-bit mode and then switched to
> 64-bit mode, in which case using a 64-bit atomic OR will generate a
> split-lock #AC (if enabled).
>
> Opportunistically isolate the clearing of the bits from KVM's cache, as
> that structure is KVM-controlled, i.e. is guaranteed to be 64-bit aligned.
> This will allow dropping the open-coded inline asm blobs in the future.
>
> [dwmw2: Cast to u64 before shifting; evtchn_pending_sel is unsigned long,
> so >> 32 is undefined on 32-bit even though the branch is
> unreachable there]
>
> Fixes: 14243b387137 ("KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery")
> Reported-by: sashiko-bot@kernel.org
> Closes: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202608071502.rYOi3Pg8-lkp@intel.com/
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 29 ++++++++++++++++++++++-------
> 1 file changed, 22 insertions(+), 7 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (7 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 08/13] KVM: x86/xen: Use 32-bit atomics if vCPU's evtchn_pending_sel isn't aligned David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:41 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 10/13] KVM: x86/xen: Take kvm->srcu in __kvm_xen_has_interrupt() David Woodhouse
` (4 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: Sean Christopherson <seanjc@google.com>
Replace the open coded atomic asm blobs in the Xen event injection code
with equivalent atomic{,64}_xxx() operations. Casting the event channel
to atomic types is ugly, but not as ugly as asm blobs.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 35 ++++++++++++-----------------------
1 file changed, 12 insertions(+), 23 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index b0fa74f2cbee..f8730ee48ab8 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -678,12 +678,12 @@ void kvm_xen_inject_pending_events(struct kvm_vcpu *v)
/* Now gpc->khva is a valid kernel address for the vcpu_info */
if (kvm_xen_has_64bit_shinfo(v->kvm)) {
struct vcpu_info *vi = gpc->khva;
+ void *vi_pending_sel = &vi->evtchn_pending_sel;
- if (IS_ALIGNED((unsigned long)&vi->evtchn_pending_sel, sizeof(u64)))
- asm volatile(LOCK_PREFIX "orq %[src], %[dst]\n"
- : [dst] "+m" (vi->evtchn_pending_sel)
- : [src] "r" (evtchn_pending_sel));
- else
+ if (IS_ALIGNED((unsigned long)vi_pending_sel, sizeof(u64))) {
+ atomic64_or(evtchn_pending_sel, vi_pending_sel);
+ } else {
+ atomic_or(evtchn_pending_sel, vi_pending_sel);
/*
* The cast keeps the shift well-defined on 32-bit,
* where evtchn_pending_sel is 32 bits wide and this
@@ -691,28 +691,17 @@ void kvm_xen_inject_pending_events(struct kvm_vcpu *v)
* kvm_xen_has_64bit_shinfo(), which is gated on
* IS_ENABLED(CONFIG_64BIT)).
*/
- asm volatile(LOCK_PREFIX "orl %[src_lo], %[dst_lo]\n"
- LOCK_PREFIX "orl %[src_hi], %[dst_hi]\n"
- : [dst_lo] "+m" (vi->evtchn_pending_sel),
- [dst_hi] "+m" (*(((u32 *)&vi->evtchn_pending_sel) + 1))
- : [src_lo] "r" ((u32)evtchn_pending_sel),
- [src_hi] "r" ((u32)((u64)evtchn_pending_sel >> 32)));
-
- asm volatile(LOCK_PREFIX "andq %1, %0\n"
- : "+m" (v->arch.xen.evtchn_pending_sel)
- : "r" (~evtchn_pending_sel));
+ atomic_or((u64)evtchn_pending_sel >> 32,
+ vi_pending_sel + 4);
+ }
+
+ atomic64_andnot(evtchn_pending_sel, (void *)&v->arch.xen.evtchn_pending_sel);
WRITE_ONCE(vi->evtchn_upcall_pending, 1);
} else {
- u32 evtchn_pending_sel32 = evtchn_pending_sel;
struct compat_vcpu_info *vi = gpc->khva;
- asm volatile(LOCK_PREFIX "orl %0, %1\n"
- "notl %0\n"
- LOCK_PREFIX "andl %0, %2\n"
- : "=r" (evtchn_pending_sel32),
- "+m" (vi->evtchn_pending_sel),
- "+m" (v->arch.xen.evtchn_pending_sel)
- : "0" (evtchn_pending_sel32));
+ atomic_or(evtchn_pending_sel, (void *)&vi->evtchn_pending_sel);
+ atomic_andnot(evtchn_pending_sel, (void *)&v->arch.xen.evtchn_pending_sel);
WRITE_ONCE(vi->evtchn_upcall_pending, 1);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents
2026-08-31 21:26 ` [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents David Woodhouse
@ 2026-09-02 12:41 ` Paul Durrant
2026-09-02 18:32 ` David Woodhouse
0 siblings, 1 reply; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:41 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: Sean Christopherson <seanjc@google.com>
>
> Replace the open coded atomic asm blobs in the Xen event injection code
> with equivalent atomic{,64}_xxx() operations. Casting the event channel
> to atomic types is ugly, but not as ugly as asm blobs.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 35 ++++++++++++-----------------------
> 1 file changed, 12 insertions(+), 23 deletions(-)
>
Not entirely clear why going to the trouble of replacing the asm blobs
in patch 8 was necessary only to remove them here but, if that's
preferable to squashing this into patch 8...
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread* Re: [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents
2026-09-02 12:41 ` Paul Durrant
@ 2026-09-02 18:32 ` David Woodhouse
2026-09-02 18:59 ` Sean Christopherson
0 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-09-02 18:32 UTC (permalink / raw)
To: Paul Durrant, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
[-- Attachment #1: Type: text/plain, Size: 1140 bytes --]
On Wed, 2026-09-02 at 13:41 +0100, Paul Durrant wrote:
> On 31/08/2026 22:26, David Woodhouse wrote:
> > From: Sean Christopherson <seanjc@google.com>
> >
> > Replace the open coded atomic asm blobs in the Xen event injection code
> > with equivalent atomic{,64}_xxx() operations. Casting the event channel
> > to atomic types is ugly, but not as ugly as asm blobs.
> >
> > No functional change intended.
> >
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> > ---
> > arch/x86/kvm/xen.c | 35 ++++++++++++-----------------------
> > 1 file changed, 12 insertions(+), 23 deletions(-)
> >
> Not entirely clear why going to the trouble of replacing the asm blobs
> in patch 8 was necessary only to remove them here but, if that's
> preferable to squashing this into patch 8...
I think Sean's logic in doing it that way is that *this* patch can be
marked 'No functional change intended' as it's merely changing *how*
the atomic access is done, while the previous patch actually changes
the pattern of *which* atomic accesses are done.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread* Re: [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents
2026-09-02 18:32 ` David Woodhouse
@ 2026-09-02 18:59 ` Sean Christopherson
0 siblings, 0 replies; 38+ messages in thread
From: Sean Christopherson @ 2026-09-02 18:59 UTC (permalink / raw)
To: David Woodhouse
Cc: Paul Durrant, pbonzini, joao.m.martins, boris.ostrovsky,
ankur.a.arora, tglx, mingo, bp, dave.hansen, hpa, x86,
syzbot+208f7f3e5f59c11aeb90, syzkaller-bugs, suryasaimadhu369,
lkp, nicoyip.dev, frn1furkan10, kvm, linux-kernel, imv4bel
On Wed, Sep 02, 2026, David Woodhouse wrote:
> On Wed, 2026-09-02 at 13:41 +0100, Paul Durrant wrote:
> > On 31/08/2026 22:26, David Woodhouse wrote:
> > > From: Sean Christopherson <seanjc@google.com>
> > >
> > > Replace the open coded atomic asm blobs in the Xen event injection code
> > > with equivalent atomic{,64}_xxx() operations. Casting the event channel
> > > to atomic types is ugly, but not as ugly as asm blobs.
> > >
> > > No functional change intended.
> > >
> > > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> > > ---
> > > arch/x86/kvm/xen.c | 35 ++++++++++++-----------------------
> > > 1 file changed, 12 insertions(+), 23 deletions(-)
> > >
> > Not entirely clear why going to the trouble of replacing the asm blobs
> > in patch 8 was necessary only to remove them here but, if that's
> > preferable to squashing this into patch 8...
>
> I think Sean's logic in doing it that way is that *this* patch can be
> marked 'No functional change intended' as it's merely changing *how*
> the atomic access is done, while the previous patch actually changes
> the pattern of *which* atomic accesses are done.
Yep, exactly.
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 10/13] KVM: x86/xen: Take kvm->srcu in __kvm_xen_has_interrupt()
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (8 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 09/13] KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:43 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 11/13] KVM: x86/xen: Mark poll_evtchn accesses with READ_ONCE()/WRITE_ONCE() David Woodhouse
` (3 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
kvm_gpc_check() checks the cached memslot generation against the current
one, which dereferences kvm->memslots and therefore requires kvm->srcu to
be held. __kvm_xen_has_interrupt() does not take it.
Most callers do happen to hold kvm->srcu, but not all of them:
- kvm_emulate_halt() on the VM-Exit path, via kvm_vcpu_has_events() and
kvm_cpu_has_extint(). vcpu_enter_guest() drops the vCPU's SRCU lock
before entering the guest, so it is not held on the way back out.
- kvm_vcpu_block() -> kvm_vcpu_check_block() -> kvm_arch_vcpu_runnable(),
which is the case the existing comment in this function describes.
On a PROVE_RCU kernel the former produces:
WARNING: suspicious RCU usage
include/linux/kvm_host.h:1092 suspicious rcu_dereference_check() usage!
...
kvm_gpc_check+0x344/0x3e0 [kvm]
__kvm_xen_has_interrupt+0x83/0x310 [kvm]
kvm_cpu_has_extint+0x1ff/0x370 [kvm]
kvm_cpu_has_interrupt+0x16/0x100 [kvm]
kvm_vcpu_has_events+0x4ce/0x690 [kvm]
kvm_emulate_halt+0x52/0x1f0 [kvm]
vmx_vcpu_run+0x988/0x2630 [kvm_intel]
Use guard(srcu) so that the three existing early returns don't each need
an explicit unlock. SRCU read sections nest, so this is harmless on the
paths which already hold it, and srcu_read_lock() does not sleep, so it
is also safe in the atomic case which this function already handles.
Fixes: 7caf9571563e ("KVM: x86/xen: Use gfn_to_pfn_cache for vcpu_info")
Cc: stable@vger.kernel.org
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Assisted-by: Claude:claude-mythos-5
---
arch/x86/kvm/xen.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index f8730ee48ab8..871cbaf8b68d 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -732,6 +732,16 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
BUILD_BUG_ON(sizeof(rc) !=
sizeof_field(struct compat_vcpu_info, evtchn_upcall_pending));
+ /*
+ * kvm_gpc_check() checks the memslot generation, so kvm->srcu must be
+ * held. Most callers hold it already, but this is also reached from
+ * kvm_emulate_halt() on the VM-Exit path and from kvm_vcpu_block(),
+ * where vcpu_enter_guest() has already dropped the vCPU's SRCU lock.
+ * Taking SRCU does not sleep, so it is safe even in the atomic case
+ * which is handled below.
+ */
+ guard(srcu)(&v->kvm->srcu);
+
read_lock_irqsave(&gpc->lock, flags);
while (!kvm_gpc_check(gpc, sizeof(struct vcpu_info))) {
read_unlock_irqrestore(&gpc->lock, flags);
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 10/13] KVM: x86/xen: Take kvm->srcu in __kvm_xen_has_interrupt()
2026-08-31 21:26 ` [PATCH v3 10/13] KVM: x86/xen: Take kvm->srcu in __kvm_xen_has_interrupt() David Woodhouse
@ 2026-09-02 12:43 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:43 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> kvm_gpc_check() checks the cached memslot generation against the current
> one, which dereferences kvm->memslots and therefore requires kvm->srcu to
> be held. __kvm_xen_has_interrupt() does not take it.
>
> Most callers do happen to hold kvm->srcu, but not all of them:
>
> - kvm_emulate_halt() on the VM-Exit path, via kvm_vcpu_has_events() and
> kvm_cpu_has_extint(). vcpu_enter_guest() drops the vCPU's SRCU lock
> before entering the guest, so it is not held on the way back out.
>
> - kvm_vcpu_block() -> kvm_vcpu_check_block() -> kvm_arch_vcpu_runnable(),
> which is the case the existing comment in this function describes.
>
> On a PROVE_RCU kernel the former produces:
>
> WARNING: suspicious RCU usage
> include/linux/kvm_host.h:1092 suspicious rcu_dereference_check() usage!
> ...
> kvm_gpc_check+0x344/0x3e0 [kvm]
> __kvm_xen_has_interrupt+0x83/0x310 [kvm]
> kvm_cpu_has_extint+0x1ff/0x370 [kvm]
> kvm_cpu_has_interrupt+0x16/0x100 [kvm]
> kvm_vcpu_has_events+0x4ce/0x690 [kvm]
> kvm_emulate_halt+0x52/0x1f0 [kvm]
> vmx_vcpu_run+0x988/0x2630 [kvm_intel]
>
> Use guard(srcu) so that the three existing early returns don't each need
> an explicit unlock. SRCU read sections nest, so this is harmless on the
> paths which already hold it, and srcu_read_lock() does not sleep, so it
> is also safe in the atomic case which this function already handles.
>
> Fixes: 7caf9571563e ("KVM: x86/xen: Use gfn_to_pfn_cache for vcpu_info")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> Assisted-by: Claude:claude-mythos-5
> ---
> arch/x86/kvm/xen.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 11/13] KVM: x86/xen: Mark poll_evtchn accesses with READ_ONCE()/WRITE_ONCE()
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (9 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 10/13] KVM: x86/xen: Take kvm->srcu in __kvm_xen_has_interrupt() David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:45 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 12/13] KVM: pfncache: use a dedicated invalidation sequence for cache refresh David Woodhouse
` (2 subsequent siblings)
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: Chengfeng Ye <nicoyip.dev@gmail.com>
Use READ_ONCE() and WRITE_ONCE() for runtime accesses to poll_evtchn.
This marks the intentionally concurrent scalar accesses and prevents the
compiler from splitting, merging, or inventing accesses.
kvm_xen_schedop_poll() publishes the single port, or -1 for multiple
ports, before setting poll_mask and halting the vCPU. Event delivery can
call kvm_xen_check_poller() on another CPU while the vCPU thread publishes
that value or resets the field to zero after returning from
kvm_vcpu_halt():
vCPU thread event delivery thread
----------- ---------------------
poll_evtchn = port
set_bit(poll_mask)
kvm_vcpu_halt()
poll_evtchn = READ
poll_evtchn = 0
clear_bit(poll_mask)
The plain read and writes therefore race. KCSAN reported:
BUG: KCSAN: data-race in kvm_xen_hypercall / kvm_xen_set_evtchn_fast
read to 0xffff888112f55af0 of 4 bytes by task 98:
kvm_xen_set_evtchn_fast+0x204/0x7c0
kvm_xen_hvm_evtchn_send+0xab/0x100
kvm_arch_vm_ioctl+0xb31/0xd90
kvm_vm_ioctl+0xf42/0x16c0
write to 0xffff888112f55af0 of 4 bytes by task 96:
kvm_xen_hypercall+0xd8d/0xf50
kvm_emulate_hypercall+0x157/0x1d0
vmx_handle_exit+0x40f/0xae0
vcpu_run+0x137f/0x27d0
kvm_arch_vcpu_ioctl_run+0x5a5/0x970
The field is an aligned int on x86. Access annotations preserve the
existing matching, callback, and poll-mask control flow while making the
single-copy access requirement explicit.
Fixes: 1a65105a5aba ("KVM: x86/xen: handle PV spinlocks slowpath")
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/xen.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 871cbaf8b68d..d15c62ad7932 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1581,9 +1581,9 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
}
if (sched_poll.nr_ports == 1)
- vcpu->arch.xen.poll_evtchn = port;
+ WRITE_ONCE(vcpu->arch.xen.poll_evtchn, port);
else
- vcpu->arch.xen.poll_evtchn = -1;
+ WRITE_ONCE(vcpu->arch.xen.poll_evtchn, -1);
set_bit(vcpu->vcpu_idx, vcpu->kvm->arch.xen.poll_mask);
@@ -1602,7 +1602,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);
}
- vcpu->arch.xen.poll_evtchn = 0;
+ WRITE_ONCE(vcpu->arch.xen.poll_evtchn, 0);
*r = 0;
out:
/* Really, this is only needed in case of timeout */
@@ -1822,7 +1822,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
static void kvm_xen_check_poller(struct kvm_vcpu *vcpu, int port)
{
- int poll_evtchn = vcpu->arch.xen.poll_evtchn;
+ int poll_evtchn = READ_ONCE(vcpu->arch.xen.poll_evtchn);
if ((poll_evtchn == port || poll_evtchn == -1) &&
test_and_clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.xen.poll_mask)) {
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 11/13] KVM: x86/xen: Mark poll_evtchn accesses with READ_ONCE()/WRITE_ONCE()
2026-08-31 21:26 ` [PATCH v3 11/13] KVM: x86/xen: Mark poll_evtchn accesses with READ_ONCE()/WRITE_ONCE() David Woodhouse
@ 2026-09-02 12:45 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:45 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: Chengfeng Ye <nicoyip.dev@gmail.com>
>
> Use READ_ONCE() and WRITE_ONCE() for runtime accesses to poll_evtchn.
> This marks the intentionally concurrent scalar accesses and prevents the
> compiler from splitting, merging, or inventing accesses.
>
> kvm_xen_schedop_poll() publishes the single port, or -1 for multiple
> ports, before setting poll_mask and halting the vCPU. Event delivery can
> call kvm_xen_check_poller() on another CPU while the vCPU thread publishes
> that value or resets the field to zero after returning from
> kvm_vcpu_halt():
>
> vCPU thread event delivery thread
> ----------- ---------------------
> poll_evtchn = port
> set_bit(poll_mask)
> kvm_vcpu_halt()
> poll_evtchn = READ
> poll_evtchn = 0
> clear_bit(poll_mask)
>
> The plain read and writes therefore race. KCSAN reported:
>
> BUG: KCSAN: data-race in kvm_xen_hypercall / kvm_xen_set_evtchn_fast
>
> read to 0xffff888112f55af0 of 4 bytes by task 98:
> kvm_xen_set_evtchn_fast+0x204/0x7c0
> kvm_xen_hvm_evtchn_send+0xab/0x100
> kvm_arch_vm_ioctl+0xb31/0xd90
> kvm_vm_ioctl+0xf42/0x16c0
>
> write to 0xffff888112f55af0 of 4 bytes by task 96:
> kvm_xen_hypercall+0xd8d/0xf50
> kvm_emulate_hypercall+0x157/0x1d0
> vmx_handle_exit+0x40f/0xae0
> vcpu_run+0x137f/0x27d0
> kvm_arch_vcpu_ioctl_run+0x5a5/0x970
>
> The field is an aligned int on x86. Access annotations preserve the
> existing matching, callback, and poll-mask control flow while making the
> single-copy access requirement explicit.
>
> Fixes: 1a65105a5aba ("KVM: x86/xen: handle PV spinlocks slowpath")
> Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/xen.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 12/13] KVM: pfncache: use a dedicated invalidation sequence for cache refresh
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (10 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 11/13] KVM: x86/xen: Mark poll_evtchn accesses with READ_ONCE()/WRITE_ONCE() David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-09-02 12:14 ` Paul Durrant
2026-08-31 21:26 ` [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray David Woodhouse
2026-09-04 15:37 ` [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup Paolo Bonzini
13 siblings, 1 reply; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: David Woodhouse <dwmw@amazon.co.uk>
The gfn_to_pfn_cache refresh path guards against mmu notifier
invalidations which complete while it has dropped gpc->lock for the
HVA->PFN lookup: hva_to_pfn_retry() samples kvm->mmu_invalidate_seq
and retries if it changed, or if mn_active_invalidate_count is still
elevated.
That is insufficient for HVA-based caches. mmu_invalidate_seq is only
advanced by kvm_mmu_invalidate_end() when the invalidated range
overlaps a memslot, and an HVA-based cache (e.g. the Xen shared_info
page mapped with KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA) need not be backed
by any memslot at all. An invalidation of the cached HVA which starts
and ends entirely within the lookup window is thus invisible to the
retry check: mn_active_invalidate_count is back to zero and the
sequence never moved. The refresh then publishes a mapping of a page
which has already been freed, and the next reader dereferences it:
BUG: KASAN: use-after-free in kvm_xen_shared_info_init+0x3c6/0x440
Read of size 4 at addr ffff8880599c2900 by task syz.2.383/7257
Since gfn_to_pfn_cache_invalidate_start() deliberately skips caches
which are not currently valid (including one whose refresh is in
progress, as the refresh clears the valid flag before dropping the
lock), the retry check is the only line of defence, and it must fire
for *any* invalidation, not just those hitting a memslot.
Add a dedicated kvm->gpc_invalidate_seq, incremented by every
kvm_mmu_notifier_invalidate_range_end() under mn_invalidate_lock
before mn_active_invalidate_count is decremented, and check it in
hva_to_pfn_retry() instead of mmu_invalidate_seq. Incrementing in
range_end() in the same critical section as the in-progress count
also closes the variant where the cache is activated with the
contested HVA only after invalidate_range_start() has run.
The same bug is also reachable through the per-vCPU vcpu_info cache
(KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA), where the stale mapping is
then dereferenced by kvm_setup_guest_pvclock() on the next KVM_RUN:
BUG: KASAN: use-after-free in kvm_setup_guest_pvclock+0x5bf/0x660
This intentionally makes refresh retry on *unrelated* mmu notifier
events; restoring precision (and reworking the GPC locking more
generally) is left for a subsequent series.
Reproducers: https://david.woodhou.se/xen_shinfo_race.c
https://david.woodhou.se/vcpu_info_race.c
Suggested-by: Sean Christopherson <seanjc@google.com>
Reported-by: syzbot+0948c82180d475ad24e2@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a0c5f2c.a00a0220.2c7954.0000.GAE@google.com/
Tested-by: syzbot+0948c82180d475ad24e2@syzkaller.appspotmail.com
Reported-by: syzbot+fb7c2dd166d3ea63df2a@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a426dd2.854d4ab9.360e1d.0008.GAE@google.com/
Fixes: b9220d32799a ("KVM: x86/xen: allow shared_info to be mapped by fixed HVA")
Cc: stable@vger.kernel.org
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Assisted-by: Claude:claude-mythos-5
---
include/linux/kvm_host.h | 2 ++
virt/kvm/kvm_main.c | 10 ++++++++++
virt/kvm/pfncache.c | 18 +++++++++---------
3 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 03bfc92864b6..3dd04605f2e5 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -855,6 +855,8 @@ struct kvm {
gfn_t mmu_invalidate_range_start;
gfn_t mmu_invalidate_range_end;
+ unsigned long gpc_invalidate_seq;
+
struct list_head devices;
u64 manual_dirty_log_protect;
struct dentry *debugfs_dentry;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 65eb26a0520d..108d42c5c1d6 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -813,6 +813,16 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
/* Pairs with the increment in range_start(). */
spin_lock(&kvm->mn_invalidate_lock);
+ kvm->gpc_invalidate_seq++;
+
+ /*
+ * As with the MMU sequence counter and mmu_invalidate_in_progress, the
+ * GPC sequence increase must be visible before the invalidate count
+ * goes to zero. Pairs with the smp_rmb() in
+ * mmu_notifier_retry_cache().
+ */
+ smp_wmb();
+
if (!WARN_ON_ONCE(!kvm->mn_active_invalidate_count))
--kvm->mn_active_invalidate_count;
wake = !kvm->mn_active_invalidate_count;
diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c
index 728d2c1b488a..3659686b97c2 100644
--- a/virt/kvm/pfncache.c
+++ b/virt/kvm/pfncache.c
@@ -124,7 +124,7 @@ static void gpc_unmap(kvm_pfn_t pfn, void *khva)
#endif
}
-static inline bool mmu_notifier_retry_cache(struct kvm *kvm, unsigned long mmu_seq)
+static inline bool mmu_notifier_retry_cache(struct kvm *kvm, unsigned long gpc_seq)
{
/*
* mn_active_invalidate_count acts for all intents and purposes
@@ -136,20 +136,20 @@ static inline bool mmu_notifier_retry_cache(struct kvm *kvm, unsigned long mmu_s
* Note, it does not matter that mn_active_invalidate_count
* is not protected by gpc->lock. It is guaranteed to
* be elevated before the mmu_notifier acquires gpc->lock, and
- * isn't dropped until after mmu_invalidate_seq is updated.
+ * isn't dropped until after gpc_invalidate_seq is updated.
*/
if (kvm->mn_active_invalidate_count)
return true;
/*
* Ensure mn_active_invalidate_count is read before
- * mmu_invalidate_seq. This pairs with the smp_wmb() in
- * mmu_notifier_invalidate_range_end() to guarantee either the
+ * gpc_invalidate_seq. This pairs with the smp_wmb() in
+ * kvm_mmu_notifier_invalidate_range_end() to guarantee either the
* old (non-zero) value of mn_active_invalidate_count or the
- * new (incremented) value of mmu_invalidate_seq is observed.
+ * new (incremented) value of gpc_invalidate_seq is observed.
*/
smp_rmb();
- return kvm->mmu_invalidate_seq != mmu_seq;
+ return kvm->gpc_invalidate_seq != gpc_seq;
}
static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
@@ -158,7 +158,7 @@ static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
void *old_khva = (void *)PAGE_ALIGN_DOWN((uintptr_t)gpc->khva);
kvm_pfn_t new_pfn = KVM_PFN_ERR_FAULT;
void *new_khva = NULL;
- unsigned long mmu_seq;
+ unsigned long gpc_seq;
struct page *page;
struct kvm_follow_pfn kfp = {
@@ -181,7 +181,7 @@ static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
gpc->valid = false;
do {
- mmu_seq = gpc->kvm->mmu_invalidate_seq;
+ gpc_seq = gpc->kvm->gpc_invalidate_seq;
smp_rmb();
write_unlock_irq(&gpc->lock);
@@ -232,7 +232,7 @@ static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
* attempting to refresh.
*/
WARN_ON_ONCE(gpc->valid);
- } while (mmu_notifier_retry_cache(gpc->kvm, mmu_seq));
+ } while (mmu_notifier_retry_cache(gpc->kvm, gpc_seq));
gpc->valid = true;
gpc->pfn = new_pfn;
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 12/13] KVM: pfncache: use a dedicated invalidation sequence for cache refresh
2026-08-31 21:26 ` [PATCH v3 12/13] KVM: pfncache: use a dedicated invalidation sequence for cache refresh David Woodhouse
@ 2026-09-02 12:14 ` Paul Durrant
0 siblings, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:14 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> The gfn_to_pfn_cache refresh path guards against mmu notifier
> invalidations which complete while it has dropped gpc->lock for the
> HVA->PFN lookup: hva_to_pfn_retry() samples kvm->mmu_invalidate_seq
> and retries if it changed, or if mn_active_invalidate_count is still
> elevated.
>
> That is insufficient for HVA-based caches. mmu_invalidate_seq is only
> advanced by kvm_mmu_invalidate_end() when the invalidated range
> overlaps a memslot, and an HVA-based cache (e.g. the Xen shared_info
> page mapped with KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA) need not be backed
> by any memslot at all. An invalidation of the cached HVA which starts
> and ends entirely within the lookup window is thus invisible to the
> retry check: mn_active_invalidate_count is back to zero and the
> sequence never moved. The refresh then publishes a mapping of a page
> which has already been freed, and the next reader dereferences it:
>
> BUG: KASAN: use-after-free in kvm_xen_shared_info_init+0x3c6/0x440
> Read of size 4 at addr ffff8880599c2900 by task syz.2.383/7257
>
> Since gfn_to_pfn_cache_invalidate_start() deliberately skips caches
> which are not currently valid (including one whose refresh is in
> progress, as the refresh clears the valid flag before dropping the
> lock), the retry check is the only line of defence, and it must fire
> for *any* invalidation, not just those hitting a memslot.
>
> Add a dedicated kvm->gpc_invalidate_seq, incremented by every
> kvm_mmu_notifier_invalidate_range_end() under mn_invalidate_lock
> before mn_active_invalidate_count is decremented, and check it in
> hva_to_pfn_retry() instead of mmu_invalidate_seq. Incrementing in
> range_end() in the same critical section as the in-progress count
> also closes the variant where the cache is activated with the
> contested HVA only after invalidate_range_start() has run.
>
> The same bug is also reachable through the per-vCPU vcpu_info cache
> (KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA), where the stale mapping is
> then dereferenced by kvm_setup_guest_pvclock() on the next KVM_RUN:
>
> BUG: KASAN: use-after-free in kvm_setup_guest_pvclock+0x5bf/0x660
>
> This intentionally makes refresh retry on *unrelated* mmu notifier
> events; restoring precision (and reworking the GPC locking more
> generally) is left for a subsequent series.
>
> Reproducers: https://david.woodhou.se/xen_shinfo_race.c
> https://david.woodhou.se/vcpu_info_race.c
>
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Reported-by: syzbot+0948c82180d475ad24e2@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/6a0c5f2c.a00a0220.2c7954.0000.GAE@google.com/
> Tested-by: syzbot+0948c82180d475ad24e2@syzkaller.appspotmail.com
> Reported-by: syzbot+fb7c2dd166d3ea63df2a@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/6a426dd2.854d4ab9.360e1d.0008.GAE@google.com/
> Fixes: b9220d32799a ("KVM: x86/xen: allow shared_info to be mapped by fixed HVA")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> Assisted-by: Claude:claude-mythos-5
> ---
> include/linux/kvm_host.h | 2 ++
> virt/kvm/kvm_main.c | 10 ++++++++++
> virt/kvm/pfncache.c | 18 +++++++++---------
> 3 files changed, 21 insertions(+), 9 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (11 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 12/13] KVM: pfncache: use a dedicated invalidation sequence for cache refresh David Woodhouse
@ 2026-08-31 21:26 ` David Woodhouse
2026-08-31 23:36 ` sashiko-bot
2026-09-02 12:48 ` Paul Durrant
2026-09-04 15:37 ` [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup Paolo Bonzini
13 siblings, 2 replies; 38+ messages in thread
From: David Woodhouse @ 2026-08-31 21:26 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: dwmw2, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx,
mingo, bp, dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
From: Furkan Caliskan <frn1furkan10@gmail.com>
IDR is deprecated in favor of XArray: see
Documentation/core-api/idr.rst. Convert evtchn_ports accordingly.
kvm_xen_eventfd_assign()'s single-slot idr_alloc() becomes
xa_insert(), since it was really an insert-at-index, not an
allocation: -EBUSY replaces -ENOSPC, still mapped to -EEXIST.
kvm_xen_hcall_evtchn_send() drops its explicit rcu_read_lock(),
since xa_load() takes its own RCU read-side section internally.
evtchnfd's lifetime is still guaranteed by kvm->srcu.
xen_lock is left in place: it protects state beyond the map itself.
Signed-off-by: Furkan Caliskan <frn1furkan10@gmail.com>
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/include/asm/kvm_host.h | 3 ++-
arch/x86/kvm/xen.c | 34 ++++++++++++++++-----------------
2 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 683bb8bf43a9..3af7395c2430 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -16,6 +16,7 @@
#include <linux/irq_work.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
+#include <linux/xarray.h>
#include <linux/kvm.h>
#include <linux/kvm_para.h>
@@ -1113,7 +1114,7 @@ struct kvm_xen {
bool runstate_update_flag;
u8 upcall_vector;
struct gfn_to_pfn_cache shinfo_cache;
- struct idr evtchn_ports;
+ struct xarray evtchn_ports;
unsigned long poll_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
struct kvm_xen_hvm_config hvm_config;
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index d15c62ad7932..718396340d3c 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -2141,7 +2141,7 @@ static int kvm_xen_eventfd_update(struct kvm *kvm,
/* Protect writes to evtchnfd as well as the idr lookup. */
mutex_lock(&kvm->arch.xen.xen_lock);
- evtchnfd = idr_find(&kvm->arch.xen.evtchn_ports, port);
+ evtchnfd = xa_load(&kvm->arch.xen.evtchn_ports, port);
ret = -ENOENT;
if (!evtchnfd)
@@ -2235,13 +2235,13 @@ static int kvm_xen_eventfd_assign(struct kvm *kvm,
}
mutex_lock(&kvm->arch.xen.xen_lock);
- ret = idr_alloc(&kvm->arch.xen.evtchn_ports, evtchnfd, port, port + 1,
+ ret = xa_insert(&kvm->arch.xen.evtchn_ports, port, evtchnfd,
GFP_KERNEL);
mutex_unlock(&kvm->arch.xen.xen_lock);
- if (ret >= 0)
+ if (!ret)
return 0;
- if (ret == -ENOSPC)
+ if (ret == -EBUSY)
ret = -EEXIST;
out:
if (eventfd)
@@ -2256,7 +2256,7 @@ static int kvm_xen_eventfd_deassign(struct kvm *kvm, u32 port)
struct evtchnfd *evtchnfd;
mutex_lock(&kvm->arch.xen.xen_lock);
- evtchnfd = idr_remove(&kvm->arch.xen.evtchn_ports, port);
+ evtchnfd = xa_erase(&kvm->arch.xen.evtchn_ports, port);
mutex_unlock(&kvm->arch.xen.xen_lock);
if (!evtchnfd)
@@ -2272,7 +2272,7 @@ static int kvm_xen_eventfd_deassign(struct kvm *kvm, u32 port)
static int kvm_xen_eventfd_reset(struct kvm *kvm)
{
struct evtchnfd *evtchnfd, **all_evtchnfds;
- int i;
+ unsigned long i;
int n = 0;
mutex_lock(&kvm->arch.xen.xen_lock);
@@ -2282,7 +2282,7 @@ static int kvm_xen_eventfd_reset(struct kvm *kvm)
* critical section, first collect all the evtchnfd objects
* in an array as they are removed from evtchn_ports.
*/
- idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i)
+ xa_for_each(&kvm->arch.xen.evtchn_ports, i, evtchnfd)
n++;
all_evtchnfds = kmalloc_objs(struct evtchnfd *, n);
@@ -2292,9 +2292,9 @@ static int kvm_xen_eventfd_reset(struct kvm *kvm)
}
n = 0;
- idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i) {
+ xa_for_each(&kvm->arch.xen.evtchn_ports, i, evtchnfd) {
all_evtchnfds[n++] = evtchnfd;
- idr_remove(&kvm->arch.xen.evtchn_ports, evtchnfd->send_port);
+ xa_erase(&kvm->arch.xen.evtchn_ports, evtchnfd->send_port);
}
mutex_unlock(&kvm->arch.xen.xen_lock);
@@ -2345,12 +2345,10 @@ static bool kvm_xen_hcall_evtchn_send(struct kvm_vcpu *vcpu, u64 param, u64 *r)
}
/*
- * evtchnfd is protected by kvm->srcu; the idr lookup instead
- * is protected by RCU.
+ * evtchnfd is protected by kvm->srcu; the xa_load is RCU-safe
+ * internally, no explicit rcu_read_lock() needed.
*/
- rcu_read_lock();
- evtchnfd = idr_find(&vcpu->kvm->arch.xen.evtchn_ports, send.port);
- rcu_read_unlock();
+ evtchnfd = xa_load(&vcpu->kvm->arch.xen.evtchn_ports, send.port);
if (!evtchnfd)
return false;
@@ -2397,23 +2395,23 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
void kvm_xen_init_vm(struct kvm *kvm)
{
mutex_init(&kvm->arch.xen.xen_lock);
- idr_init(&kvm->arch.xen.evtchn_ports);
+ xa_init(&kvm->arch.xen.evtchn_ports);
kvm_gpc_init(&kvm->arch.xen.shinfo_cache, kvm);
}
void kvm_xen_destroy_vm(struct kvm *kvm)
{
struct evtchnfd *evtchnfd;
- int i;
+ unsigned long i;
kvm_gpc_deactivate(&kvm->arch.xen.shinfo_cache);
- idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i) {
+ xa_for_each(&kvm->arch.xen.evtchn_ports, i, evtchnfd) {
if (!evtchnfd->deliver.port.port)
eventfd_ctx_put(evtchnfd->deliver.eventfd.ctx);
kfree(evtchnfd);
}
- idr_destroy(&kvm->arch.xen.evtchn_ports);
+ xa_destroy(&kvm->arch.xen.evtchn_ports);
if (kvm->arch.xen.hvm_config.msr)
static_branch_slow_dec_deferred(&kvm_xen_enabled);
--
2.55.0
^ permalink raw reply related [flat|nested] 38+ messages in thread* Re: [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray
2026-08-31 21:26 ` [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray David Woodhouse
@ 2026-08-31 23:36 ` sashiko-bot
2026-09-01 0:07 ` David Woodhouse
2026-09-02 12:48 ` Paul Durrant
1 sibling, 1 reply; 38+ messages in thread
From: sashiko-bot @ 2026-08-31 23:36 UTC (permalink / raw)
To: David Woodhouse; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Type confusion in evtchnfd delivery union allows a userspace guest to crash the host kernel by assigning an EVTCHNSTAT_ipi event channel to port 0.
--
commit 365d4c87b9f4941190fe8a9a101dce7853ba1e18
Author: Furkan Caliskan <frn1furkan10@gmail.com>
KVM: x86/xen: Convert evtchn_ports from IDR to XArray
This patch converts the deprecated IDR used for evtchn_ports into an XArray.
It replaces idr_alloc() with xa_insert() and idr_remove() with xa_erase(),
dropping the explicit rcu_read_lock() in kvm_xen_hcall_evtchn_send() since
xa_load() is internally RCU-safe.
> diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
> index b024a09de55a3..b59c6b747c2f6 100644
> --- a/arch/x86/kvm/xen.c
> +++ b/arch/x86/kvm/xen.c
> @@ -2214,13 +2214,13 @@ static int kvm_xen_eventfd_assign(struct kvm *kvm,
> }
>
> mutex_lock(&kvm->arch.xen.xen_lock);
> - ret = idr_alloc(&kvm->arch.xen.evtchn_ports, evtchnfd, port, port + 1,
> + ret = xa_insert(&kvm->arch.xen.evtchn_ports, port, evtchnfd,
> GFP_KERNEL);
[Severity: Critical]
This isn't a bug introduced by this patch, but could this union type
confusion allow a userspace guest to crash the host kernel?
When a userspace process calls the KVM ioctl to assign an event channel with
type EVTCHNSTAT_ipi and send_port = 0, the setup code just prior to this
insertion does the following in kvm_xen_eventfd_assign():
evtchnfd->deliver.port.port = data->u.evtchn.deliver.port.port;
evtchnfd->deliver.port.vcpu_id = data->u.evtchn.deliver.port.vcpu;
evtchnfd->deliver.port.vcpu_idx = -1;
Because of the union layout in the evtchnfd structure, deliver.port overlaps
with deliver.eventfd. Writing -1 to vcpu_idx corrupts the eventfd_ctx pointer.
> [ ... ]
> @@ -2235,7 +2235,7 @@ static int kvm_xen_eventfd_deassign(struct kvm *kvm, u32 port)
> struct evtchnfd *evtchnfd;
>
> mutex_lock(&kvm->arch.xen.xen_lock);
> - evtchnfd = idr_remove(&kvm->arch.xen.evtchn_ports, port);
> + evtchnfd = xa_erase(&kvm->arch.xen.evtchn_ports, port);
> mutex_unlock(&kvm->arch.xen.xen_lock);
>
> if (!evtchnfd)
> @@ -2251,7 +2251,7 @@ static int kvm_xen_eventfd_deassign(struct kvm *kvm, u32 port)
> [ ... ]
> @@ -2376,23 +2374,23 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
> void kvm_xen_destroy_vm(struct kvm *kvm)
> {
> struct evtchnfd *evtchnfd;
> - int i;
> + unsigned long i;
>
> kvm_gpc_deactivate(&kvm->arch.xen.shinfo_cache);
>
> - idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i) {
> + xa_for_each(&kvm->arch.xen.evtchn_ports, i, evtchnfd) {
> if (!evtchnfd->deliver.port.port)
> eventfd_ctx_put(evtchnfd->deliver.eventfd.ctx);
[Severity: Critical]
This is a pre-existing issue, but does this check trigger an invalid pointer
dereference due to the type confusion mentioned above?
If an IPI was assigned to port 0, evtchnfd->deliver.port.port evaluates to 0,
making the condition true. The kernel will then mistakenly dereference the
corrupted pointer (overlapping with vcpu_idx = -1) by calling
eventfd_ctx_put().
This exact sequence is present during deassignment in
kvm_xen_eventfd_deassign(), as well as here during VM destruction, which
seems like it could lead to a kernel panic and a host denial of service.
> kfree(evtchnfd);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831213632.81023-1-dwmw2@infradead.org?part=13
^ permalink raw reply [flat|nested] 38+ messages in thread* Re: [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray
2026-08-31 23:36 ` sashiko-bot
@ 2026-09-01 0:07 ` David Woodhouse
0 siblings, 0 replies; 38+ messages in thread
From: David Woodhouse @ 2026-09-01 0:07 UTC (permalink / raw)
To: sashiko-reviews; +Cc: kvm
[-- Attachment #1: Type: text/plain, Size: 1653 bytes --]
On Mon, 2026-08-31 at 23:36 +0000, sashiko-bot@kernel.org wrote:
>
> [Severity: Critical]
> This isn't a bug introduced by this patch, but could this union type
> confusion allow a userspace guest to crash the host kernel?
>
> When a userspace process calls the KVM ioctl to assign an event channel with
> type EVTCHNSTAT_ipi and send_port = 0, the setup code just prior to this
> insertion does the following in kvm_xen_eventfd_assign():
>
> evtchnfd->deliver.port.port = data->u.evtchn.deliver.port.port;
> evtchnfd->deliver.port.vcpu_id = data->u.evtchn.deliver.port.vcpu;
> evtchnfd->deliver.port.vcpu_idx = -1;
>
> Because of the union layout in the evtchnfd structure, deliver.port overlaps
> with deliver.eventfd. Writing -1 to vcpu_idx corrupts the eventfd_ctx pointer.
No, because we can't get into kvm_xen_eventfd_assign() with send_port==0.
That's checked in kvm_xen_setattr_evtchn():
if (!port || port >= kvm_max_evtchn_port(kvm))
return -EINVAL;
This is dealing with events *sent* by the guest itself, accelerating
the EVTCHNOP_send hypercall. So kvm_xen_eventfd_assign() only handles
the EVTCHNSTAT_ipi and EVTCHNSTAT_interdomain types, as the guest can't
send virq/pirq.
The EVTCHNSTAT_interdomain is what the eventfd trigger was designed
for, when deliver_port.port == 0 and the eventfd.fd is provided.
And EVTCHNSTAT_ipi is protected by the validation on *send_port* above,
coupled with the restriction that send_port==deliver.port.port for
IPIs. (Since it's the delivery port being zero that would have
triggered the hypothetical bug in kvm_xen_destroy_vm(), not send_port).
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray
2026-08-31 21:26 ` [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray David Woodhouse
2026-08-31 23:36 ` sashiko-bot
@ 2026-09-02 12:48 ` Paul Durrant
1 sibling, 0 replies; 38+ messages in thread
From: Paul Durrant @ 2026-09-02 12:48 UTC (permalink / raw)
To: David Woodhouse, seanjc, pbonzini
Cc: joao.m.martins, boris.ostrovsky, ankur.a.arora, tglx, mingo, bp,
dave.hansen, hpa, x86, syzbot+208f7f3e5f59c11aeb90,
syzkaller-bugs, suryasaimadhu369, lkp, nicoyip.dev, frn1furkan10,
kvm, linux-kernel, imv4bel
On 31/08/2026 22:26, David Woodhouse wrote:
> From: Furkan Caliskan <frn1furkan10@gmail.com>
>
> IDR is deprecated in favor of XArray: see
> Documentation/core-api/idr.rst. Convert evtchn_ports accordingly.
>
> kvm_xen_eventfd_assign()'s single-slot idr_alloc() becomes
> xa_insert(), since it was really an insert-at-index, not an
> allocation: -EBUSY replaces -ENOSPC, still mapped to -EEXIST.
>
> kvm_xen_hcall_evtchn_send() drops its explicit rcu_read_lock(),
> since xa_load() takes its own RCU read-side section internally.
> evtchnfd's lifetime is still guaranteed by kvm->srcu.
>
> xen_lock is left in place: it protects state beyond the map itself.
>
> Signed-off-by: Furkan Caliskan <frn1furkan10@gmail.com>
> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/include/asm/kvm_host.h | 3 ++-
> arch/x86/kvm/xen.c | 34 ++++++++++++++++-----------------
> 2 files changed, 18 insertions(+), 19 deletions(-)
>
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup
2026-08-31 21:26 [PATCH v3 0/13] KVM: x86/xen: Bug fixes and long_mode cleanup David Woodhouse
` (12 preceding siblings ...)
2026-08-31 21:26 ` [PATCH v3 13/13] KVM: x86/xen: Convert evtchn_ports from IDR to XArray David Woodhouse
@ 2026-09-04 15:37 ` Paolo Bonzini
13 siblings, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2026-09-04 15:37 UTC (permalink / raw)
To: David Woodhouse
Cc: seanjc, paul, joao.m.martins, boris.ostrovsky, ankur.a.arora,
tglx, mingo, bp, dave.hansen, hpa, x86,
syzbot+208f7f3e5f59c11aeb90, syzkaller-bugs, suryasaimadhu369,
lkp, nicoyip.dev, frn1furkan10, kvm, linux-kernel, imv4bel
On Mon, Aug 31, 2026 at 11:36 PM David Woodhouse <dwmw2@infradead.org> wrote:
>
> Clean up the handling of vcpu->arch.xen.long_mode to be consistent and
> correctly handle 32-bit/64-bit alignment. And various other bug fixes
> that have accumulated over the months since v1.
Applied to kvm/next, thanks.
Paolo
> v3:
> - Rebase onto kvm/next (7.3 merge window).
> - Add poll_evtchn READ_ONCE/WRITE_ONCE annotation (Chengfeng Ye).
> - Add evtchn_ports IDR to XArray conversion (Furkan Caliskan).
>
> v2: https://lore.kernel.org/all/20260811094829.98794-1-dwmw2@infradead.org/
> - Take kvm->srcu in __kvm_xen_has_interrupt().
> - Add dedicated invalidation sequence for HVA-based caches.
> - Take Sean's version of the 32-bit atomics patch, and his follow-up
> replacing the remaining asm blobs with atomic*() APIs.
> - Use GEN_BINARY_RMWcc() rather than open-coding the btsl.
> - Explain why the pending_bits access in kvm_xen_set_evtchn_fast() does
> not need the same treatment as the vcpu_info one (it is in the page
> aligned per-VM shared_info).
> - Don't require 8-byte alignment of vcpu_info in 64-bit mode; always
> accept 4-byte alignment, so as not to break migration of guests which
> registered while in 32-bit mode.
> - Add Closes: links for the reported issues.
> - Cast to u64 before the >> 32 in the unaligned evtchn_pending_sel
> handling; evtchn_pending_sel is unsigned long, so the shift was
> undefined on 32-bit even though the branch is unreachable there
> (kernel test robot).
> - Rebase onto kvm-x86/next; the mode-aware kvm_<reg>_read() helpers which
> landed in the meantime subsume most of what patch 1 was doing by hand.
>
> v1: https://lore.kernel.org/all/20260605143034.3603-1-dwmw2@infradead.org/
>
> Chengfeng Ye (1):
> KVM: x86/xen: Mark poll_evtchn accesses with READ_ONCE()/WRITE_ONCE()
>
> David Woodhouse (8):
> KVM: x86/xen: Rename 'longmode' to 'is_64bit' in hypercall handling
> KVM: x86/xen: Introduce kvm_xen_has_64bit_shinfo() macro
> KVM: x86/xen: Rename max_evtchn_port() to kvm_max_evtchn_port()
> KVM: x86/xen: Latch shinfo mode in kvm_xen_schedop_poll()
> KVM: x86/xen: Enforce 4-byte alignment of vcpu_info registration
> KVM: x86/xen: Use 32-bit locked bts for vcpu_info evtchn_pending_sel
> KVM: x86/xen: Take kvm->srcu in __kvm_xen_has_interrupt()
> KVM: pfncache: use a dedicated invalidation sequence for cache refresh
>
> Furkan Caliskan (1):
> KVM: x86/xen: Convert evtchn_ports from IDR to XArray
>
> Hyunwoo Kim (1):
> KVM: x86/xen: Latch shinfo mode in kvm_xen_set_evtchn_fast()
>
> Sean Christopherson (2):
> KVM: x86/xen: Use 32-bit atomics if vCPU's evtchn_pending_sel isn't aligned
> KVM: x86/xen: Use atomic*() APIs instead of open coded equivalents
>
> arch/x86/include/asm/kvm_host.h | 3 +-
> arch/x86/kvm/xen.c | 212 ++++++++++++++++++++++++----------------
> arch/x86/kvm/xen.h | 5 +
> include/linux/kvm_host.h | 2 +
> virt/kvm/kvm_main.c | 10 ++
> virt/kvm/pfncache.c | 18 ++--
> 6 files changed, 157 insertions(+), 93 deletions(-)
>
^ permalink raw reply [flat|nested] 38+ messages in thread