4 * Copyright (C) 2015 ARM Ltd.
5 * Author: Marc Zyngier <marc.zyngier@arm.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 #include <linux/kvm_host.h>
17 #include <kvm/arm_vgic.h>
18 #include <linux/uaccess.h>
23 static int vgic_set_common_attr(struct kvm_device
*dev
,
24 struct kvm_device_attr
*attr
)
28 switch (attr
->group
) {
29 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS
: {
30 u32 __user
*uaddr
= (u32 __user
*)(long)attr
->addr
;
34 if (get_user(val
, uaddr
))
39 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
40 * - at most 1024 interrupts
41 * - a multiple of 32 interrupts
43 if (val
< (VGIC_NR_PRIVATE_IRQS
+ 32) ||
44 val
> VGIC_MAX_RESERVED
||
48 mutex_lock(&dev
->kvm
->lock
);
50 if (vgic_ready(dev
->kvm
) || dev
->kvm
->arch
.vgic
.nr_spis
)
53 dev
->kvm
->arch
.vgic
.nr_spis
=
54 val
- VGIC_NR_PRIVATE_IRQS
;
56 mutex_unlock(&dev
->kvm
->lock
);
60 case KVM_DEV_ARM_VGIC_GRP_CTRL
: {
62 case KVM_DEV_ARM_VGIC_CTRL_INIT
:
63 mutex_lock(&dev
->kvm
->lock
);
64 r
= vgic_init(dev
->kvm
);
65 mutex_unlock(&dev
->kvm
->lock
);
75 static int vgic_get_common_attr(struct kvm_device
*dev
,
76 struct kvm_device_attr
*attr
)
80 switch (attr
->group
) {
81 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS
: {
82 u32 __user
*uaddr
= (u32 __user
*)(long)attr
->addr
;
84 r
= put_user(dev
->kvm
->arch
.vgic
.nr_spis
+
85 VGIC_NR_PRIVATE_IRQS
, uaddr
);
93 static int vgic_create(struct kvm_device
*dev
, u32 type
)
95 return kvm_vgic_create(dev
->kvm
, type
);
98 static void vgic_destroy(struct kvm_device
*dev
)
103 void kvm_register_vgic_device(unsigned long type
)
106 case KVM_DEV_TYPE_ARM_VGIC_V2
:
107 kvm_register_device_ops(&kvm_arm_vgic_v2_ops
,
108 KVM_DEV_TYPE_ARM_VGIC_V2
);
110 #ifdef CONFIG_KVM_ARM_VGIC_V3
111 case KVM_DEV_TYPE_ARM_VGIC_V3
:
112 kvm_register_device_ops(&kvm_arm_vgic_v3_ops
,
113 KVM_DEV_TYPE_ARM_VGIC_V3
);
121 static int vgic_v2_set_attr(struct kvm_device
*dev
,
122 struct kvm_device_attr
*attr
)
126 ret
= vgic_set_common_attr(dev
, attr
);
131 static int vgic_v2_get_attr(struct kvm_device
*dev
,
132 struct kvm_device_attr
*attr
)
136 ret
= vgic_get_common_attr(dev
, attr
);
140 static int vgic_v2_has_attr(struct kvm_device
*dev
,
141 struct kvm_device_attr
*attr
)
143 switch (attr
->group
) {
144 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS
:
146 case KVM_DEV_ARM_VGIC_GRP_CTRL
:
147 switch (attr
->attr
) {
148 case KVM_DEV_ARM_VGIC_CTRL_INIT
:
155 struct kvm_device_ops kvm_arm_vgic_v2_ops
= {
156 .name
= "kvm-arm-vgic-v2",
157 .create
= vgic_create
,
158 .destroy
= vgic_destroy
,
159 .set_attr
= vgic_v2_set_attr
,
160 .get_attr
= vgic_v2_get_attr
,
161 .has_attr
= vgic_v2_has_attr
,
166 #ifdef CONFIG_KVM_ARM_VGIC_V3
168 static int vgic_v3_set_attr(struct kvm_device
*dev
,
169 struct kvm_device_attr
*attr
)
171 return vgic_set_common_attr(dev
, attr
);
174 static int vgic_v3_get_attr(struct kvm_device
*dev
,
175 struct kvm_device_attr
*attr
)
177 return vgic_get_common_attr(dev
, attr
);
180 static int vgic_v3_has_attr(struct kvm_device
*dev
,
181 struct kvm_device_attr
*attr
)
183 switch (attr
->group
) {
184 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS
:
186 case KVM_DEV_ARM_VGIC_GRP_CTRL
:
187 switch (attr
->attr
) {
188 case KVM_DEV_ARM_VGIC_CTRL_INIT
:
195 struct kvm_device_ops kvm_arm_vgic_v3_ops
= {
196 .name
= "kvm-arm-vgic-v3",
197 .create
= vgic_create
,
198 .destroy
= vgic_destroy
,
199 .set_attr
= vgic_v3_set_attr
,
200 .get_attr
= vgic_v3_get_attr
,
201 .has_attr
= vgic_v3_has_attr
,
204 #endif /* CONFIG_KVM_ARM_VGIC_V3 */