2 * VGICv3 MMIO handling functions
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/irqchip/arm-gic-v3.h>
15 #include <linux/kvm.h>
16 #include <linux/kvm_host.h>
17 #include <kvm/iodev.h>
18 #include <kvm/arm_vgic.h>
20 #include <asm/kvm_emulate.h>
23 #include "vgic-mmio.h"
25 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu
*vcpu
,
26 gpa_t addr
, unsigned int len
)
30 switch (addr
& 0x0c) {
32 if (vcpu
->kvm
->arch
.vgic
.enabled
)
33 value
|= GICD_CTLR_ENABLE_SS_G1
;
34 value
|= GICD_CTLR_ARE_NS
| GICD_CTLR_DS
;
37 value
= vcpu
->kvm
->arch
.vgic
.nr_spis
+ VGIC_NR_PRIVATE_IRQS
;
38 value
= (value
>> 5) - 1;
39 value
|= (INTERRUPT_ID_BITS_SPIS
- 1) << 19;
42 value
= (PRODUCT_ID_KVM
<< 24) | (IMPLEMENTER_ARM
<< 0);
51 static void vgic_mmio_write_v3_misc(struct kvm_vcpu
*vcpu
,
52 gpa_t addr
, unsigned int len
,
55 struct vgic_dist
*dist
= &vcpu
->kvm
->arch
.vgic
;
56 bool was_enabled
= dist
->enabled
;
58 switch (addr
& 0x0c) {
60 dist
->enabled
= val
& GICD_CTLR_ENABLE_SS_G1
;
62 if (!was_enabled
&& dist
->enabled
)
63 vgic_kick_vcpus(vcpu
->kvm
);
72 * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
73 * redistributors, while SPIs are covered by registers in the distributor
74 * block. Trying to set private IRQs in this block gets ignored.
75 * We take some special care here to fix the calculation of the register
78 #define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc) \
81 .bits_per_irq = bpi, \
82 .len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \
83 .access_flags = acc, \
84 .read = vgic_mmio_read_raz, \
85 .write = vgic_mmio_write_wi, \
87 .reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \
88 .bits_per_irq = bpi, \
89 .len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8, \
90 .access_flags = acc, \
95 static const struct vgic_register_region vgic_v3_dist_registers
[] = {
96 REGISTER_DESC_WITH_LENGTH(GICD_CTLR
,
97 vgic_mmio_read_v3_misc
, vgic_mmio_write_v3_misc
, 16,
99 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR
,
100 vgic_mmio_read_rao
, vgic_mmio_write_wi
, 1,
102 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER
,
103 vgic_mmio_read_enable
, vgic_mmio_write_senable
, 1,
105 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER
,
106 vgic_mmio_read_enable
, vgic_mmio_write_cenable
, 1,
108 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR
,
109 vgic_mmio_read_pending
, vgic_mmio_write_spending
, 1,
111 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR
,
112 vgic_mmio_read_pending
, vgic_mmio_write_cpending
, 1,
114 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER
,
115 vgic_mmio_read_active
, vgic_mmio_write_sactive
, 1,
117 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER
,
118 vgic_mmio_read_active
, vgic_mmio_write_cactive
, 1,
120 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR
,
121 vgic_mmio_read_priority
, vgic_mmio_write_priority
, 8,
122 VGIC_ACCESS_32bit
| VGIC_ACCESS_8bit
),
123 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR
,
124 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 8,
125 VGIC_ACCESS_32bit
| VGIC_ACCESS_8bit
),
126 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR
,
127 vgic_mmio_read_config
, vgic_mmio_write_config
, 2,
129 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR
,
130 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 1,
132 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER
,
133 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 64,
134 VGIC_ACCESS_64bit
| VGIC_ACCESS_32bit
),
135 REGISTER_DESC_WITH_LENGTH(GICD_IDREGS
,
136 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 48,
140 static const struct vgic_register_region vgic_v3_rdbase_registers
[] = {
141 REGISTER_DESC_WITH_LENGTH(GICR_CTLR
,
142 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 4,
144 REGISTER_DESC_WITH_LENGTH(GICR_IIDR
,
145 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 4,
147 REGISTER_DESC_WITH_LENGTH(GICR_TYPER
,
148 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 8,
149 VGIC_ACCESS_64bit
| VGIC_ACCESS_32bit
),
150 REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER
,
151 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 8,
152 VGIC_ACCESS_64bit
| VGIC_ACCESS_32bit
),
153 REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER
,
154 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 8,
155 VGIC_ACCESS_64bit
| VGIC_ACCESS_32bit
),
156 REGISTER_DESC_WITH_LENGTH(GICR_IDREGS
,
157 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 48,
161 static const struct vgic_register_region vgic_v3_sgibase_registers
[] = {
162 REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0
,
163 vgic_mmio_read_rao
, vgic_mmio_write_wi
, 4,
165 REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0
,
166 vgic_mmio_read_enable
, vgic_mmio_write_senable
, 4,
168 REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0
,
169 vgic_mmio_read_enable
, vgic_mmio_write_cenable
, 4,
171 REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0
,
172 vgic_mmio_read_pending
, vgic_mmio_write_spending
, 4,
174 REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0
,
175 vgic_mmio_read_pending
, vgic_mmio_write_cpending
, 4,
177 REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0
,
178 vgic_mmio_read_active
, vgic_mmio_write_sactive
, 4,
180 REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0
,
181 vgic_mmio_read_active
, vgic_mmio_write_cactive
, 4,
183 REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0
,
184 vgic_mmio_read_priority
, vgic_mmio_write_priority
, 32,
185 VGIC_ACCESS_32bit
| VGIC_ACCESS_8bit
),
186 REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0
,
187 vgic_mmio_read_config
, vgic_mmio_write_config
, 8,
189 REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0
,
190 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 4,
192 REGISTER_DESC_WITH_LENGTH(GICR_NSACR
,
193 vgic_mmio_read_raz
, vgic_mmio_write_wi
, 4,
197 unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device
*dev
)
199 dev
->regions
= vgic_v3_dist_registers
;
200 dev
->nr_regions
= ARRAY_SIZE(vgic_v3_dist_registers
);
202 kvm_iodevice_init(&dev
->dev
, &kvm_io_gic_ops
);
207 int vgic_register_redist_iodevs(struct kvm
*kvm
, gpa_t redist_base_address
)
209 int nr_vcpus
= atomic_read(&kvm
->online_vcpus
);
210 struct kvm_vcpu
*vcpu
;
211 struct vgic_io_device
*devices
;
214 devices
= kmalloc(sizeof(struct vgic_io_device
) * nr_vcpus
* 2,
219 kvm_for_each_vcpu(c
, vcpu
, kvm
) {
220 gpa_t rd_base
= redist_base_address
+ c
* SZ_64K
* 2;
221 gpa_t sgi_base
= rd_base
+ SZ_64K
;
222 struct vgic_io_device
*rd_dev
= &devices
[c
* 2];
223 struct vgic_io_device
*sgi_dev
= &devices
[c
* 2 + 1];
225 kvm_iodevice_init(&rd_dev
->dev
, &kvm_io_gic_ops
);
226 rd_dev
->base_addr
= rd_base
;
227 rd_dev
->regions
= vgic_v3_rdbase_registers
;
228 rd_dev
->nr_regions
= ARRAY_SIZE(vgic_v3_rdbase_registers
);
229 rd_dev
->redist_vcpu
= vcpu
;
231 mutex_lock(&kvm
->slots_lock
);
232 ret
= kvm_io_bus_register_dev(kvm
, KVM_MMIO_BUS
, rd_base
,
233 SZ_64K
, &rd_dev
->dev
);
234 mutex_unlock(&kvm
->slots_lock
);
239 kvm_iodevice_init(&sgi_dev
->dev
, &kvm_io_gic_ops
);
240 sgi_dev
->base_addr
= sgi_base
;
241 sgi_dev
->regions
= vgic_v3_sgibase_registers
;
242 sgi_dev
->nr_regions
= ARRAY_SIZE(vgic_v3_sgibase_registers
);
243 sgi_dev
->redist_vcpu
= vcpu
;
245 mutex_lock(&kvm
->slots_lock
);
246 ret
= kvm_io_bus_register_dev(kvm
, KVM_MMIO_BUS
, sgi_base
,
247 SZ_64K
, &sgi_dev
->dev
);
248 mutex_unlock(&kvm
->slots_lock
);
250 kvm_io_bus_unregister_dev(kvm
, KVM_MMIO_BUS
,
257 /* The current c failed, so we start with the previous one. */
258 for (c
--; c
>= 0; c
--) {
259 kvm_io_bus_unregister_dev(kvm
, KVM_MMIO_BUS
,
260 &devices
[c
* 2].dev
);
261 kvm_io_bus_unregister_dev(kvm
, KVM_MMIO_BUS
,
262 &devices
[c
* 2 + 1].dev
);
266 kvm
->arch
.vgic
.redist_iodevs
= devices
;