blob: c6d52a1fd9c88b72939618de217fc5cef4f2f0eb [file] [log] [blame]
Thomas Gleixner1802d0b2019-05-27 08:55:21 +02001// SPDX-License-Identifier: GPL-2.0-only
Eric Augerc86c7722015-11-30 14:01:58 +01002/*
3 * VGIC: KVM DEVICE API
4 *
5 * Copyright (C) 2015 ARM Ltd.
6 * Author: Marc Zyngier <marc.zyngier@arm.com>
Eric Augerc86c7722015-11-30 14:01:58 +01007 */
8#include <linux/kvm_host.h>
9#include <kvm/arm_vgic.h>
Eric Augerfca25602015-12-21 16:33:22 +010010#include <linux/uaccess.h>
Eric Augere2c1f9a2015-12-21 16:36:04 +010011#include <asm/kvm_mmu.h>
Vijaya Kumar K94574c92017-01-26 19:50:47 +053012#include <asm/cputype.h>
Eric Augerfca25602015-12-21 16:33:22 +010013#include "vgic.h"
Eric Augerc86c7722015-11-30 14:01:58 +010014
15/* common helpers */
16
Ricardo Kollerf25c5e42021-10-04 18:19:11 -070017int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr,
18 phys_addr_t addr, phys_addr_t alignment,
19 phys_addr_t size)
20{
Ricardo Koller96e90382021-10-04 18:19:15 -070021 if (!IS_VGIC_ADDR_UNDEF(ioaddr))
22 return -EEXIST;
Ricardo Kollerf25c5e42021-10-04 18:19:11 -070023
Ricardo Koller96e90382021-10-04 18:19:15 -070024 if (!IS_ALIGNED(addr, alignment) || !IS_ALIGNED(size, alignment))
Ricardo Kollerf25c5e42021-10-04 18:19:11 -070025 return -EINVAL;
26
27 if (addr + size < addr)
28 return -EINVAL;
29
Ricardo Koller96e90382021-10-04 18:19:15 -070030 if (addr & ~kvm_phys_mask(kvm) || addr + size > kvm_phys_size(kvm))
Ricardo Kollerf25c5e42021-10-04 18:19:11 -070031 return -E2BIG;
32
33 return 0;
34}
35
Christoffer Dall72030532017-05-08 12:28:19 +020036static int vgic_check_type(struct kvm *kvm, int type_needed)
37{
38 if (kvm->arch.vgic.vgic_model != type_needed)
39 return -ENODEV;
40 else
41 return 0;
42}
43
Eric Augere2c1f9a2015-12-21 16:36:04 +010044/**
45 * kvm_vgic_addr - set or get vgic VM base addresses
46 * @kvm: pointer to the vm struct
47 * @type: the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
48 * @addr: pointer to address value
49 * @write: if true set the address in the VM address space, if false read the
50 * address
51 *
52 * Set or get the vgic base addresses for the distributor and the virtual CPU
53 * interface in the VM physical address space. These addresses are properties
54 * of the emulated core/SoC and therefore user space initially knows this
55 * information.
56 * Check them for sanity (alignment, double assignment). We can't check for
57 * overlapping regions in case of a virtual GICv3 here, since we don't know
58 * the number of VCPUs yet, so we defer this check to map_resources().
59 */
60int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
61{
62 int r = 0;
63 struct vgic_dist *vgic = &kvm->arch.vgic;
Ricardo Kollerc56a87d2021-10-04 18:19:13 -070064 phys_addr_t *addr_ptr, alignment, size;
Eric Augerdbd97332018-05-22 09:55:08 +020065 u64 undef_value = VGIC_ADDR_UNDEF;
Eric Augere2c1f9a2015-12-21 16:36:04 +010066
67 mutex_lock(&kvm->lock);
68 switch (type) {
69 case KVM_VGIC_V2_ADDR_TYPE_DIST:
Christoffer Dall72030532017-05-08 12:28:19 +020070 r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
Eric Augere2c1f9a2015-12-21 16:36:04 +010071 addr_ptr = &vgic->vgic_dist_base;
72 alignment = SZ_4K;
Ricardo Kollerc56a87d2021-10-04 18:19:13 -070073 size = KVM_VGIC_V2_DIST_SIZE;
Eric Augere2c1f9a2015-12-21 16:36:04 +010074 break;
75 case KVM_VGIC_V2_ADDR_TYPE_CPU:
Christoffer Dall72030532017-05-08 12:28:19 +020076 r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
Eric Augere2c1f9a2015-12-21 16:36:04 +010077 addr_ptr = &vgic->vgic_cpu_base;
78 alignment = SZ_4K;
Ricardo Kollerc56a87d2021-10-04 18:19:13 -070079 size = KVM_VGIC_V2_CPU_SIZE;
Eric Augere2c1f9a2015-12-21 16:36:04 +010080 break;
Eric Augere2c1f9a2015-12-21 16:36:04 +010081 case KVM_VGIC_V3_ADDR_TYPE_DIST:
Christoffer Dall72030532017-05-08 12:28:19 +020082 r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
Eric Augere2c1f9a2015-12-21 16:36:04 +010083 addr_ptr = &vgic->vgic_dist_base;
84 alignment = SZ_64K;
Ricardo Kollerc56a87d2021-10-04 18:19:13 -070085 size = KVM_VGIC_V3_DIST_SIZE;
Eric Augere2c1f9a2015-12-21 16:36:04 +010086 break;
Eric Augerdbd97332018-05-22 09:55:08 +020087 case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
88 struct vgic_redist_region *rdreg;
89
Christoffer Dall72030532017-05-08 12:28:19 +020090 r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
Christoffer Dall1aab6f42017-05-08 12:30:24 +020091 if (r)
92 break;
93 if (write) {
Eric Auger04c11092018-05-22 09:55:17 +020094 r = vgic_v3_set_redist_base(kvm, 0, *addr, 0);
Christoffer Dall1aab6f42017-05-08 12:30:24 +020095 goto out;
96 }
Eric Auger94ac0832021-04-12 17:00:34 +020097 rdreg = list_first_entry_or_null(&vgic->rd_regions,
98 struct vgic_redist_region, list);
Eric Augerdbd97332018-05-22 09:55:08 +020099 if (!rdreg)
100 addr_ptr = &undef_value;
101 else
102 addr_ptr = &rdreg->base;
Eric Augere2c1f9a2015-12-21 16:36:04 +0100103 break;
Eric Augerdbd97332018-05-22 09:55:08 +0200104 }
Eric Auger04c11092018-05-22 09:55:17 +0200105 case KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION:
106 {
107 struct vgic_redist_region *rdreg;
108 u8 index;
109
110 r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
111 if (r)
112 break;
113
114 index = *addr & KVM_VGIC_V3_RDIST_INDEX_MASK;
115
116 if (write) {
117 gpa_t base = *addr & KVM_VGIC_V3_RDIST_BASE_MASK;
118 u32 count = (*addr & KVM_VGIC_V3_RDIST_COUNT_MASK)
119 >> KVM_VGIC_V3_RDIST_COUNT_SHIFT;
120 u8 flags = (*addr & KVM_VGIC_V3_RDIST_FLAGS_MASK)
121 >> KVM_VGIC_V3_RDIST_FLAGS_SHIFT;
122
123 if (!count || flags)
124 r = -EINVAL;
125 else
126 r = vgic_v3_set_redist_base(kvm, index,
127 base, count);
128 goto out;
129 }
130
131 rdreg = vgic_v3_rdist_region_from_index(kvm, index);
132 if (!rdreg) {
133 r = -ENOENT;
134 goto out;
135 }
136
137 *addr = index;
138 *addr |= rdreg->base;
139 *addr |= (u64)rdreg->count << KVM_VGIC_V3_RDIST_COUNT_SHIFT;
140 goto out;
141 }
Eric Augere2c1f9a2015-12-21 16:36:04 +0100142 default:
143 r = -ENODEV;
Eric Augere2c1f9a2015-12-21 16:36:04 +0100144 }
145
Christoffer Dall72030532017-05-08 12:28:19 +0200146 if (r)
Eric Augere2c1f9a2015-12-21 16:36:04 +0100147 goto out;
Eric Augere2c1f9a2015-12-21 16:36:04 +0100148
149 if (write) {
Ricardo Kollerc56a87d2021-10-04 18:19:13 -0700150 r = vgic_check_iorange(kvm, *addr_ptr, *addr, alignment, size);
Eric Augere2c1f9a2015-12-21 16:36:04 +0100151 if (!r)
152 *addr_ptr = *addr;
153 } else {
154 *addr = *addr_ptr;
155 }
156
157out:
158 mutex_unlock(&kvm->lock);
159 return r;
160}
161
Eric Augerfca25602015-12-21 16:33:22 +0100162static int vgic_set_common_attr(struct kvm_device *dev,
163 struct kvm_device_attr *attr)
164{
Eric Augerafcc7c52015-12-21 17:22:05 +0100165 int r;
166
Eric Augerfca25602015-12-21 16:33:22 +0100167 switch (attr->group) {
Eric Augere5c30292015-12-21 17:27:39 +0100168 case KVM_DEV_ARM_VGIC_GRP_ADDR: {
169 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
170 u64 addr;
171 unsigned long type = (unsigned long)attr->attr;
172
173 if (copy_from_user(&addr, uaddr, sizeof(addr)))
174 return -EFAULT;
175
176 r = kvm_vgic_addr(dev->kvm, type, &addr, true);
177 return (r == -ENODEV) ? -ENXIO : r;
178 }
Eric Augerfca25602015-12-21 16:33:22 +0100179 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
180 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
181 u32 val;
182 int ret = 0;
183
184 if (get_user(val, uaddr))
185 return -EFAULT;
186
187 /*
188 * We require:
189 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
190 * - at most 1024 interrupts
191 * - a multiple of 32 interrupts
192 */
193 if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
194 val > VGIC_MAX_RESERVED ||
195 (val & 31))
196 return -EINVAL;
197
198 mutex_lock(&dev->kvm->lock);
199
200 if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
201 ret = -EBUSY;
202 else
203 dev->kvm->arch.vgic.nr_spis =
204 val - VGIC_NR_PRIVATE_IRQS;
205
206 mutex_unlock(&dev->kvm->lock);
207
208 return ret;
209 }
Eric Augerafcc7c52015-12-21 17:22:05 +0100210 case KVM_DEV_ARM_VGIC_GRP_CTRL: {
211 switch (attr->attr) {
212 case KVM_DEV_ARM_VGIC_CTRL_INIT:
213 mutex_lock(&dev->kvm->lock);
214 r = vgic_init(dev->kvm);
215 mutex_unlock(&dev->kvm->lock);
216 return r;
217 }
218 break;
219 }
Eric Augerfca25602015-12-21 16:33:22 +0100220 }
221
222 return -ENXIO;
223}
224
225static int vgic_get_common_attr(struct kvm_device *dev,
226 struct kvm_device_attr *attr)
227{
228 int r = -ENXIO;
229
230 switch (attr->group) {
Eric Augere5c30292015-12-21 17:27:39 +0100231 case KVM_DEV_ARM_VGIC_GRP_ADDR: {
232 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
233 u64 addr;
234 unsigned long type = (unsigned long)attr->attr;
235
Eric Auger53b16dd62021-04-05 18:39:34 +0200236 if (copy_from_user(&addr, uaddr, sizeof(addr)))
237 return -EFAULT;
238
Eric Augere5c30292015-12-21 17:27:39 +0100239 r = kvm_vgic_addr(dev->kvm, type, &addr, false);
240 if (r)
241 return (r == -ENODEV) ? -ENXIO : r;
242
243 if (copy_to_user(uaddr, &addr, sizeof(addr)))
244 return -EFAULT;
245 break;
246 }
Eric Augerfca25602015-12-21 16:33:22 +0100247 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
248 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
249
250 r = put_user(dev->kvm->arch.vgic.nr_spis +
251 VGIC_NR_PRIVATE_IRQS, uaddr);
252 break;
253 }
254 }
255
256 return r;
257}
258
Eric Augerc86c7722015-11-30 14:01:58 +0100259static int vgic_create(struct kvm_device *dev, u32 type)
260{
261 return kvm_vgic_create(dev->kvm, type);
262}
263
264static void vgic_destroy(struct kvm_device *dev)
265{
266 kfree(dev);
267}
268
Andre Przywara42c88702016-07-15 12:43:23 +0100269int kvm_register_vgic_device(unsigned long type)
Eric Augerc86c7722015-11-30 14:01:58 +0100270{
Andre Przywara42c88702016-07-15 12:43:23 +0100271 int ret = -ENODEV;
272
Eric Augerc86c7722015-11-30 14:01:58 +0100273 switch (type) {
274 case KVM_DEV_TYPE_ARM_VGIC_V2:
Andre Przywara42c88702016-07-15 12:43:23 +0100275 ret = kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
276 KVM_DEV_TYPE_ARM_VGIC_V2);
Eric Augerc86c7722015-11-30 14:01:58 +0100277 break;
Eric Augerc86c7722015-11-30 14:01:58 +0100278 case KVM_DEV_TYPE_ARM_VGIC_V3:
Andre Przywara42c88702016-07-15 12:43:23 +0100279 ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
280 KVM_DEV_TYPE_ARM_VGIC_V3);
Vladimir Murzin7a1ff702016-09-12 15:49:18 +0100281
Andre Przywara0e4e82f2016-07-15 12:43:38 +0100282 if (ret)
283 break;
284 ret = kvm_vgic_register_its_device();
Eric Augerc86c7722015-11-30 14:01:58 +0100285 break;
Eric Augerc86c7722015-11-30 14:01:58 +0100286 }
Andre Przywara42c88702016-07-15 12:43:23 +0100287
288 return ret;
Eric Augerc86c7722015-11-30 14:01:58 +0100289}
290
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530291int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
292 struct vgic_reg_attr *reg_attr)
Christoffer Dallba7b9162016-08-16 16:48:20 +0200293{
294 int cpuid;
295
296 cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
297 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
298
299 if (cpuid >= atomic_read(&dev->kvm->online_vcpus))
300 return -EINVAL;
301
302 reg_attr->vcpu = kvm_get_vcpu(dev->kvm, cpuid);
303 reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
304
305 return 0;
306}
307
308/* unlocks vcpus from @vcpu_lock_idx and smaller */
309static void unlock_vcpus(struct kvm *kvm, int vcpu_lock_idx)
310{
311 struct kvm_vcpu *tmp_vcpu;
312
313 for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
314 tmp_vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
315 mutex_unlock(&tmp_vcpu->mutex);
316 }
317}
318
Eric Augerdfc99f82017-03-23 11:51:52 +0100319void unlock_all_vcpus(struct kvm *kvm)
Christoffer Dallba7b9162016-08-16 16:48:20 +0200320{
321 unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1);
322}
323
324/* Returns true if all vcpus were locked, false otherwise */
Eric Augerdfc99f82017-03-23 11:51:52 +0100325bool lock_all_vcpus(struct kvm *kvm)
Christoffer Dallba7b9162016-08-16 16:48:20 +0200326{
327 struct kvm_vcpu *tmp_vcpu;
Marc Zyngier46808a42021-11-16 16:04:02 +0000328 unsigned long c;
Christoffer Dallba7b9162016-08-16 16:48:20 +0200329
330 /*
331 * Any time a vcpu is run, vcpu_load is called which tries to grab the
332 * vcpu->mutex. By grabbing the vcpu->mutex of all VCPUs we ensure
333 * that no other VCPUs are run and fiddle with the vgic state while we
334 * access it.
335 */
336 kvm_for_each_vcpu(c, tmp_vcpu, kvm) {
337 if (!mutex_trylock(&tmp_vcpu->mutex)) {
338 unlock_vcpus(kvm, c - 1);
339 return false;
340 }
341 }
342
343 return true;
344}
345
Christoffer Dall1fe00092016-08-16 16:52:14 +0200346/**
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530347 * vgic_v2_attr_regs_access - allows user space to access VGIC v2 state
Eric Augerf94591e2015-12-21 17:34:52 +0100348 *
Christoffer Dall1fe00092016-08-16 16:52:14 +0200349 * @dev: kvm device handle
350 * @attr: kvm device attribute
351 * @reg: address the value is read or written
352 * @is_write: true if userspace is writing a register
Eric Augerf94591e2015-12-21 17:34:52 +0100353 */
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530354static int vgic_v2_attr_regs_access(struct kvm_device *dev,
Christoffer Dall1fe00092016-08-16 16:52:14 +0200355 struct kvm_device_attr *attr,
356 u32 *reg, bool is_write)
Eric Augerf94591e2015-12-21 17:34:52 +0100357{
Christoffer Dallba7b9162016-08-16 16:48:20 +0200358 struct vgic_reg_attr reg_attr;
Andre Przywara7d450e22015-12-01 22:36:37 +0000359 gpa_t addr;
Christoffer Dallba7b9162016-08-16 16:48:20 +0200360 struct kvm_vcpu *vcpu;
361 int ret;
Andre Przywara7d450e22015-12-01 22:36:37 +0000362
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530363 ret = vgic_v2_parse_attr(dev, attr, &reg_attr);
Christoffer Dallba7b9162016-08-16 16:48:20 +0200364 if (ret)
365 return ret;
366
367 vcpu = reg_attr.vcpu;
368 addr = reg_attr.addr;
Andre Przywara7d450e22015-12-01 22:36:37 +0000369
370 mutex_lock(&dev->kvm->lock);
371
372 ret = vgic_init(dev->kvm);
373 if (ret)
374 goto out;
375
Christoffer Dallba7b9162016-08-16 16:48:20 +0200376 if (!lock_all_vcpus(dev->kvm)) {
377 ret = -EBUSY;
Andre Przywara7d450e22015-12-01 22:36:37 +0000378 goto out;
379 }
380
Andre Przywara7d450e22015-12-01 22:36:37 +0000381 switch (attr->group) {
382 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
Andre Przywara878c5692015-12-03 11:48:42 +0000383 ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
Andre Przywara7d450e22015-12-01 22:36:37 +0000384 break;
385 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
386 ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
387 break;
388 default:
389 ret = -EINVAL;
390 break;
391 }
392
Christoffer Dallba7b9162016-08-16 16:48:20 +0200393 unlock_all_vcpus(dev->kvm);
Andre Przywara7d450e22015-12-01 22:36:37 +0000394out:
Andre Przywara7d450e22015-12-01 22:36:37 +0000395 mutex_unlock(&dev->kvm->lock);
396 return ret;
Eric Augerf94591e2015-12-21 17:34:52 +0100397}
398
Eric Augerc86c7722015-11-30 14:01:58 +0100399static int vgic_v2_set_attr(struct kvm_device *dev,
400 struct kvm_device_attr *attr)
401{
Eric Augerfca25602015-12-21 16:33:22 +0100402 int ret;
403
404 ret = vgic_set_common_attr(dev, attr);
Eric Augerf94591e2015-12-21 17:34:52 +0100405 if (ret != -ENXIO)
406 return ret;
Eric Augerfca25602015-12-21 16:33:22 +0100407
Eric Augerf94591e2015-12-21 17:34:52 +0100408 switch (attr->group) {
409 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
410 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
411 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
412 u32 reg;
413
414 if (get_user(reg, uaddr))
415 return -EFAULT;
416
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530417 return vgic_v2_attr_regs_access(dev, attr, &reg, true);
Eric Augerf94591e2015-12-21 17:34:52 +0100418 }
419 }
420
421 return -ENXIO;
Eric Augerc86c7722015-11-30 14:01:58 +0100422}
423
424static int vgic_v2_get_attr(struct kvm_device *dev,
425 struct kvm_device_attr *attr)
426{
Eric Augerfca25602015-12-21 16:33:22 +0100427 int ret;
428
429 ret = vgic_get_common_attr(dev, attr);
Eric Augerf94591e2015-12-21 17:34:52 +0100430 if (ret != -ENXIO)
431 return ret;
432
433 switch (attr->group) {
434 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
435 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
436 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
437 u32 reg = 0;
438
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530439 ret = vgic_v2_attr_regs_access(dev, attr, &reg, false);
Eric Augerf94591e2015-12-21 17:34:52 +0100440 if (ret)
441 return ret;
442 return put_user(reg, uaddr);
443 }
444 }
445
446 return -ENXIO;
Eric Augerc86c7722015-11-30 14:01:58 +0100447}
448
449static int vgic_v2_has_attr(struct kvm_device *dev,
450 struct kvm_device_attr *attr)
451{
Eric Augerfca25602015-12-21 16:33:22 +0100452 switch (attr->group) {
Eric Augere5c30292015-12-21 17:27:39 +0100453 case KVM_DEV_ARM_VGIC_GRP_ADDR:
454 switch (attr->attr) {
455 case KVM_VGIC_V2_ADDR_TYPE_DIST:
456 case KVM_VGIC_V2_ADDR_TYPE_CPU:
457 return 0;
458 }
459 break;
Eric Augerf94591e2015-12-21 17:34:52 +0100460 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
461 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
462 return vgic_v2_has_attr_regs(dev, attr);
Eric Augerfca25602015-12-21 16:33:22 +0100463 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
464 return 0;
Eric Augerafcc7c52015-12-21 17:22:05 +0100465 case KVM_DEV_ARM_VGIC_GRP_CTRL:
466 switch (attr->attr) {
467 case KVM_DEV_ARM_VGIC_CTRL_INIT:
468 return 0;
469 }
Eric Augerfca25602015-12-21 16:33:22 +0100470 }
Eric Augerc86c7722015-11-30 14:01:58 +0100471 return -ENXIO;
472}
473
474struct kvm_device_ops kvm_arm_vgic_v2_ops = {
475 .name = "kvm-arm-vgic-v2",
476 .create = vgic_create,
477 .destroy = vgic_destroy,
478 .set_attr = vgic_v2_set_attr,
479 .get_attr = vgic_v2_get_attr,
480 .has_attr = vgic_v2_has_attr,
481};
482
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530483int vgic_v3_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
484 struct vgic_reg_attr *reg_attr)
485{
486 unsigned long vgic_mpidr, mpidr_reg;
487
488 /*
489 * For KVM_DEV_ARM_VGIC_GRP_DIST_REGS group,
490 * attr might not hold MPIDR. Hence assume vcpu0.
491 */
492 if (attr->group != KVM_DEV_ARM_VGIC_GRP_DIST_REGS) {
493 vgic_mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
494 KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
495
496 mpidr_reg = VGIC_TO_MPIDR(vgic_mpidr);
497 reg_attr->vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr_reg);
498 } else {
499 reg_attr->vcpu = kvm_get_vcpu(dev->kvm, 0);
500 }
501
502 if (!reg_attr->vcpu)
503 return -EINVAL;
504
505 reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
506
507 return 0;
508}
509
510/*
511 * vgic_v3_attr_regs_access - allows user space to access VGIC v3 state
512 *
513 * @dev: kvm device handle
514 * @attr: kvm device attribute
515 * @reg: address the value is read or written
516 * @is_write: true if userspace is writing a register
517 */
518static int vgic_v3_attr_regs_access(struct kvm_device *dev,
519 struct kvm_device_attr *attr,
520 u64 *reg, bool is_write)
521{
522 struct vgic_reg_attr reg_attr;
523 gpa_t addr;
524 struct kvm_vcpu *vcpu;
525 int ret;
526 u32 tmp32;
527
528 ret = vgic_v3_parse_attr(dev, attr, &reg_attr);
529 if (ret)
530 return ret;
531
532 vcpu = reg_attr.vcpu;
533 addr = reg_attr.addr;
534
535 mutex_lock(&dev->kvm->lock);
536
537 if (unlikely(!vgic_initialized(dev->kvm))) {
538 ret = -EBUSY;
539 goto out;
540 }
541
542 if (!lock_all_vcpus(dev->kvm)) {
543 ret = -EBUSY;
544 goto out;
545 }
546
547 switch (attr->group) {
548 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
549 if (is_write)
550 tmp32 = *reg;
551
552 ret = vgic_v3_dist_uaccess(vcpu, is_write, addr, &tmp32);
553 if (!is_write)
554 *reg = tmp32;
555 break;
556 case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
557 if (is_write)
558 tmp32 = *reg;
559
560 ret = vgic_v3_redist_uaccess(vcpu, is_write, addr, &tmp32);
561 if (!is_write)
562 *reg = tmp32;
563 break;
Vijaya Kumar Kd017d7b2017-01-26 19:50:51 +0530564 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
565 u64 regid;
566
567 regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
568 ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
569 regid, reg);
570 break;
571 }
Vijaya Kumar Ke96a0062017-01-26 19:50:52 +0530572 case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
573 unsigned int info, intid;
574
575 info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
576 KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;
577 if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {
578 intid = attr->attr &
579 KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;
580 ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,
581 intid, reg);
582 } else {
583 ret = -EINVAL;
584 }
585 break;
586 }
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530587 default:
588 ret = -EINVAL;
589 break;
590 }
591
592 unlock_all_vcpus(dev->kvm);
593out:
594 mutex_unlock(&dev->kvm->lock);
595 return ret;
596}
597
Eric Augerc86c7722015-11-30 14:01:58 +0100598static int vgic_v3_set_attr(struct kvm_device *dev,
599 struct kvm_device_attr *attr)
600{
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530601 int ret;
602
603 ret = vgic_set_common_attr(dev, attr);
604 if (ret != -ENXIO)
605 return ret;
606
607 switch (attr->group) {
608 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
609 case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS: {
610 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
611 u32 tmp32;
612 u64 reg;
613
614 if (get_user(tmp32, uaddr))
615 return -EFAULT;
616
617 reg = tmp32;
618 return vgic_v3_attr_regs_access(dev, attr, &reg, true);
619 }
Vijaya Kumar Kd017d7b2017-01-26 19:50:51 +0530620 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
621 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
622 u64 reg;
623
624 if (get_user(reg, uaddr))
625 return -EFAULT;
626
627 return vgic_v3_attr_regs_access(dev, attr, &reg, true);
628 }
Vijaya Kumar Ke96a0062017-01-26 19:50:52 +0530629 case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
630 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
631 u64 reg;
632 u32 tmp32;
633
634 if (get_user(tmp32, uaddr))
635 return -EFAULT;
636
637 reg = tmp32;
638 return vgic_v3_attr_regs_access(dev, attr, &reg, true);
639 }
Eric Auger28077122017-01-09 16:28:27 +0100640 case KVM_DEV_ARM_VGIC_GRP_CTRL: {
641 int ret;
642
643 switch (attr->attr) {
644 case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
645 mutex_lock(&dev->kvm->lock);
646
647 if (!lock_all_vcpus(dev->kvm)) {
648 mutex_unlock(&dev->kvm->lock);
649 return -EBUSY;
650 }
651 ret = vgic_v3_save_pending_tables(dev->kvm);
652 unlock_all_vcpus(dev->kvm);
653 mutex_unlock(&dev->kvm->lock);
654 return ret;
655 }
656 break;
657 }
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530658 }
659 return -ENXIO;
Eric Augerc86c7722015-11-30 14:01:58 +0100660}
661
662static int vgic_v3_get_attr(struct kvm_device *dev,
663 struct kvm_device_attr *attr)
664{
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530665 int ret;
666
667 ret = vgic_get_common_attr(dev, attr);
668 if (ret != -ENXIO)
669 return ret;
670
671 switch (attr->group) {
672 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
673 case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS: {
674 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
675 u64 reg;
676 u32 tmp32;
677
678 ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
679 if (ret)
680 return ret;
681 tmp32 = reg;
682 return put_user(tmp32, uaddr);
683 }
Vijaya Kumar Kd017d7b2017-01-26 19:50:51 +0530684 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
685 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
686 u64 reg;
687
688 ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
689 if (ret)
690 return ret;
691 return put_user(reg, uaddr);
692 }
Vijaya Kumar Ke96a0062017-01-26 19:50:52 +0530693 case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
694 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
695 u64 reg;
696 u32 tmp32;
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530697
Vijaya Kumar Ke96a0062017-01-26 19:50:52 +0530698 ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
699 if (ret)
700 return ret;
701 tmp32 = reg;
702 return put_user(tmp32, uaddr);
703 }
704 }
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530705 return -ENXIO;
Eric Augerc86c7722015-11-30 14:01:58 +0100706}
707
708static int vgic_v3_has_attr(struct kvm_device *dev,
709 struct kvm_device_attr *attr)
710{
Eric Augerfca25602015-12-21 16:33:22 +0100711 switch (attr->group) {
Eric Augere5c30292015-12-21 17:27:39 +0100712 case KVM_DEV_ARM_VGIC_GRP_ADDR:
713 switch (attr->attr) {
714 case KVM_VGIC_V3_ADDR_TYPE_DIST:
715 case KVM_VGIC_V3_ADDR_TYPE_REDIST:
Eric Auger04c11092018-05-22 09:55:17 +0200716 case KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION:
Eric Augere5c30292015-12-21 17:27:39 +0100717 return 0;
718 }
719 break;
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530720 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
721 case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
Vijaya Kumar Kd017d7b2017-01-26 19:50:51 +0530722 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
Vijaya Kumar K94574c92017-01-26 19:50:47 +0530723 return vgic_v3_has_attr_regs(dev, attr);
Eric Augerfca25602015-12-21 16:33:22 +0100724 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
725 return 0;
Vijaya Kumar Ke96a0062017-01-26 19:50:52 +0530726 case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
727 if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
728 KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==
729 VGIC_LEVEL_INFO_LINE_LEVEL)
730 return 0;
731 break;
732 }
Eric Augerafcc7c52015-12-21 17:22:05 +0100733 case KVM_DEV_ARM_VGIC_GRP_CTRL:
734 switch (attr->attr) {
735 case KVM_DEV_ARM_VGIC_CTRL_INIT:
736 return 0;
Eric Auger28077122017-01-09 16:28:27 +0100737 case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
738 return 0;
Eric Augerafcc7c52015-12-21 17:22:05 +0100739 }
Eric Augerfca25602015-12-21 16:33:22 +0100740 }
Eric Augerc86c7722015-11-30 14:01:58 +0100741 return -ENXIO;
742}
743
744struct kvm_device_ops kvm_arm_vgic_v3_ops = {
745 .name = "kvm-arm-vgic-v3",
746 .create = vgic_create,
747 .destroy = vgic_destroy,
748 .set_attr = vgic_v3_set_attr,
749 .get_attr = vgic_v3_get_attr,
750 .has_attr = vgic_v3_has_attr,
751};