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 */