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