diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2014-07-08 07:09:07 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2014-09-18 21:48:58 -0400 |
commit | a98f26f183801685ef57333de4bafd4bbc692c7c (patch) | |
tree | 8b33a5d7d13d8c2f507223b548b766ba16d559b1 /virt | |
parent | 4956f2bc1fdee4bc336532f3f34635a8534cedfd (diff) |
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>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/vgic.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index ac2b44d58e60..b6fab0f25f3b 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -2253,6 +2253,36 @@ static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | |||
2253 | 2253 | ||
2254 | return vgic_attr_regs_access(dev, attr, ®, true); | 2254 | return vgic_attr_regs_access(dev, attr, ®, true); |
2255 | } | 2255 | } |
2256 | case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: { | ||
2257 | u32 __user *uaddr = (u32 __user *)(long)attr->addr; | ||
2258 | u32 val; | ||
2259 | int ret = 0; | ||
2260 | |||
2261 | if (get_user(val, uaddr)) | ||
2262 | return -EFAULT; | ||
2263 | |||
2264 | /* | ||
2265 | * We require: | ||
2266 | * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs | ||
2267 | * - at most 1024 interrupts | ||
2268 | * - a multiple of 32 interrupts | ||
2269 | */ | ||
2270 | if (val < (VGIC_NR_PRIVATE_IRQS + 32) || | ||
2271 | val > VGIC_MAX_IRQS || | ||
2272 | (val & 31)) | ||
2273 | return -EINVAL; | ||
2274 | |||
2275 | mutex_lock(&dev->kvm->lock); | ||
2276 | |||
2277 | if (vgic_initialized(dev->kvm) || dev->kvm->arch.vgic.nr_irqs) | ||
2278 | ret = -EBUSY; | ||
2279 | else | ||
2280 | dev->kvm->arch.vgic.nr_irqs = val; | ||
2281 | |||
2282 | mutex_unlock(&dev->kvm->lock); | ||
2283 | |||
2284 | return ret; | ||
2285 | } | ||
2256 | 2286 | ||
2257 | } | 2287 | } |
2258 | 2288 | ||
@@ -2289,6 +2319,11 @@ static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | |||
2289 | r = put_user(reg, uaddr); | 2319 | r = put_user(reg, uaddr); |
2290 | break; | 2320 | break; |
2291 | } | 2321 | } |
2322 | case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: { | ||
2323 | u32 __user *uaddr = (u32 __user *)(long)attr->addr; | ||
2324 | r = put_user(dev->kvm->arch.vgic.nr_irqs, uaddr); | ||
2325 | break; | ||
2326 | } | ||
2292 | 2327 | ||
2293 | } | 2328 | } |
2294 | 2329 | ||
@@ -2325,6 +2360,8 @@ static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | |||
2325 | case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: | 2360 | case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: |
2326 | offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK; | 2361 | offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK; |
2327 | return vgic_has_attr_regs(vgic_cpu_ranges, offset); | 2362 | return vgic_has_attr_regs(vgic_cpu_ranges, offset); |
2363 | case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: | ||
2364 | return 0; | ||
2328 | } | 2365 | } |
2329 | return -ENXIO; | 2366 | return -ENXIO; |
2330 | } | 2367 | } |