Per-vCPU vLPI enable, disable, and query ioctls should finish reading or writing the state of their target vCPU before another operation does the same.
Implement a vlpi_toggle_mutex to be acquired whenever KVM_ENABLE_VCPU_VLPI, KVM_DISABLE_VCPU_VLPI, or KVM_QUERY_VCPU_VLPI ioctls are handled.
Signed-off-by: Maximilian Dittgen mdittgen@amazon.com --- arch/arm64/kvm/arm.c | 3 +++ arch/arm64/kvm/vgic/vgic-v4.c | 5 +++++ include/kvm/arm_vgic.h | 3 +++ 3 files changed, 11 insertions(+)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 180eaa4165e9..c2224664f05e 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1961,6 +1961,7 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) if (!vcpu) return -EINVAL;
+ guard(mutex)(&vcpu->arch.vgic_cpu.vlpi_toggle_mutex); return kvm_vgic_enable_vcpu_vlpi(vcpu); } case KVM_DISABLE_VCPU_VLPI: { @@ -1974,6 +1975,7 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) if (!vcpu) return -EINVAL;
+ guard(mutex)(&vcpu->arch.vgic_cpu.vlpi_toggle_mutex); return kvm_vgic_disable_vcpu_vlpi(vcpu); } case KVM_QUERY_VCPU_VLPI: { @@ -1987,6 +1989,7 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) if (!vcpu) return -EINVAL;
+ guard(mutex)(&vcpu->arch.vgic_cpu.vlpi_toggle_mutex); return kvm_vgic_query_vcpu_vlpi(vcpu); } default: diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c index 39fababf2861..b7dbc1789c90 100644 --- a/arch/arm64/kvm/vgic/vgic-v4.c +++ b/arch/arm64/kvm/vgic/vgic-v4.c @@ -325,6 +325,11 @@ int vgic_v4_init(struct kvm *kvm) if (!dist->its_vm.vprop_page) ret = -ENOMEM; } + + /* vLPI toggle mutex */ + kvm_for_each_vcpu(i, vcpu, kvm) + mutex_init(&vcpu->arch.vgic_cpu.vlpi_toggle_mutex); + #endif if (ret) vgic_v4_teardown(kvm); diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 18a49c4b83f8..c9dad0e84c77 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -372,6 +372,9 @@ struct vgic_cpu { u32 rdreg_index; atomic_t syncr_busy;
+ /* Ensure atomicity of per-vCPU vLPI enable/disable/query operations */ + struct mutex vlpi_toggle_mutex; + /* Contains the attributes and gpa of the LPI pending tables. */ u64 pendbaser; /* GICR_CTLR.{ENABLE_LPIS,RWP} */