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 | |
| 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>
| -rw-r--r-- | Documentation/virtual/kvm/devices/arm-vgic.txt | 10 | ||||
| -rw-r--r-- | arch/arm/include/uapi/asm/kvm.h | 1 | ||||
| -rw-r--r-- | arch/arm64/include/uapi/asm/kvm.h | 1 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic.c | 37 |
4 files changed, 49 insertions, 0 deletions
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt index 7f4e91b1316b..df8b0c7540b6 100644 --- a/Documentation/virtual/kvm/devices/arm-vgic.txt +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt | |||
| @@ -71,3 +71,13 @@ Groups: | |||
| 71 | Errors: | 71 | Errors: |
| 72 | -ENODEV: Getting or setting this register is not yet supported | 72 | -ENODEV: Getting or setting this register is not yet supported |
| 73 | -EBUSY: One or more VCPUs are running | 73 | -EBUSY: One or more VCPUs are running |
| 74 | |||
| 75 | KVM_DEV_ARM_VGIC_GRP_NR_IRQS | ||
| 76 | Attributes: | ||
| 77 | A value describing the number of interrupts (SGI, PPI and SPI) for | ||
| 78 | this GIC instance, ranging from 64 to 1024, in increments of 32. | ||
| 79 | |||
| 80 | Errors: | ||
| 81 | -EINVAL: Value set is out of the expected range | ||
| 82 | -EBUSY: Value has already be set, or GIC has already been initialized | ||
| 83 | with default values. | ||
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 51257fda254b..09ee408c1a67 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h | |||
| @@ -174,6 +174,7 @@ struct kvm_arch_memory_slot { | |||
| 174 | #define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) | 174 | #define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
| 175 | #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 | 175 | #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 |
| 176 | #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) | 176 | #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) |
| 177 | #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 | ||
| 177 | 178 | ||
| 178 | /* KVM_IRQ_LINE irq field index values */ | 179 | /* KVM_IRQ_LINE irq field index values */ |
| 179 | #define KVM_ARM_IRQ_TYPE_SHIFT 24 | 180 | #define KVM_ARM_IRQ_TYPE_SHIFT 24 |
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index f4ec5a674d05..8e38878c87c6 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h | |||
| @@ -160,6 +160,7 @@ struct kvm_arch_memory_slot { | |||
| 160 | #define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) | 160 | #define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
| 161 | #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 | 161 | #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 |
| 162 | #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) | 162 | #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) |
| 163 | #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 | ||
| 163 | 164 | ||
| 164 | /* KVM_IRQ_LINE irq field index values */ | 165 | /* KVM_IRQ_LINE irq field index values */ |
| 165 | #define KVM_ARM_IRQ_TYPE_SHIFT 24 | 166 | #define KVM_ARM_IRQ_TYPE_SHIFT 24 |
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 | } |
