arm/arm64: KVM: vgic: make number of irqs a configurable attribute
In order to make the number of interrupts configurable, use the new fancy device management API to add KVM_DEV_ARM_VGIC_GRP_NR_IRQS as a VGIC configurable attribute. Userspace can now specify the exact size of the GIC (by increments of 32 interrupts). Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
4956f2bc1f
commit
a98f26f183
@ -71,3 +71,13 @@ Groups:
|
||||
Errors:
|
||||
-ENODEV: Getting or setting this register is not yet supported
|
||||
-EBUSY: One or more VCPUs are running
|
||||
|
||||
KVM_DEV_ARM_VGIC_GRP_NR_IRQS
|
||||
Attributes:
|
||||
A value describing the number of interrupts (SGI, PPI and SPI) for
|
||||
this GIC instance, ranging from 64 to 1024, in increments of 32.
|
||||
|
||||
Errors:
|
||||
-EINVAL: Value set is out of the expected range
|
||||
-EBUSY: Value has already be set, or GIC has already been initialized
|
||||
with default values.
|
||||
|
@ -174,6 +174,7 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
@ -160,6 +160,7 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
@ -2253,6 +2253,36 @@ static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||
|
||||
return vgic_attr_regs_access(dev, attr, ®, true);
|
||||
}
|
||||
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
|
||||
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
|
||||
if (get_user(val, uaddr))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* We require:
|
||||
* - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
|
||||
* - at most 1024 interrupts
|
||||
* - a multiple of 32 interrupts
|
||||
*/
|
||||
if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
|
||||
val > VGIC_MAX_IRQS ||
|
||||
(val & 31))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->kvm->lock);
|
||||
|
||||
if (vgic_initialized(dev->kvm) || dev->kvm->arch.vgic.nr_irqs)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
dev->kvm->arch.vgic.nr_irqs = val;
|
||||
|
||||
mutex_unlock(&dev->kvm->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2289,6 +2319,11 @@ static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||
r = put_user(reg, uaddr);
|
||||
break;
|
||||
}
|
||||
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
|
||||
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
|
||||
r = put_user(dev->kvm->arch.vgic.nr_irqs, uaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2325,6 +2360,8 @@ static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
|
||||
offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
|
||||
return vgic_has_attr_regs(vgic_cpu_ranges, offset);
|
||||
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
|
||||
return 0;
|
||||
}
|
||||
return -ENXIO;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user