summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorEric Auger <eric.auger@linaro.org>2015-12-21 10:33:22 -0500
committerChristoffer Dall <christoffer.dall@linaro.org>2016-05-20 09:40:00 -0400
commitfca256026bb0d78991f975a7d4a3f601b7234401 (patch)
treeb847f2667ca0718a0e8e1071562a60939eb67c1c /virt
parentc86c772191d7e65f873e6908e9604b31168936cd (diff)
KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS
This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This modality is supported by both VGIC V2 and V3 KVM device as will be other groups, hence the introduction of common helpers. Signed-off-by: Eric Auger <eric.auger@linaro.org> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-kvm-device.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ff332f34a221..05ff925f5377 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -15,9 +15,69 @@
15 */ 15 */
16#include <linux/kvm_host.h> 16#include <linux/kvm_host.h>
17#include <kvm/arm_vgic.h> 17#include <kvm/arm_vgic.h>
18#include <linux/uaccess.h>
19#include "vgic.h"
18 20
19/* common helpers */ 21/* common helpers */
20 22
23static int vgic_set_common_attr(struct kvm_device *dev,
24 struct kvm_device_attr *attr)
25{
26 switch (attr->group) {
27 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
28 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
29 u32 val;
30 int ret = 0;
31
32 if (get_user(val, uaddr))
33 return -EFAULT;
34
35 /*
36 * We require:
37 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
38 * - at most 1024 interrupts
39 * - a multiple of 32 interrupts
40 */
41 if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
42 val > VGIC_MAX_RESERVED ||
43 (val & 31))
44 return -EINVAL;
45
46 mutex_lock(&dev->kvm->lock);
47
48 if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
49 ret = -EBUSY;
50 else
51 dev->kvm->arch.vgic.nr_spis =
52 val - VGIC_NR_PRIVATE_IRQS;
53
54 mutex_unlock(&dev->kvm->lock);
55
56 return ret;
57 }
58 }
59
60 return -ENXIO;
61}
62
63static int vgic_get_common_attr(struct kvm_device *dev,
64 struct kvm_device_attr *attr)
65{
66 int r = -ENXIO;
67
68 switch (attr->group) {
69 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
70 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
71
72 r = put_user(dev->kvm->arch.vgic.nr_spis +
73 VGIC_NR_PRIVATE_IRQS, uaddr);
74 break;
75 }
76 }
77
78 return r;
79}
80
21static int vgic_create(struct kvm_device *dev, u32 type) 81static int vgic_create(struct kvm_device *dev, u32 type)
22{ 82{
23 return kvm_vgic_create(dev->kvm, type); 83 return kvm_vgic_create(dev->kvm, type);
@@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
49static int vgic_v2_set_attr(struct kvm_device *dev, 109static int vgic_v2_set_attr(struct kvm_device *dev,
50 struct kvm_device_attr *attr) 110 struct kvm_device_attr *attr)
51{ 111{
52 return -ENXIO; 112 int ret;
113
114 ret = vgic_set_common_attr(dev, attr);
115 return ret;
116
53} 117}
54 118
55static int vgic_v2_get_attr(struct kvm_device *dev, 119static int vgic_v2_get_attr(struct kvm_device *dev,
56 struct kvm_device_attr *attr) 120 struct kvm_device_attr *attr)
57{ 121{
58 return -ENXIO; 122 int ret;
123
124 ret = vgic_get_common_attr(dev, attr);
125 return ret;
59} 126}
60 127
61static int vgic_v2_has_attr(struct kvm_device *dev, 128static int vgic_v2_has_attr(struct kvm_device *dev,
62 struct kvm_device_attr *attr) 129 struct kvm_device_attr *attr)
63{ 130{
131 switch (attr->group) {
132 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
133 return 0;
134 }
64 return -ENXIO; 135 return -ENXIO;
65} 136}
66 137
@@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
80static int vgic_v3_set_attr(struct kvm_device *dev, 151static int vgic_v3_set_attr(struct kvm_device *dev,
81 struct kvm_device_attr *attr) 152 struct kvm_device_attr *attr)
82{ 153{
83 return -ENXIO; 154 return vgic_set_common_attr(dev, attr);
84} 155}
85 156
86static int vgic_v3_get_attr(struct kvm_device *dev, 157static int vgic_v3_get_attr(struct kvm_device *dev,
87 struct kvm_device_attr *attr) 158 struct kvm_device_attr *attr)
88{ 159{
89 return -ENXIO; 160 return vgic_get_common_attr(dev, attr);
90} 161}
91 162
92static int vgic_v3_has_attr(struct kvm_device *dev, 163static int vgic_v3_has_attr(struct kvm_device *dev,
93 struct kvm_device_attr *attr) 164 struct kvm_device_attr *attr)
94{ 165{
166 switch (attr->group) {
167 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
168 return 0;
169 }
95 return -ENXIO; 170 return -ENXIO;
96} 171}
97 172