]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: vgic-v3: Consolidate MAINT_IRQ handling
authorOliver Upton <oliver.upton@linux.dev>
Thu, 24 Jul 2025 06:28:01 +0000 (23:28 -0700)
committerOliver Upton <oliver.upton@linux.dev>
Sat, 26 Jul 2025 15:37:45 +0000 (08:37 -0700)
Consolidate the duplicated handling of the VGICv3 maintenance IRQ
attribute as a regular GICv3 attribute, as it is neither a register nor
a common attribute. As this is now handled separately from the VGIC
registers, the locking is relaxed to only acquire the intended
config_lock.

Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250724062805.2658919-3-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/vgic/vgic-kvm-device.c

index f9ae790163fb0d0151433d968594ba9a7ed4fb9b..00c011cc86278a8aec298320166459d7d5648165 100644 (file)
@@ -303,12 +303,6 @@ static int vgic_get_common_attr(struct kvm_device *dev,
                             VGIC_NR_PRIVATE_IRQS, uaddr);
                break;
        }
-       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ: {
-               u32 __user *uaddr = (u32 __user *)(long)attr->addr;
-
-               r = put_user(dev->kvm->arch.vgic.mi_intid, uaddr);
-               break;
-       }
        }
 
        return r;
@@ -523,7 +517,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
        struct vgic_reg_attr reg_attr;
        gpa_t addr;
        struct kvm_vcpu *vcpu;
-       bool uaccess, post_init = true;
+       bool uaccess;
        u32 val;
        int ret;
 
@@ -539,9 +533,6 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
                /* Sysregs uaccess is performed by the sysreg handling code */
                uaccess = false;
                break;
-       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
-               post_init = false;
-               fallthrough;
        default:
                uaccess = true;
        }
@@ -561,7 +552,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
 
        mutex_lock(&dev->kvm->arch.config_lock);
 
-       if (post_init != vgic_initialized(dev->kvm)) {
+       if (!vgic_initialized(dev->kvm)) {
                ret = -EBUSY;
                goto out;
        }
@@ -591,19 +582,6 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
                }
                break;
        }
-       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
-               if (!is_write) {
-                       val = dev->kvm->arch.vgic.mi_intid;
-                       ret = 0;
-                       break;
-               }
-
-               ret = -EINVAL;
-               if ((val < VGIC_NR_PRIVATE_IRQS) && (val >= VGIC_NR_SGIS)) {
-                       dev->kvm->arch.vgic.mi_intid = val;
-                       ret = 0;
-               }
-               break;
        default:
                ret = -EINVAL;
                break;
@@ -630,8 +608,24 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
        case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
        case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
        case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO:
-       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
                return vgic_v3_attr_regs_access(dev, attr, true);
+       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ: {
+               u32 __user *uaddr = (u32 __user *)attr->addr;
+               u32 val;
+
+               if (get_user(val, uaddr))
+                       return -EFAULT;
+
+               guard(mutex)(&dev->kvm->arch.config_lock);
+               if (vgic_initialized(dev->kvm))
+                       return -EBUSY;
+
+               if (!irq_is_ppi(val))
+                       return -EINVAL;
+
+               dev->kvm->arch.vgic.mi_intid = val;
+               return 0;
+       }
        default:
                return vgic_set_common_attr(dev, attr);
        }
@@ -645,8 +639,13 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
        case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
        case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
        case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO:
-       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
                return vgic_v3_attr_regs_access(dev, attr, false);
+       case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ: {
+               u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+               guard(mutex)(&dev->kvm->arch.config_lock);
+               return put_user(dev->kvm->arch.vgic.mi_intid, uaddr);
+       }
        default:
                return vgic_get_common_attr(dev, attr);
        }