@@ -435,6 +435,29 @@ static void kvm_arm_pmu_destroy(struct kvm_device *dev)
kfree(dev);
}
+static bool irq_is_invalid(kvm_device *dev, int irq, bool is_ppi)
+{
+ int i;
+ struct kvm_vcpu *vcpu;
+ struct kvm *kvm = dev->kvm;
+
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ struct kvm_pmu *pmu = &vcpu->arch.pmu;
+
+ if (!kvm_arm_pmu_initialized(vcpu))
+ continue;
+
+ if (is_ppi)
+ if (pmu->irq_num != irq)
+ return true;
+ else
+ if (pmu->irq_num == irq)
+ return true;
+ }
+
+ return false;
+}
+
static int kvm_arm_pmu_set_attr(struct kvm_device *dev,
struct kvm_device_attr *attr)
{
@@ -452,7 +475,8 @@ static int kvm_arm_pmu_set_attr(struct kvm_device *dev,
* the interrupt number is same for all vcpus, while as
a SPI it
* must be different for each vcpu.
*/
- if (reg < VGIC_NR_SGIS || reg >=
dev->kvm->arch.vgic.nr_irqs)
+ if (reg < VGIC_NR_SGIS || reg >=
dev->kvm->arch.vgic.nr_irqs ||
+ irq_is_invalid(dev, reg, reg < VGIC_NR_PRIVATE_IRQS))