]> asedeno.scripts.mit.edu Git - linux.git/blob - virt/kvm/arm/vgic/vgic-its.c
4654d6edf6a6ded36e764743c633d40e26fcb008
[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
25 #include <linux/irqchip/arm-gic-v3.h>
26
27 #include <asm/kvm_emulate.h>
28 #include <asm/kvm_arm.h>
29 #include <asm/kvm_mmu.h>
30
31 #include "vgic.h"
32 #include "vgic-mmio.h"
33
34 #define REGISTER_ITS_DESC(off, rd, wr, length, acc)             \
35 {                                                               \
36         .reg_offset = off,                                      \
37         .len = length,                                          \
38         .access_flags = acc,                                    \
39         .its_read = rd,                                         \
40         .its_write = wr,                                        \
41 }
42
43 static unsigned long its_mmio_read_raz(struct kvm *kvm, struct vgic_its *its,
44                                        gpa_t addr, unsigned int len)
45 {
46         return 0;
47 }
48
49 static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
50                               gpa_t addr, unsigned int len, unsigned long val)
51 {
52         /* Ignore */
53 }
54
55 static struct vgic_register_region its_registers[] = {
56         REGISTER_ITS_DESC(GITS_CTLR,
57                 its_mmio_read_raz, its_mmio_write_wi, 4,
58                 VGIC_ACCESS_32bit),
59         REGISTER_ITS_DESC(GITS_IIDR,
60                 its_mmio_read_raz, its_mmio_write_wi, 4,
61                 VGIC_ACCESS_32bit),
62         REGISTER_ITS_DESC(GITS_TYPER,
63                 its_mmio_read_raz, its_mmio_write_wi, 8,
64                 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
65         REGISTER_ITS_DESC(GITS_CBASER,
66                 its_mmio_read_raz, its_mmio_write_wi, 8,
67                 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
68         REGISTER_ITS_DESC(GITS_CWRITER,
69                 its_mmio_read_raz, its_mmio_write_wi, 8,
70                 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
71         REGISTER_ITS_DESC(GITS_CREADR,
72                 its_mmio_read_raz, its_mmio_write_wi, 8,
73                 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
74         REGISTER_ITS_DESC(GITS_BASER,
75                 its_mmio_read_raz, its_mmio_write_wi, 0x40,
76                 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
77         REGISTER_ITS_DESC(GITS_IDREGS_BASE,
78                 its_mmio_read_raz, its_mmio_write_wi, 0x30,
79                 VGIC_ACCESS_32bit),
80 };
81
82 static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
83 {
84         struct vgic_io_device *iodev = &its->iodev;
85         int ret;
86
87         if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
88                 return -ENXIO;
89
90         iodev->regions = its_registers;
91         iodev->nr_regions = ARRAY_SIZE(its_registers);
92         kvm_iodevice_init(&iodev->dev, &kvm_io_gic_ops);
93
94         iodev->base_addr = its->vgic_its_base;
95         iodev->iodev_type = IODEV_ITS;
96         iodev->its = its;
97         mutex_lock(&kvm->slots_lock);
98         ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, iodev->base_addr,
99                                       KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
100         mutex_unlock(&kvm->slots_lock);
101
102         return ret;
103 }