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 | } |
