mbox series

[v3,0/4] KVM: arm64: Fix vcpu->mutex v. kvm->lock inversion

Message ID 20230327164747.2466958-1-oliver.upton@linux.dev (mailing list archive)
Headers show
Series KVM: arm64: Fix vcpu->mutex v. kvm->lock inversion | expand

Message

Oliver Upton March 27, 2023, 4:47 p.m. UTC
As it so happens, lock ordering in KVM/arm64 is completely backwards.
There's a significant amount of VM-wide state that needs to be accessed
from the context of a vCPU. Until now, this was accomplished by
acquiring the kvm->lock, but that cannot be nested within vcpu->mutex.

This series fixes the issue with some fine-grained locking for MP state
and a new, dedicated mutex that can nest with both kvm->lock and
vcpu->mutex.

Tested with kvmtool and QEMU scaled up to 64 vCPUs on a kernel w/
lockdep enabled. Applies to kvmarm-fixes-6.3-2.

Please note that these changes will most likely be taken in the 6.4
merge window and not as a fixup during 6.3. After discussing with Marc
we agreed that letting these patches marinade in -next for a while is
probably best as it is quite an overhaul to our locking. Additionally,
there is no evidence of actual deadlocks occurring in the wild, likely
because we _always_ ordered the locks backwards, hence the only breakage
at the moment is lockdep.

Also, Jeremy, I chose to omit your Tested-by tag on the last patch as it
was rather significantly changed from when you last took it for a spin.

v1: http://lore.kernel.org/kvmarm/20230308083947.3760066-1-oliver.upton@linux.dev
v2: https://lore.kernel.org/kvmarm/20230316211412.2651555-1-oliver.upton@linux.dev/

v2 -> v3:
 - Continue to acquire the kvm->lock where we must protect against a
   concurrent vCPU creation (Marc)
 - Plug a few missing WRITE_ONCE() promotions for mp_state (Marc)
 - Hold the mp_state_lock when reading reset_state (Marc)
 - Fix the unguarded write to mp_state in kvm_prepare_system_event()
 - Collect Jeremy's Tested-by tags (thanks!)

v1 -> v2:
 - Add a dedicated lock for serializing writes to MP state
 - Inform lockdep of acquisition order at time of VM/vCPU creation
 - Plug a race with GIC creation (Sean)
 - Use the config_lock in GIC ITS flows as well

Oliver Upton (4):
  KVM: arm64: Avoid vcpu->mutex v. kvm->lock inversion in CPU_ON
  KVM: arm64: Avoid lock inversion when setting the VM register width
  KVM: arm64: Use config_lock to protect data ordered against KVM_RUN
  KVM: arm64: Use config_lock to protect vgic state

 arch/arm64/include/asm/kvm_host.h     |  4 ++
 arch/arm64/kvm/arm.c                  | 53 +++++++++++++++++++++------
 arch/arm64/kvm/guest.c                |  2 +
 arch/arm64/kvm/hypercalls.c           |  4 +-
 arch/arm64/kvm/pmu-emul.c             | 23 +++---------
 arch/arm64/kvm/psci.c                 | 28 ++++++++------
 arch/arm64/kvm/reset.c                | 15 ++++----
 arch/arm64/kvm/vgic/vgic-debug.c      |  8 ++--
 arch/arm64/kvm/vgic/vgic-init.c       | 36 +++++++++++-------
 arch/arm64/kvm/vgic/vgic-its.c        | 18 ++++++---
 arch/arm64/kvm/vgic/vgic-kvm-device.c | 47 ++++++++++++++----------
 arch/arm64/kvm/vgic/vgic-mmio-v3.c    |  4 +-
 arch/arm64/kvm/vgic/vgic-mmio.c       | 12 +++---
 arch/arm64/kvm/vgic/vgic-v4.c         | 11 +++---
 arch/arm64/kvm/vgic/vgic.c            | 12 +++---
 15 files changed, 168 insertions(+), 109 deletions(-)


base-commit: 8c2e8ac8ad4be68409e806ce1cc78fc7a04539f3

Comments

Marc Zyngier March 30, 2023, 6:36 p.m. UTC | #1
On Mon, 27 Mar 2023 16:47:43 +0000, Oliver Upton wrote:
> As it so happens, lock ordering in KVM/arm64 is completely backwards.
> There's a significant amount of VM-wide state that needs to be accessed
> from the context of a vCPU. Until now, this was accomplished by
> acquiring the kvm->lock, but that cannot be nested within vcpu->mutex.
> 
> This series fixes the issue with some fine-grained locking for MP state
> and a new, dedicated mutex that can nest with both kvm->lock and
> vcpu->mutex.
> 
> [...]

Applied to next, thanks!

[1/4] KVM: arm64: Avoid vcpu->mutex v. kvm->lock inversion in CPU_ON
      commit: 0acc7239c20a8401b8968c2adace8f7c9b0295ae
[2/4] KVM: arm64: Avoid lock inversion when setting the VM register width
      commit: c43120afb5c66a3465c7468f5cf9806a26484cde
[3/4] KVM: arm64: Use config_lock to protect data ordered against KVM_RUN
      commit: 4bba7f7def6f278266dadf845da472cfbfed784e
[4/4] KVM: arm64: Use config_lock to protect vgic state
      commit: f00327731131d1b5aa6a1aa9f50bcf8d620ace4c

Cheers,

	M.