KVM: arm64: vgic-its: Introduce new KVM ITS device
[deliverable/linux.git] / virt / kvm / arm / vgic / vgic-its.c
1 /*
2 * GICv3 ITS emulation
3 *
4 * Copyright (C) 2015,2016 ARM Ltd.
5 * Author: Andre Przywara <andre.przywara@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 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <linux/cpu.h>
21 #include <linux/kvm.h>
22 #include <linux/kvm_host.h>
23 #include <linux/interrupt.h>
24 #include <linux/uaccess.h>
25
26 #include <linux/irqchip/arm-gic-v3.h>
27
28 #include <asm/kvm_emulate.h>
29 #include <asm/kvm_arm.h>
30 #include <asm/kvm_mmu.h>
31
32 #include "vgic.h"
33 #include "vgic-mmio.h"
34
35 #define REGISTER_ITS_DESC(off, rd, wr, length, acc) \
36 { \
37 .reg_offset = off, \
38 .len = length, \
39 .access_flags = acc, \
40 .its_read = rd, \
41 .its_write = wr, \
42 }
43
44 static unsigned long its_mmio_read_raz(struct kvm *kvm, struct vgic_its *its,
45 gpa_t addr, unsigned int len)
46 {
47 return 0;
48 }
49
50 static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
51 gpa_t addr, unsigned int len, unsigned long val)
52 {
53 /* Ignore */
54 }
55
56 static struct vgic_register_region its_registers[] = {
57 REGISTER_ITS_DESC(GITS_CTLR,
58 its_mmio_read_raz, its_mmio_write_wi, 4,
59 VGIC_ACCESS_32bit),
60 REGISTER_ITS_DESC(GITS_IIDR,
61 its_mmio_read_raz, its_mmio_write_wi, 4,
62 VGIC_ACCESS_32bit),
63 REGISTER_ITS_DESC(GITS_TYPER,
64 its_mmio_read_raz, its_mmio_write_wi, 8,
65 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
66 REGISTER_ITS_DESC(GITS_CBASER,
67 its_mmio_read_raz, its_mmio_write_wi, 8,
68 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
69 REGISTER_ITS_DESC(GITS_CWRITER,
70 its_mmio_read_raz, its_mmio_write_wi, 8,
71 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
72 REGISTER_ITS_DESC(GITS_CREADR,
73 its_mmio_read_raz, its_mmio_write_wi, 8,
74 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
75 REGISTER_ITS_DESC(GITS_BASER,
76 its_mmio_read_raz, its_mmio_write_wi, 0x40,
77 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
78 REGISTER_ITS_DESC(GITS_IDREGS_BASE,
79 its_mmio_read_raz, its_mmio_write_wi, 0x30,
80 VGIC_ACCESS_32bit),
81 };
82
83 static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
84 {
85 struct vgic_io_device *iodev = &its->iodev;
86 int ret;
87
88 if (its->initialized)
89 return 0;
90
91 if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
92 return -ENXIO;
93
94 iodev->regions = its_registers;
95 iodev->nr_regions = ARRAY_SIZE(its_registers);
96 kvm_iodevice_init(&iodev->dev, &kvm_io_gic_ops);
97
98 iodev->base_addr = its->vgic_its_base;
99 iodev->iodev_type = IODEV_ITS;
100 iodev->its = its;
101 mutex_lock(&kvm->slots_lock);
102 ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, iodev->base_addr,
103 KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
104 mutex_unlock(&kvm->slots_lock);
105
106 if (!ret)
107 its->initialized = true;
108
109 return ret;
110 }
111
112 static int vgic_its_create(struct kvm_device *dev, u32 type)
113 {
114 struct vgic_its *its;
115
116 if (type != KVM_DEV_TYPE_ARM_VGIC_ITS)
117 return -ENODEV;
118
119 its = kzalloc(sizeof(struct vgic_its), GFP_KERNEL);
120 if (!its)
121 return -ENOMEM;
122
123 its->vgic_its_base = VGIC_ADDR_UNDEF;
124
125 dev->kvm->arch.vgic.has_its = true;
126 its->initialized = false;
127 its->enabled = false;
128
129 dev->private = its;
130
131 return 0;
132 }
133
134 static void vgic_its_destroy(struct kvm_device *kvm_dev)
135 {
136 struct vgic_its *its = kvm_dev->private;
137
138 kfree(its);
139 }
140
141 static int vgic_its_has_attr(struct kvm_device *dev,
142 struct kvm_device_attr *attr)
143 {
144 switch (attr->group) {
145 case KVM_DEV_ARM_VGIC_GRP_ADDR:
146 switch (attr->attr) {
147 case KVM_VGIC_ITS_ADDR_TYPE:
148 return 0;
149 }
150 break;
151 case KVM_DEV_ARM_VGIC_GRP_CTRL:
152 switch (attr->attr) {
153 case KVM_DEV_ARM_VGIC_CTRL_INIT:
154 return 0;
155 }
156 break;
157 }
158 return -ENXIO;
159 }
160
161 static int vgic_its_set_attr(struct kvm_device *dev,
162 struct kvm_device_attr *attr)
163 {
164 struct vgic_its *its = dev->private;
165 int ret;
166
167 switch (attr->group) {
168 case KVM_DEV_ARM_VGIC_GRP_ADDR: {
169 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
170 unsigned long type = (unsigned long)attr->attr;
171 u64 addr;
172
173 if (type != KVM_VGIC_ITS_ADDR_TYPE)
174 return -ENODEV;
175
176 if (its->initialized)
177 return -EBUSY;
178
179 if (copy_from_user(&addr, uaddr, sizeof(addr)))
180 return -EFAULT;
181
182 ret = vgic_check_ioaddr(dev->kvm, &its->vgic_its_base,
183 addr, SZ_64K);
184 if (ret)
185 return ret;
186
187 its->vgic_its_base = addr;
188
189 return 0;
190 }
191 case KVM_DEV_ARM_VGIC_GRP_CTRL:
192 switch (attr->attr) {
193 case KVM_DEV_ARM_VGIC_CTRL_INIT:
194 return vgic_its_init_its(dev->kvm, its);
195 }
196 break;
197 }
198 return -ENXIO;
199 }
200
201 static int vgic_its_get_attr(struct kvm_device *dev,
202 struct kvm_device_attr *attr)
203 {
204 switch (attr->group) {
205 case KVM_DEV_ARM_VGIC_GRP_ADDR: {
206 struct vgic_its *its = dev->private;
207 u64 addr = its->vgic_its_base;
208 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
209 unsigned long type = (unsigned long)attr->attr;
210
211 if (type != KVM_VGIC_ITS_ADDR_TYPE)
212 return -ENODEV;
213
214 if (copy_to_user(uaddr, &addr, sizeof(addr)))
215 return -EFAULT;
216 break;
217 default:
218 return -ENXIO;
219 }
220 }
221
222 return 0;
223 }
224
225 static struct kvm_device_ops kvm_arm_vgic_its_ops = {
226 .name = "kvm-arm-vgic-its",
227 .create = vgic_its_create,
228 .destroy = vgic_its_destroy,
229 .set_attr = vgic_its_set_attr,
230 .get_attr = vgic_its_get_attr,
231 .has_attr = vgic_its_has_attr,
232 };
233
234 int kvm_vgic_register_its_device(void)
235 {
236 return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
237 KVM_DEV_TYPE_ARM_VGIC_ITS);
238 }
This page took 0.036581 seconds and 6 git commands to generate.