* [PATCH 0/5] KVM: arm64: vgic fixes for 6.7
@ 2023-12-07 15:11 Marc Zyngier
2023-12-07 15:11 ` [PATCH 1/5] KVM: arm64: vgic: Simplify kvm_vgic_destroy() Marc Zyngier
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Marc Zyngier @ 2023-12-07 15:11 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Will Deacon, vdonnefort
It appears that under some cirumstances, the lifetime of a vcpu
doesn't correctly align with that of the structure describing the
redistributor associated with that vcpu. That's not great.
Fixing it is, unfortunately, not as trivial as it appears as the
required locking gets in the way.
The first two patches in this series amend that locking so that the
third patch, which is the actual fix, becomes almost trivial. The last
two patches are more cosmetic and only add assertions that helped me
debugging the whole thing.
I've earmarked the first 3 patches as stable candidates, and would
love to see them in 6.7. Patches on top of -rc4.
Marc Zyngier (5):
KVM: arm64: vgic: Simplify kvm_vgic_destroy()
KVM: arm64: vgic: Add a non-locking primitive for
kvm_vgic_vcpu_destroy()
KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
KVM: arm64: vgic: Ensure that slots_lock is held in
vgic_register_all_redist_iodevs()
KVM: Convert comment into an assertion in kvm_io_bus_register_dev()
arch/arm64/kvm/arm.c | 2 +-
arch/arm64/kvm/vgic/vgic-init.c | 47 ++++++++++++++++++------------
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 4 ++-
arch/arm64/kvm/vgic/vgic.h | 1 +
virt/kvm/kvm_main.c | 3 +-
5 files changed, 36 insertions(+), 21 deletions(-)
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/5] KVM: arm64: vgic: Simplify kvm_vgic_destroy()
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
@ 2023-12-07 15:11 ` Marc Zyngier
2023-12-07 15:11 ` [PATCH 2/5] KVM: arm64: vgic: Add a non-locking primitive for kvm_vgic_vcpu_destroy() Marc Zyngier
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Marc Zyngier @ 2023-12-07 15:11 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Will Deacon, vdonnefort, stable
When destroying a vgic, we have rather cumbersome rules about
when slots_lock and config_lock are held, resulting in fun
buglets.
The first port of call is to simplify kvm_vgic_map_resources()
so that there is only one call to kvm_vgic_destroy() instead of
two, with the second only holding half of the locks.
For that, we kill the non-locking primitive and move the call
outside of the locking altogether. This doesn't change anything
(we re-acquire the locks and teardown the whole vgic), and
simplifies the code significantly.
Cc: stable@vger.kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index c8c3cb812783..ad7e86879eb9 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -382,26 +382,24 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
}
-static void __kvm_vgic_destroy(struct kvm *kvm)
+void kvm_vgic_destroy(struct kvm *kvm)
{
struct kvm_vcpu *vcpu;
unsigned long i;
- lockdep_assert_held(&kvm->arch.config_lock);
+ mutex_lock(&kvm->slots_lock);
vgic_debug_destroy(kvm);
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_vgic_vcpu_destroy(vcpu);
+ mutex_lock(&kvm->arch.config_lock);
+
kvm_vgic_dist_destroy(kvm);
-}
-void kvm_vgic_destroy(struct kvm *kvm)
-{
- mutex_lock(&kvm->arch.config_lock);
- __kvm_vgic_destroy(kvm);
mutex_unlock(&kvm->arch.config_lock);
+ mutex_unlock(&kvm->slots_lock);
}
/**
@@ -469,25 +467,26 @@ int kvm_vgic_map_resources(struct kvm *kvm)
type = VGIC_V3;
}
- if (ret) {
- __kvm_vgic_destroy(kvm);
+ if (ret)
goto out;
- }
+
dist->ready = true;
dist_base = dist->vgic_dist_base;
mutex_unlock(&kvm->arch.config_lock);
ret = vgic_register_dist_iodev(kvm, dist_base, type);
- if (ret) {
+ if (ret)
kvm_err("Unable to register VGIC dist MMIO regions\n");
- kvm_vgic_destroy(kvm);
- }
- mutex_unlock(&kvm->slots_lock);
- return ret;
+ goto out_slots;
out:
mutex_unlock(&kvm->arch.config_lock);
+out_slots:
mutex_unlock(&kvm->slots_lock);
+
+ if (ret)
+ kvm_vgic_destroy(kvm);
+
return ret;
}
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] KVM: arm64: vgic: Add a non-locking primitive for kvm_vgic_vcpu_destroy()
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
2023-12-07 15:11 ` [PATCH 1/5] KVM: arm64: vgic: Simplify kvm_vgic_destroy() Marc Zyngier
@ 2023-12-07 15:11 ` Marc Zyngier
2023-12-07 15:11 ` [PATCH 3/5] KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy Marc Zyngier
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Marc Zyngier @ 2023-12-07 15:11 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Will Deacon, vdonnefort, stable
As we are going to need to call into kvm_vgic_vcpu_destroy() without
prior holding of the slots_lock, introduce __kvm_vgic_vcpu_destroy()
as a non-locking primitive of kvm_vgic_vcpu_destroy().
Cc: stable@vger.kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index ad7e86879eb9..a86f300321a7 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -368,7 +368,7 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
vgic_v4_teardown(kvm);
}
-void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+static void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
@@ -382,6 +382,15 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
}
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+
+ mutex_lock(&kvm->slots_lock);
+ __kvm_vgic_vcpu_destroy(vcpu);
+ mutex_unlock(&kvm->slots_lock);
+}
+
void kvm_vgic_destroy(struct kvm *kvm)
{
struct kvm_vcpu *vcpu;
@@ -392,7 +401,7 @@ void kvm_vgic_destroy(struct kvm *kvm)
vgic_debug_destroy(kvm);
kvm_for_each_vcpu(i, vcpu, kvm)
- kvm_vgic_vcpu_destroy(vcpu);
+ __kvm_vgic_vcpu_destroy(vcpu);
mutex_lock(&kvm->arch.config_lock);
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
2023-12-07 15:11 ` [PATCH 1/5] KVM: arm64: vgic: Simplify kvm_vgic_destroy() Marc Zyngier
2023-12-07 15:11 ` [PATCH 2/5] KVM: arm64: vgic: Add a non-locking primitive for kvm_vgic_vcpu_destroy() Marc Zyngier
@ 2023-12-07 15:11 ` Marc Zyngier
2023-12-07 15:12 ` [PATCH 4/5] KVM: arm64: vgic: Ensure that slots_lock is held in vgic_register_all_redist_iodevs() Marc Zyngier
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Marc Zyngier @ 2023-12-07 15:11 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Will Deacon, vdonnefort, stable
When failing to create a vcpu because (for example) it has a
duplicate vcpu_id, we destroy the vcpu. Amusingly, this leaves
the redistributor registered with the KVM_MMIO bus.
This is no good, and we should properly clean the mess. Force
a teardown of the vgic vcpu interface, including the RD device
before returning to the caller.
Cc: stable@vger.kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arm.c | 2 +-
arch/arm64/kvm/vgic/vgic-init.c | 5 ++++-
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +-
arch/arm64/kvm/vgic/vgic.h | 1 +
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index e5f75f1f1085..4796104c4471 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -410,7 +410,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
kvm_timer_vcpu_terminate(vcpu);
kvm_pmu_vcpu_destroy(vcpu);
-
+ kvm_vgic_vcpu_destroy(vcpu);
kvm_arm_vcpu_destroy(vcpu);
}
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index a86f300321a7..e949e1d0fd9f 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -379,7 +379,10 @@ static void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
vgic_flush_pending_lpis(vcpu);
INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
- vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
+ if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ vgic_unregister_redist_iodev(vcpu);
+ vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
+ }
}
void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 89117ba2528a..0f039d46d4fc 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -820,7 +820,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
return ret;
}
-static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
+void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
{
struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 0ab09b0d4440..8d134569d0a1 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -241,6 +241,7 @@ int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq);
int vgic_v3_save_pending_tables(struct kvm *kvm);
int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count);
int vgic_register_redist_iodev(struct kvm_vcpu *vcpu);
+void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu);
bool vgic_v3_check_base(struct kvm *kvm);
void vgic_v3_load(struct kvm_vcpu *vcpu);
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] KVM: arm64: vgic: Ensure that slots_lock is held in vgic_register_all_redist_iodevs()
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
` (2 preceding siblings ...)
2023-12-07 15:11 ` [PATCH 3/5] KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy Marc Zyngier
@ 2023-12-07 15:12 ` Marc Zyngier
2023-12-07 15:12 ` [PATCH 5/5] KVM: Convert comment into an assertion in kvm_io_bus_register_dev() Marc Zyngier
2023-12-12 7:45 ` [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Oliver Upton
5 siblings, 0 replies; 7+ messages in thread
From: Marc Zyngier @ 2023-12-07 15:12 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Will Deacon, vdonnefort
Although we implicitly depend on slots_lock being held when registering
IO devices with the IO bus infrastructure, we don't enforce this
requirement. Make it explicit.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 0f039d46d4fc..a764b0ab8bf9 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -833,6 +833,8 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
unsigned long c;
int ret = 0;
+ lockdep_assert_held(&kvm->slots_lock);
+
kvm_for_each_vcpu(c, vcpu, kvm) {
ret = vgic_register_redist_iodev(vcpu);
if (ret)
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] KVM: Convert comment into an assertion in kvm_io_bus_register_dev()
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
` (3 preceding siblings ...)
2023-12-07 15:12 ` [PATCH 4/5] KVM: arm64: vgic: Ensure that slots_lock is held in vgic_register_all_redist_iodevs() Marc Zyngier
@ 2023-12-07 15:12 ` Marc Zyngier
2023-12-12 7:45 ` [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Oliver Upton
5 siblings, 0 replies; 7+ messages in thread
From: Marc Zyngier @ 2023-12-07 15:12 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Will Deacon, vdonnefort
Instead of having a comment indicating the need to hold slots_lock
when calling kvm_io_bus_register_dev(), make it explicit with
a lockdep assertion.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
virt/kvm/kvm_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 486800a7024b..278d31ae45d8 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -5545,7 +5545,6 @@ int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
return r < 0 ? r : 0;
}
-/* Caller must hold slots_lock. */
int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
int len, struct kvm_io_device *dev)
{
@@ -5553,6 +5552,8 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
struct kvm_io_bus *new_bus, *bus;
struct kvm_io_range range;
+ lockdep_assert_held(&kvm->slots_lock);
+
bus = kvm_get_bus(kvm, bus_idx);
if (!bus)
return -ENOMEM;
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 0/5] KVM: arm64: vgic fixes for 6.7
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
` (4 preceding siblings ...)
2023-12-07 15:12 ` [PATCH 5/5] KVM: Convert comment into an assertion in kvm_io_bus_register_dev() Marc Zyngier
@ 2023-12-12 7:45 ` Oliver Upton
5 siblings, 0 replies; 7+ messages in thread
From: Oliver Upton @ 2023-12-12 7:45 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, kvm, Marc Zyngier
Cc: Oliver Upton, Will Deacon, James Morse, Zenghui Yu, vdonnefort,
Suzuki K Poulose
On Thu, 7 Dec 2023 15:11:56 +0000, Marc Zyngier wrote:
> It appears that under some cirumstances, the lifetime of a vcpu
> doesn't correctly align with that of the structure describing the
> redistributor associated with that vcpu. That's not great.
>
> Fixing it is, unfortunately, not as trivial as it appears as the
> required locking gets in the way.
>
> [...]
Applied to kvmarm/fixes, thanks!
[1/5] KVM: arm64: vgic: Simplify kvm_vgic_destroy()
https://git.kernel.org/kvmarm/kvmarm/c/01ad29d224ff
[2/5] KVM: arm64: vgic: Add a non-locking primitive for kvm_vgic_vcpu_destroy()
https://git.kernel.org/kvmarm/kvmarm/c/d26b9cb33c2d
[3/5] KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
https://git.kernel.org/kvmarm/kvmarm/c/02e3858f08fa
[4/5] KVM: arm64: vgic: Ensure that slots_lock is held in vgic_register_all_redist_iodevs()
https://git.kernel.org/kvmarm/kvmarm/c/6bef365e310a
[5/5] KVM: Convert comment into an assertion in kvm_io_bus_register_dev()
https://git.kernel.org/kvmarm/kvmarm/c/b1a39a718db4
--
Best,
Oliver
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-12-12 7:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-07 15:11 [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Marc Zyngier
2023-12-07 15:11 ` [PATCH 1/5] KVM: arm64: vgic: Simplify kvm_vgic_destroy() Marc Zyngier
2023-12-07 15:11 ` [PATCH 2/5] KVM: arm64: vgic: Add a non-locking primitive for kvm_vgic_vcpu_destroy() Marc Zyngier
2023-12-07 15:11 ` [PATCH 3/5] KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy Marc Zyngier
2023-12-07 15:12 ` [PATCH 4/5] KVM: arm64: vgic: Ensure that slots_lock is held in vgic_register_all_redist_iodevs() Marc Zyngier
2023-12-07 15:12 ` [PATCH 5/5] KVM: Convert comment into an assertion in kvm_io_bus_register_dev() Marc Zyngier
2023-12-12 7:45 ` [PATCH 0/5] KVM: arm64: vgic fixes for 6.7 Oliver Upton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).