]> git.ipfire.org Git - thirdparty/kernel/linux.git/blame - virt/kvm/arm/vgic/vgic-kvm-device.c
KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS
[thirdparty/kernel/linux.git] / virt / kvm / arm / vgic / vgic-kvm-device.c
CommitLineData
c86c7721
EA
1/*
2 * VGIC: KVM DEVICE API
3 *
4 * Copyright (C) 2015 ARM Ltd.
5 * Author: Marc Zyngier <marc.zyngier@arm.com>
6 *
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.
10 *
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.
15 */
16#include <linux/kvm_host.h>
17#include <kvm/arm_vgic.h>
fca25602
EA
18#include <linux/uaccess.h>
19#include "vgic.h"
c86c7721
EA
20
21/* common helpers */
22
fca25602
EA
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
c86c7721
EA
81static int vgic_create(struct kvm_device *dev, u32 type)
82{
83 return kvm_vgic_create(dev->kvm, type);
84}
85
86static void vgic_destroy(struct kvm_device *dev)
87{
88 kfree(dev);
89}
90
91void kvm_register_vgic_device(unsigned long type)
92{
93 switch (type) {
94 case KVM_DEV_TYPE_ARM_VGIC_V2:
95 kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
96 KVM_DEV_TYPE_ARM_VGIC_V2);
97 break;
98#ifdef CONFIG_KVM_ARM_VGIC_V3
99 case KVM_DEV_TYPE_ARM_VGIC_V3:
100 kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
101 KVM_DEV_TYPE_ARM_VGIC_V3);
102 break;
103#endif
104 }
105}
106
107/* V2 ops */
108
109static int vgic_v2_set_attr(struct kvm_device *dev,
110 struct kvm_device_attr *attr)
111{
fca25602
EA
112 int ret;
113
114 ret = vgic_set_common_attr(dev, attr);
115 return ret;
116
c86c7721
EA
117}
118
119static int vgic_v2_get_attr(struct kvm_device *dev,
120 struct kvm_device_attr *attr)
121{
fca25602
EA
122 int ret;
123
124 ret = vgic_get_common_attr(dev, attr);
125 return ret;
c86c7721
EA
126}
127
128static int vgic_v2_has_attr(struct kvm_device *dev,
129 struct kvm_device_attr *attr)
130{
fca25602
EA
131 switch (attr->group) {
132 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
133 return 0;
134 }
c86c7721
EA
135 return -ENXIO;
136}
137
138struct kvm_device_ops kvm_arm_vgic_v2_ops = {
139 .name = "kvm-arm-vgic-v2",
140 .create = vgic_create,
141 .destroy = vgic_destroy,
142 .set_attr = vgic_v2_set_attr,
143 .get_attr = vgic_v2_get_attr,
144 .has_attr = vgic_v2_has_attr,
145};
146
147/* V3 ops */
148
149#ifdef CONFIG_KVM_ARM_VGIC_V3
150
151static int vgic_v3_set_attr(struct kvm_device *dev,
152 struct kvm_device_attr *attr)
153{
fca25602 154 return vgic_set_common_attr(dev, attr);
c86c7721
EA
155}
156
157static int vgic_v3_get_attr(struct kvm_device *dev,
158 struct kvm_device_attr *attr)
159{
fca25602 160 return vgic_get_common_attr(dev, attr);
c86c7721
EA
161}
162
163static int vgic_v3_has_attr(struct kvm_device *dev,
164 struct kvm_device_attr *attr)
165{
fca25602
EA
166 switch (attr->group) {
167 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
168 return 0;
169 }
c86c7721
EA
170 return -ENXIO;
171}
172
173struct kvm_device_ops kvm_arm_vgic_v3_ops = {
174 .name = "kvm-arm-vgic-v3",
175 .create = vgic_create,
176 .destroy = vgic_destroy,
177 .set_attr = vgic_v3_set_attr,
178 .get_attr = vgic_v3_get_attr,
179 .has_attr = vgic_v3_has_attr,
180};
181
182#endif /* CONFIG_KVM_ARM_VGIC_V3 */
183