4 * Copyright (C) 2015,2016 ARM Ltd.
5 * Author: Andre Przywara <andre.przywara@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 * 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/>.
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>
26 #include <linux/irqchip/arm-gic-v3.h>
28 #include <asm/kvm_emulate.h>
29 #include <asm/kvm_arm.h>
30 #include <asm/kvm_mmu.h>
33 #include "vgic-mmio.h"
35 #define REGISTER_ITS_DESC(off, rd, wr, length, acc) \
39 .access_flags = acc, \
44 static unsigned long its_mmio_read_raz(struct kvm
*kvm
, struct vgic_its
*its
,
45 gpa_t addr
, unsigned int len
)
50 static void its_mmio_write_wi(struct kvm
*kvm
, struct vgic_its
*its
,
51 gpa_t addr
, unsigned int len
, unsigned long val
)
56 static struct vgic_register_region its_registers
[] = {
57 REGISTER_ITS_DESC(GITS_CTLR
,
58 its_mmio_read_raz
, its_mmio_write_wi
, 4,
60 REGISTER_ITS_DESC(GITS_IIDR
,
61 its_mmio_read_raz
, its_mmio_write_wi
, 4,
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,
83 static int vgic_its_init_its(struct kvm
*kvm
, struct vgic_its
*its
)
85 struct vgic_io_device
*iodev
= &its
->iodev
;
91 if (IS_VGIC_ADDR_UNDEF(its
->vgic_its_base
))
94 iodev
->regions
= its_registers
;
95 iodev
->nr_regions
= ARRAY_SIZE(its_registers
);
96 kvm_iodevice_init(&iodev
->dev
, &kvm_io_gic_ops
);
98 iodev
->base_addr
= its
->vgic_its_base
;
99 iodev
->iodev_type
= IODEV_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
);
107 its
->initialized
= true;
112 static int vgic_its_create(struct kvm_device
*dev
, u32 type
)
114 struct vgic_its
*its
;
116 if (type
!= KVM_DEV_TYPE_ARM_VGIC_ITS
)
119 its
= kzalloc(sizeof(struct vgic_its
), GFP_KERNEL
);
123 its
->vgic_its_base
= VGIC_ADDR_UNDEF
;
125 dev
->kvm
->arch
.vgic
.has_its
= true;
126 its
->initialized
= false;
127 its
->enabled
= false;
134 static void vgic_its_destroy(struct kvm_device
*kvm_dev
)
136 struct vgic_its
*its
= kvm_dev
->private;
141 static int vgic_its_has_attr(struct kvm_device
*dev
,
142 struct kvm_device_attr
*attr
)
144 switch (attr
->group
) {
145 case KVM_DEV_ARM_VGIC_GRP_ADDR
:
146 switch (attr
->attr
) {
147 case KVM_VGIC_ITS_ADDR_TYPE
:
151 case KVM_DEV_ARM_VGIC_GRP_CTRL
:
152 switch (attr
->attr
) {
153 case KVM_DEV_ARM_VGIC_CTRL_INIT
:
161 static int vgic_its_set_attr(struct kvm_device
*dev
,
162 struct kvm_device_attr
*attr
)
164 struct vgic_its
*its
= dev
->private;
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
;
173 if (type
!= KVM_VGIC_ITS_ADDR_TYPE
)
176 if (its
->initialized
)
179 if (copy_from_user(&addr
, uaddr
, sizeof(addr
)))
182 ret
= vgic_check_ioaddr(dev
->kvm
, &its
->vgic_its_base
,
187 its
->vgic_its_base
= addr
;
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
);
201 static int vgic_its_get_attr(struct kvm_device
*dev
,
202 struct kvm_device_attr
*attr
)
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
;
211 if (type
!= KVM_VGIC_ITS_ADDR_TYPE
)
214 if (copy_to_user(uaddr
, &addr
, sizeof(addr
)))
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
,
234 int kvm_vgic_register_its_device(void)
236 return kvm_register_device_ops(&kvm_arm_vgic_its_ops
,
237 KVM_DEV_TYPE_ARM_VGIC_ITS
);