All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] KVM: arm64: Fix MPIDR lookup for unreset vCPUs
@ 2026-06-11 14:40 fuqiang wang
  2026-06-11 14:40 ` [PATCH v2 1/2] arm64: Add MPIDR_EL1 RES1 definitions fuqiang wang
  2026-06-11 14:40 ` [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table fuqiang wang
  0 siblings, 2 replies; 8+ messages in thread
From: fuqiang wang @ 2026-06-11 14:40 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton, Zenghui Yu, linux-kernel, kvmarm
  Cc: dongxu zhang, wangfuqiang49

From: wangfuqiang49 <wangfuqiang49@jd.com>

Hi,

This series fixes an MPIDR lookup issue when a VM is created with CPU
hotplug support.

kvm_init_mpidr_data() builds a compressed MPIDR-to-vCPU lookup table by
walking all possible vCPUs. However, vCPUs that have not been reset yet
still have a zero MPIDR_EL1 state, which aliases vCPU0. This can cause
cmpidr_to_idx[0] to be overwritten with the index of an unreset vCPU.

As a result, MPIDR 0 lookups can return the wrong vCPU, preventing
interrupts targeting vCPU0 from being delivered correctly and making
guest boot extremely slow in configurations using CPU hotplug.

Patch 1 adds named definitions for the MPIDR_EL1 RES1 bit used to detect
whether a vCPU's MPIDR_EL1 state has been reset.
Patch 2 skips unreset vCPUs when populating the compressed MPIDR lookup
table.

Thanks,
Fuqiang

SELF-TEST result:

1. use crash debug cmpidr_to_idx[]

(qemu args: -smp maxcpus=512,cpus=4,sockets=2,cores=128,threads=2)

crash> struct kvm_mpidr_data.mpidr_mask 0xffff2020acda15e0
  mpidr_mask = 3,
crash> x/8xh 0xffff2020acda15e8
0xffff2020acda15e8:     0x0000  0x0001  0x0002  0x0003  0x642f  0x7665  0x6e2f  0x6d76

2. use link [1] to test IPI latency(Before the patch was merged, it often took
   seconds for a kernel thread to be scheduled after being woken up.)

IPI Latency Matrix - avg (ns) [100000 samples]

          CPU0     CPU1     CPU2     CPU3
CPU0           -    1355    2242    2238
CPU1        2730       -    2391    1852
CPU2        2149    3015       -    2033
CPU3        2005    1651    1801       -


Changes in v2:
- Fix macro naming/placement/type and pass vcpu instead of pre-masked
  affinity to correctly check MPIDR_EL1 bit[31] (sashiko bot)

v1: https://lore.kernel.org/all/20260611090934.84469-1-fuqiang.wng@gmail.com/

[1]: https://github.com/cai-fuqiang/kernel_test/tree/master/ipi_latency

fuqiang wang (2):
  arm64: Add MPIDR_EL1 RES1 definitions
  KVM: arm64: Skip unreset vCPUs in MPIDR lookup table

 arch/arm64/include/asm/cputype.h     |  1 +
 arch/arm64/include/asm/kvm_emulate.h |  9 +++++++++
 arch/arm64/kvm/arm.c                 | 14 ++++++++++++--
 3 files changed, 22 insertions(+), 2 deletions(-)

-- 
2.47.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/2] arm64: Add MPIDR_EL1 RES1 definitions
  2026-06-11 14:40 [PATCH v2 0/2] KVM: arm64: Fix MPIDR lookup for unreset vCPUs fuqiang wang
@ 2026-06-11 14:40 ` fuqiang wang
  2026-06-11 14:40 ` [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table fuqiang wang
  1 sibling, 0 replies; 8+ messages in thread
From: fuqiang wang @ 2026-06-11 14:40 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton, Zenghui Yu, linux-kernel, kvmarm
  Cc: dongxu zhang, wangfuqiang49, fuqiang wang

MPIDR_EL1 bit 31 is RES1. Add named definitions for the bit.

Signed-off-by: fuqiang wang <fuqiang.wng@gmail.com>
---
 arch/arm64/include/asm/cputype.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 7b518e81dd15..22dc44d2de03 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -9,6 +9,7 @@
 
 #define MPIDR_UP_BITMASK	(0x1 << 30)
 #define MPIDR_MT_BITMASK	(0x1 << 24)
+#define MPIDR_RES1_BITMASK	(UL(1) << 31)
 #define MPIDR_HWID_BITMASK	UL(0xff00ffffff)
 
 #define MPIDR_LEVEL_BITS_SHIFT	3
-- 
2.47.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table
  2026-06-11 14:40 [PATCH v2 0/2] KVM: arm64: Fix MPIDR lookup for unreset vCPUs fuqiang wang
  2026-06-11 14:40 ` [PATCH v2 1/2] arm64: Add MPIDR_EL1 RES1 definitions fuqiang wang
@ 2026-06-11 14:40 ` fuqiang wang
  2026-06-14  9:26   ` Marc Zyngier
  1 sibling, 1 reply; 8+ messages in thread
From: fuqiang wang @ 2026-06-11 14:40 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton, Zenghui Yu, linux-kernel, kvmarm
  Cc: dongxu zhang, wangfuqiang49, fuqiang wang

When a VM is created with CPU hotplug support, kvm_for_each_vcpu() can
walk vCPUs that have not been reset yet. Their MPIDR_EL1 state is still
zero, which aliases vCPU0 when populating the compressed MPIDR lookup
table.

As a result, cmpidr_to_idx[0] can be overwritten with the index of an
unreset vCPU. A lookup for MPIDR 0 then returns the wrong vCPU, which
can prevent interrupts targeting vCPU0 from being delivered correctly
and make guest boot extremely slow.

Skip vCPUs whose MPIDR_EL1 value does not have the RES1 bit set.

Fixes: 5544750efd51 ("KVM: arm64: Build MPIDR to vcpu index cache at runtime")
Signed-off-by: fuqiang wang <fuqiang.wng@gmail.com>
---
 arch/arm64/include/asm/kvm_emulate.h |  9 +++++++++
 arch/arm64/kvm/arm.c                 | 14 ++++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 5bf3d7e1d92c..3d2f0a8b040d 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -506,6 +506,15 @@ static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 	return __vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
 }
 
+/*
+ * Check if vCPU MPIDR_EL1 has been reset. MPIDR_EL1.bit[31] is RES1
+ * and set during reset; a zero value indicates the vCPU is unreset.
+ */
+static inline bool kvm_vcpu_mpidr_is_reset(struct kvm_vcpu *vcpu)
+{
+	return !!(__vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_RES1_BITMASK);
+}
+
 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
 {
 	if (vcpu_mode_is_32bit(vcpu)) {
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3732ee9eb0d4..fccfa97370df 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -887,8 +887,18 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
 	data->mpidr_mask = mask;
 
 	kvm_for_each_vcpu(c, vcpu, kvm) {
-		u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
-		u16 index = kvm_mpidr_index(data, aff);
+		u64 aff;
+		u16 index;
+
+		/*
+		 * Skip vCPUs that haven't been reset yet; their MPIDR_EL1 is
+		 * zero.
+		 */
+		if (!kvm_vcpu_mpidr_is_reset(vcpu))
+			continue;
+
+		aff = kvm_vcpu_get_mpidr_aff(vcpu);
+		index = kvm_mpidr_index(data, aff);
 
 		data->cmpidr_to_idx[index] = c;
 	}
-- 
2.47.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table
  2026-06-11 14:40 ` [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table fuqiang wang
@ 2026-06-14  9:26   ` Marc Zyngier
  2026-06-15  4:20     ` Oliver Upton
  0 siblings, 1 reply; 8+ messages in thread
From: Marc Zyngier @ 2026-06-14  9:26 UTC (permalink / raw)
  To: fuqiang wang
  Cc: Oliver Upton, Zenghui Yu, linux-kernel, kvmarm, dongxu zhang,
	wangfuqiang49

On Thu, 11 Jun 2026 15:40:42 +0100,
fuqiang wang <fuqiang.wng@gmail.com> wrote:
> 
> When a VM is created with CPU hotplug support,

I'm not sure what you mean by "hotplug support". KVM has no support
for vcpu hotplug at all (all vcpus must have been created before the
VM can run).

> kvm_for_each_vcpu() can
> walk vCPUs that have not been reset yet. Their MPIDR_EL1 state is still
> zero, which aliases vCPU0 when populating the compressed MPIDR lookup
> table.
> 
> As a result, cmpidr_to_idx[0] can be overwritten with the index of an
> unreset vCPU. A lookup for MPIDR 0 then returns the wrong vCPU, which
> can prevent interrupts targeting vCPU0 from being delivered correctly
> and make guest boot extremely slow.

OK, so the problem you are describing is related to vcpus that have
haven't gone through the INIT phase, and really has nothing to do with
hotplug.

> 
> Skip vCPUs whose MPIDR_EL1 value does not have the RES1 bit set.
> 
> Fixes: 5544750efd51 ("KVM: arm64: Build MPIDR to vcpu index cache at runtime")
> Signed-off-by: fuqiang wang <fuqiang.wng@gmail.com>
> ---
>  arch/arm64/include/asm/kvm_emulate.h |  9 +++++++++
>  arch/arm64/kvm/arm.c                 | 14 ++++++++++++--
>  2 files changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index 5bf3d7e1d92c..3d2f0a8b040d 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -506,6 +506,15 @@ static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
>  	return __vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
>  }
>  
> +/*
> + * Check if vCPU MPIDR_EL1 has been reset. MPIDR_EL1.bit[31] is RES1
> + * and set during reset; a zero value indicates the vCPU is unreset.
> + */
> +static inline bool kvm_vcpu_mpidr_is_reset(struct kvm_vcpu *vcpu)
> +{
> +	return !!(__vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_RES1_BITMASK);
> +}
> +

This helper has only a single caller, so it would better be placed in
the function that makes use of it, specially considering that its a
one-liner.

>  static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
>  {
>  	if (vcpu_mode_is_32bit(vcpu)) {
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 3732ee9eb0d4..fccfa97370df 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -887,8 +887,18 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
>  	data->mpidr_mask = mask;
>  
>  	kvm_for_each_vcpu(c, vcpu, kvm) {
> -		u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
> -		u16 index = kvm_mpidr_index(data, aff);
> +		u64 aff;
> +		u16 index;
> +
> +		/*
> +		 * Skip vCPUs that haven't been reset yet; their MPIDR_EL1 is
> +		 * zero.
> +		 */
> +		if (!kvm_vcpu_mpidr_is_reset(vcpu))
> +			continue;

But what about the initial loop that computes the significant bits
amongst the vcpus?

> +
> +		aff = kvm_vcpu_get_mpidr_aff(vcpu);
> +		index = kvm_mpidr_index(data, aff);

In all honesty, I think this is a userspace bug more than anything
else, and checking for random bits in MPDR_EL1 to verify whether the
value is plausible is gross.

Yhis isn't different from setting MPIDR_EL1 to the same value on all
vcpus, which we don't try to mitigate. Late setting of MPIDR_EL1 also
defeats the whole point of having a cache for the affinity to index
conversion, making SGIs pretty slow for late CPUs.

I really think that by not finalising your vcpus and start running the
guest, you have cornered yourself pretty badly, and we shouldn't try
to paper over it.

Thanks,

	M.

-- 
Jazz isn't dead. It just smells funny.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table
  2026-06-14  9:26   ` Marc Zyngier
@ 2026-06-15  4:20     ` Oliver Upton
  2026-06-15 10:08       ` Marc Zyngier
  0 siblings, 1 reply; 8+ messages in thread
From: Oliver Upton @ 2026-06-15  4:20 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: fuqiang wang, Zenghui Yu, linux-kernel, kvmarm, dongxu zhang,
	wangfuqiang49

On Sun, Jun 14, 2026 at 10:26:32AM +0100, Marc Zyngier wrote:
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 3732ee9eb0d4..fccfa97370df 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -887,8 +887,18 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
> >  	data->mpidr_mask = mask;
> >  
> >  	kvm_for_each_vcpu(c, vcpu, kvm) {
> > -		u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
> > -		u16 index = kvm_mpidr_index(data, aff);
> > +		u64 aff;
> > +		u16 index;
> > +
> > +		/*
> > +		 * Skip vCPUs that haven't been reset yet; their MPIDR_EL1 is
> > +		 * zero.
> > +		 */
> > +		if (!kvm_vcpu_mpidr_is_reset(vcpu))
> > +			continue;
> 
> But what about the initial loop that computes the significant bits
> amongst the vcpus?
> 
> > +
> > +		aff = kvm_vcpu_get_mpidr_aff(vcpu);
> > +		index = kvm_mpidr_index(data, aff);
> 
> In all honesty, I think this is a userspace bug more than anything
> else, and checking for random bits in MPDR_EL1 to verify whether the
> value is plausible is gross.

+1. Checking the MPIDR value is also broken because userspace can write
whatever it wants to the register, which could even clear the RES1 bit
that's getting tested here.

> Yhis isn't different from setting MPIDR_EL1 to the same value on all
> vcpus, which we don't try to mitigate. Late setting of MPIDR_EL1 also
> defeats the whole point of having a cache for the affinity to index
> conversion, making SGIs pretty slow for late CPUs.
> 
> I really think that by not finalising your vcpus and start running the
> guest, you have cornered yourself pretty badly, and we shouldn't try
> to paper over it.

I generally agree, although I wouldn't be against a change that nuked
any of the cached routings in case of userspace doing stupid things like
collisions and whatnot.

Thanks,
Oliver

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table
  2026-06-15  4:20     ` Oliver Upton
@ 2026-06-15 10:08       ` Marc Zyngier
  2026-06-18 11:38         ` fuqiang wang
  0 siblings, 1 reply; 8+ messages in thread
From: Marc Zyngier @ 2026-06-15 10:08 UTC (permalink / raw)
  To: Oliver Upton
  Cc: fuqiang wang, Zenghui Yu, linux-kernel, kvmarm, dongxu zhang,
	wangfuqiang49

On Mon, 15 Jun 2026 05:20:35 +0100,
Oliver Upton <oupton@kernel.org> wrote:
> 
> On Sun, Jun 14, 2026 at 10:26:32AM +0100, Marc Zyngier wrote:
> > > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > > index 3732ee9eb0d4..fccfa97370df 100644
> > > --- a/arch/arm64/kvm/arm.c
> > > +++ b/arch/arm64/kvm/arm.c
> > > @@ -887,8 +887,18 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
> > >  	data->mpidr_mask = mask;
> > >  
> > >  	kvm_for_each_vcpu(c, vcpu, kvm) {
> > > -		u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
> > > -		u16 index = kvm_mpidr_index(data, aff);
> > > +		u64 aff;
> > > +		u16 index;
> > > +
> > > +		/*
> > > +		 * Skip vCPUs that haven't been reset yet; their MPIDR_EL1 is
> > > +		 * zero.
> > > +		 */
> > > +		if (!kvm_vcpu_mpidr_is_reset(vcpu))
> > > +			continue;
> > 
> > But what about the initial loop that computes the significant bits
> > amongst the vcpus?
> > 
> > > +
> > > +		aff = kvm_vcpu_get_mpidr_aff(vcpu);
> > > +		index = kvm_mpidr_index(data, aff);
> > 
> > In all honesty, I think this is a userspace bug more than anything
> > else, and checking for random bits in MPDR_EL1 to verify whether the
> > value is plausible is gross.
> 
> +1. Checking the MPIDR value is also broken because userspace can write
> whatever it wants to the register, which could even clear the RES1 bit
> that's getting tested here.
> 
> > Yhis isn't different from setting MPIDR_EL1 to the same value on all
> > vcpus, which we don't try to mitigate. Late setting of MPIDR_EL1 also
> > defeats the whole point of having a cache for the affinity to index
> > conversion, making SGIs pretty slow for late CPUs.
> > 
> > I really think that by not finalising your vcpus and start running the
> > guest, you have cornered yourself pretty badly, and we shouldn't try
> > to paper over it.
> 
> I generally agree, although I wouldn't be against a change that nuked
> any of the cached routings in case of userspace doing stupid things like
> collisions and whatnot.

Detecting collisions is difficult, as we have no idea of the overall
guest topology. All we can do is work out whether the computed mask
has enough bits to represent the number of online vcpus, but that's
not necessarily good enough.

One possibility would be to invalidate the cache on each update to any
MPIDR_EL1, including reset. People doing silly things by initialising
vcpus post first start will still suffer, but should we care?

Thanks,

	M.

-- 
Jazz isn't dead. It just smells funny.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table
  2026-06-15 10:08       ` Marc Zyngier
@ 2026-06-18 11:38         ` fuqiang wang
  2026-06-18 12:32           ` Marc Zyngier
  0 siblings, 1 reply; 8+ messages in thread
From: fuqiang wang @ 2026-06-18 11:38 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton
  Cc: Zenghui Yu, linux-kernel, kvmarm, dongxu zhang, wangfuqiang49,
	diaojiaqing.1



On 6/15/26 6:08 PM, Marc Zyngier wrote:

Hi Oliver, Marc

Thank you very much for your replies and guidance. I'm sorry for the
late reply.(I took some time to brush up on ARM CPU hotplug.)

> On Mon, 15 Jun 2026 05:20:35 +0100,
> Oliver Upton <oupton@kernel.org> wrote:
>>
>> On Sun, Jun 14, 2026 at 10:26:32AM +0100, Marc Zyngier wrote:
>>>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>>>> index 3732ee9eb0d4..fccfa97370df 100644
>>>> --- a/arch/arm64/kvm/arm.c
>>>> +++ b/arch/arm64/kvm/arm.c
>>>> @@ -887,8 +887,18 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
>>>>   	data->mpidr_mask = mask;
>>>>   
>>>>   	kvm_for_each_vcpu(c, vcpu, kvm) {
>>>> -		u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
>>>> -		u16 index = kvm_mpidr_index(data, aff);
>>>> +		u64 aff;
>>>> +		u16 index;
>>>> +
>>>> +		/*
>>>> +		 * Skip vCPUs that haven't been reset yet; their MPIDR_EL1 is
>>>> +		 * zero.
>>>> +		 */
>>>> +		if (!kvm_vcpu_mpidr_is_reset(vcpu))
>>>> +			continue;
>>>
>>> But what about the initial loop that computes the significant bits
>>> amongst the vcpus?

Yes, this is indeed missed here, possibly making the following nr_entries
calculation too large.

>>>
>>>> +
>>>> +		aff = kvm_vcpu_get_mpidr_aff(vcpu);
>>>> +		index = kvm_mpidr_index(data, aff);
>>>
>>> In all honesty, I think this is a userspace bug more than anything
>>> else, and checking for random bits in MPDR_EL1 to verify whether the
>>> value is plausible is gross.
>>
>> +1. Checking the MPIDR value is also broken because userspace can write
>> whatever it wants to the register, which could even clear the RES1 bit
>> that's getting tested here.

Yes, the change here is quite ugly — it looks like temporary debug code.
It would be better to change it to !kvm_vcpu_initialized().

>>
>>> Yhis isn't different from setting MPIDR_EL1 to the same value on all
>>> vcpus, which we don't try to mitigate. Late setting of MPIDR_EL1 also
>>> defeats the whole point of having a cache for the affinity to index
>>> conversion, making SGIs pretty slow for late CPUs.
>>>
>>> I really think that by not finalising your vcpus and start running the
>>> guest, you have cornered yourself pretty badly, and we shouldn't try
>>> to paper over it.
>>
>> I generally agree, although I wouldn't be against a change that nuked
>> any of the cached routings in case of userspace doing stupid things like
>> collisions and whatnot.

I once thought about sending patch [1] again, because I found that Oliver
had done something similar[2]... but then I gave up.

For restless userspace programs, KVM cannot foresee their behavior. For
example, when a VCPU is running, there may be cases like:

+ some vcpus not create, later create
+ some vcpus created but not reset, later reset
+ some vcpu not create, later create BUT never run. This may prevent other
   vCPU threads from using the mpidr_data, because they rely on the vCPU that
   destroys the mpidr_data to trigger a rebuild. (Although we can rebuild
   mpidr_data when resetting the vCPU(just for later-created vcpu), it is
   preferable to defer the rebuild until after all destruction actions have
   been completed).

even, as mentioned above, userspace write MPIDR_EL1 to cause collisions. It
seems somewhat not worth the effort.

[1]: https://github.com/cai-fuqiang/armkvm/commit/eeda9309e0a6c700449e90cf27127a7e4e0238ed
[2]: https://lore.kernel.org/all/20240508071952.2035422-1-oliver.upton@linux.dev/#r

> 
> Detecting collisions is difficult, as we have no idea of the overall
> guest topology. All we can do is work out whether the computed mask
> has enough bits to represent the number of online vcpus, but that's
> not necessarily good enough.
> 
> One possibility would be to invalidate the cache on each update to any
> MPIDR_EL1, including reset. People doing silly things by initialising
> vcpus post first start will still suffer, but should we care?

However, could we detect collisions within the init function and, upon
detection, notify userspace without taking any corrective or fallback
action? This would serve as a stronger reminder to userspace of its
non-compliant behavior.

e.g.

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3732ee9eb0d4..7563feab1a11 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -893,6 +893,17 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
                 data->cmpidr_to_idx[index] = c;
         }

+       kvm_for_each_vcpu(c, vcpu, kvm) {
+               u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
+               u16 index = kvm_mpidr_index(data, aff);
+
+               if (data->cmpidr_to_idx[index] != c) {
+                       pr_warn("Multiple vCPUs share the same MPIDR value, "
+                               "it may cause the guest to hang or run slower\n");
+                       break;
+               }
+       }
+
         rcu_assign_pointer(kvm->arch.mpidr_data, data);
  out:
         mutex_unlock(&kvm->arch.config_lock);


Thanks
fuqiang

> 
> Thanks,
> 
> 	M.
> 


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table
  2026-06-18 11:38         ` fuqiang wang
@ 2026-06-18 12:32           ` Marc Zyngier
  0 siblings, 0 replies; 8+ messages in thread
From: Marc Zyngier @ 2026-06-18 12:32 UTC (permalink / raw)
  To: fuqiang wang
  Cc: Oliver Upton, Zenghui Yu, linux-kernel, kvmarm, dongxu zhang,
	wangfuqiang49, diaojiaqing.1

On Thu, 18 Jun 2026 12:38:54 +0100,
fuqiang wang <fuqiang.wng@gmail.com> wrote:
> 
> However, could we detect collisions within the init function and, upon
> detection, notify userspace without taking any corrective or fallback
> action? This would serve as a stronger reminder to userspace of its
> non-compliant behavior.
> 
> e.g.
> 
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 3732ee9eb0d4..7563feab1a11 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -893,6 +893,17 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
>                 data->cmpidr_to_idx[index] = c;
>         }
> 
> +       kvm_for_each_vcpu(c, vcpu, kvm) {
> +               u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
> +               u16 index = kvm_mpidr_index(data, aff);
> +
> +               if (data->cmpidr_to_idx[index] != c) {
> +                       pr_warn("Multiple vCPUs share the same MPIDR value, "
> +                               "it may cause the guest to hang or run slower\n");
> +                       break;
> +               }
> +       }
> +

That's not reporting anything to userspace. That's just screaming in
the kernel log, and a random user does not have access to that.

If you wanted the user to take notice, you'd need to fail the entry
into the guest.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-06-18 12:32 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-11 14:40 [PATCH v2 0/2] KVM: arm64: Fix MPIDR lookup for unreset vCPUs fuqiang wang
2026-06-11 14:40 ` [PATCH v2 1/2] arm64: Add MPIDR_EL1 RES1 definitions fuqiang wang
2026-06-11 14:40 ` [PATCH v2 2/2] KVM: arm64: Skip unreset vCPUs in MPIDR lookup table fuqiang wang
2026-06-14  9:26   ` Marc Zyngier
2026-06-15  4:20     ` Oliver Upton
2026-06-15 10:08       ` Marc Zyngier
2026-06-18 11:38         ` fuqiang wang
2026-06-18 12:32           ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.