KVM: arm64: Refactor PMU attribute error handling
authorMarc Zyngier <maz@kernel.org>
Thu, 12 Mar 2020 17:27:36 +0000 (17:27 +0000)
committerMarc Zyngier <maz@kernel.org>
Tue, 29 Sep 2020 13:19:38 +0000 (14:19 +0100)
The PMU emulation error handling is pretty messy when dealing with
attributes. Let's refactor it so that we have less duplication,
and that it is easy to extend later on.

A functional change is that kvm_arm_pmu_v3_init() used to return
-ENXIO when the PMU feature wasn't set. The error is now reported
as -ENODEV, matching the documentation. -ENXIO is still returned
when the interrupt isn't properly configured.

Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/pmu-emul.c

index f0d0312c0a552c46f85d7e9e93fc9dbf26fbec21..363f188fb7072c0a78a2d67b36fdd2acffa6f06c 100644 (file)
@@ -735,15 +735,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 
 static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 {
-       if (!kvm_arm_support_pmu_v3())
-               return -ENODEV;
-
-       if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
-               return -ENXIO;
-
-       if (vcpu->arch.pmu.created)
-               return -EBUSY;
-
        if (irqchip_in_kernel(vcpu->kvm)) {
                int ret;
 
@@ -796,6 +787,13 @@ static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 
 int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 {
+       if (!kvm_arm_support_pmu_v3() ||
+           !test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
+               return -ENODEV;
+
+       if (vcpu->arch.pmu.created)
+               return -EBUSY;
+
        switch (attr->attr) {
        case KVM_ARM_VCPU_PMU_V3_IRQ: {
                int __user *uaddr = (int __user *)(long)attr->addr;
@@ -804,9 +802,6 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
                if (!irqchip_in_kernel(vcpu->kvm))
                        return -EINVAL;
 
-               if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
-                       return -ENODEV;
-
                if (get_user(irq, uaddr))
                        return -EFAULT;