aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm/vgic.c
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2013-01-21 19:36:16 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2013-02-11 14:00:10 -0500
commit01ac5e342f3b87a9b83b991230d96c22c4167ec9 (patch)
tree84c06fa12415ef191bee35914323c7c65a9c4b0d /arch/arm/kvm/vgic.c
parent348b2b0708f6cdd3d0db95f8d02aa4ad2b3e2fa9 (diff)
ARM: KVM: VGIC initialisation code
Add the init code for the hypervisor, the virtual machine, and the virtual CPUs. An interrupt handler is also wired to allow the VGIC maintenance interrupts, used to deal with level triggered interrupts and LR underflows. A CPU hotplug notifier is registered to disable/enable the interrupt as requested. Reviewed-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm/kvm/vgic.c')
-rw-r--r--arch/arm/kvm/vgic.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index 2e6a585c23e5..6d8407672dec 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -16,11 +16,20 @@
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */ 17 */
18 18
19#include <linux/cpu.h>
19#include <linux/kvm.h> 20#include <linux/kvm.h>
20#include <linux/kvm_host.h> 21#include <linux/kvm_host.h>
21#include <linux/interrupt.h> 22#include <linux/interrupt.h>
22#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/of.h>
25#include <linux/of_address.h>
26#include <linux/of_irq.h>
27
28#include <linux/irqchip/arm-gic.h>
29
23#include <asm/kvm_emulate.h> 30#include <asm/kvm_emulate.h>
31#include <asm/kvm_arm.h>
32#include <asm/kvm_mmu.h>
24 33
25/* 34/*
26 * How the whole thing works (courtesy of Christoffer Dall): 35 * How the whole thing works (courtesy of Christoffer Dall):
@@ -62,6 +71,14 @@
62#define VGIC_ADDR_UNDEF (-1) 71#define VGIC_ADDR_UNDEF (-1)
63#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF) 72#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF)
64 73
74/* Physical address of vgic virtual cpu interface */
75static phys_addr_t vgic_vcpu_base;
76
77/* Virtual control interface base address */
78static void __iomem *vgic_vctrl_base;
79
80static struct device_node *vgic_node;
81
65#define ACCESS_READ_VALUE (1 << 0) 82#define ACCESS_READ_VALUE (1 << 0)
66#define ACCESS_READ_RAZ (0 << 0) 83#define ACCESS_READ_RAZ (0 << 0)
67#define ACCESS_READ_MASK(x) ((x) & (1 << 0)) 84#define ACCESS_READ_MASK(x) ((x) & (1 << 0))
@@ -75,6 +92,9 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu);
75static void vgic_update_state(struct kvm *kvm); 92static void vgic_update_state(struct kvm *kvm);
76static void vgic_kick_vcpus(struct kvm *kvm); 93static void vgic_kick_vcpus(struct kvm *kvm);
77static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg); 94static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg);
95static u32 vgic_nr_lr;
96
97static unsigned int vgic_maint_irq;
78 98
79static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x, 99static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x,
80 int cpuid, u32 offset) 100 int cpuid, u32 offset)
@@ -1221,6 +1241,210 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
1221 return 0; 1241 return 0;
1222} 1242}
1223 1243
1244static irqreturn_t vgic_maintenance_handler(int irq, void *data)
1245{
1246 /*
1247 * We cannot rely on the vgic maintenance interrupt to be
1248 * delivered synchronously. This means we can only use it to
1249 * exit the VM, and we perform the handling of EOIed
1250 * interrupts on the exit path (see vgic_process_maintenance).
1251 */
1252 return IRQ_HANDLED;
1253}
1254
1255int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
1256{
1257 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
1258 struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
1259 int i;
1260
1261 if (!irqchip_in_kernel(vcpu->kvm))
1262 return 0;
1263
1264 if (vcpu->vcpu_id >= VGIC_MAX_CPUS)
1265 return -EBUSY;
1266
1267 for (i = 0; i < VGIC_NR_IRQS; i++) {
1268 if (i < VGIC_NR_PPIS)
1269 vgic_bitmap_set_irq_val(&dist->irq_enabled,
1270 vcpu->vcpu_id, i, 1);
1271 if (i < VGIC_NR_PRIVATE_IRQS)
1272 vgic_bitmap_set_irq_val(&dist->irq_cfg,
1273 vcpu->vcpu_id, i, VGIC_CFG_EDGE);
1274
1275 vgic_cpu->vgic_irq_lr_map[i] = LR_EMPTY;
1276 }
1277
1278 /*
1279 * By forcing VMCR to zero, the GIC will restore the binary
1280 * points to their reset values. Anything else resets to zero
1281 * anyway.
1282 */
1283 vgic_cpu->vgic_vmcr = 0;
1284
1285 vgic_cpu->nr_lr = vgic_nr_lr;
1286 vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */
1287
1288 return 0;
1289}
1290
1291static void vgic_init_maintenance_interrupt(void *info)
1292{
1293 enable_percpu_irq(vgic_maint_irq, 0);
1294}
1295
1296static int vgic_cpu_notify(struct notifier_block *self,
1297 unsigned long action, void *cpu)
1298{
1299 switch (action) {
1300 case CPU_STARTING:
1301 case CPU_STARTING_FROZEN:
1302 vgic_init_maintenance_interrupt(NULL);
1303 break;
1304 case CPU_DYING:
1305 case CPU_DYING_FROZEN:
1306 disable_percpu_irq(vgic_maint_irq);
1307 break;
1308 }
1309
1310 return NOTIFY_OK;
1311}
1312
1313static struct notifier_block vgic_cpu_nb = {
1314 .notifier_call = vgic_cpu_notify,
1315};
1316
1317int kvm_vgic_hyp_init(void)
1318{
1319 int ret;
1320 struct resource vctrl_res;
1321 struct resource vcpu_res;
1322
1323 vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic");
1324 if (!vgic_node) {
1325 kvm_err("error: no compatible vgic node in DT\n");
1326 return -ENODEV;
1327 }
1328
1329 vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0);
1330 if (!vgic_maint_irq) {
1331 kvm_err("error getting vgic maintenance irq from DT\n");
1332 ret = -ENXIO;
1333 goto out;
1334 }
1335
1336 ret = request_percpu_irq(vgic_maint_irq, vgic_maintenance_handler,
1337 "vgic", kvm_get_running_vcpus());
1338 if (ret) {
1339 kvm_err("Cannot register interrupt %d\n", vgic_maint_irq);
1340 goto out;
1341 }
1342
1343 ret = register_cpu_notifier(&vgic_cpu_nb);
1344 if (ret) {
1345 kvm_err("Cannot register vgic CPU notifier\n");
1346 goto out_free_irq;
1347 }
1348
1349 ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
1350 if (ret) {
1351 kvm_err("Cannot obtain VCTRL resource\n");
1352 goto out_free_irq;
1353 }
1354
1355 vgic_vctrl_base = of_iomap(vgic_node, 2);
1356 if (!vgic_vctrl_base) {
1357 kvm_err("Cannot ioremap VCTRL\n");
1358 ret = -ENOMEM;
1359 goto out_free_irq;
1360 }
1361
1362 vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR);
1363 vgic_nr_lr = (vgic_nr_lr & 0x3f) + 1;
1364
1365 ret = create_hyp_io_mappings(vgic_vctrl_base,
1366 vgic_vctrl_base + resource_size(&vctrl_res),
1367 vctrl_res.start);
1368 if (ret) {
1369 kvm_err("Cannot map VCTRL into hyp\n");
1370 goto out_unmap;
1371 }
1372
1373 kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
1374 vctrl_res.start, vgic_maint_irq);
1375 on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
1376
1377 if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
1378 kvm_err("Cannot obtain VCPU resource\n");
1379 ret = -ENXIO;
1380 goto out_unmap;
1381 }
1382 vgic_vcpu_base = vcpu_res.start;
1383
1384 goto out;
1385
1386out_unmap:
1387 iounmap(vgic_vctrl_base);
1388out_free_irq:
1389 free_percpu_irq(vgic_maint_irq, kvm_get_running_vcpus());
1390out:
1391 of_node_put(vgic_node);
1392 return ret;
1393}
1394
1395int kvm_vgic_init(struct kvm *kvm)
1396{
1397 int ret = 0, i;
1398
1399 mutex_lock(&kvm->lock);
1400
1401 if (vgic_initialized(kvm))
1402 goto out;
1403
1404 if (IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_dist_base) ||
1405 IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_cpu_base)) {
1406 kvm_err("Need to set vgic cpu and dist addresses first\n");
1407 ret = -ENXIO;
1408 goto out;
1409 }
1410
1411 ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
1412 vgic_vcpu_base, KVM_VGIC_V2_CPU_SIZE);
1413 if (ret) {
1414 kvm_err("Unable to remap VGIC CPU to VCPU\n");
1415 goto out;
1416 }
1417
1418 for (i = VGIC_NR_PRIVATE_IRQS; i < VGIC_NR_IRQS; i += 4)
1419 vgic_set_target_reg(kvm, 0, i);
1420
1421 kvm->arch.vgic.ready = true;
1422out:
1423 mutex_unlock(&kvm->lock);
1424 return ret;
1425}
1426
1427int kvm_vgic_create(struct kvm *kvm)
1428{
1429 int ret = 0;
1430
1431 mutex_lock(&kvm->lock);
1432
1433 if (atomic_read(&kvm->online_vcpus) || kvm->arch.vgic.vctrl_base) {
1434 ret = -EEXIST;
1435 goto out;
1436 }
1437
1438 spin_lock_init(&kvm->arch.vgic.lock);
1439 kvm->arch.vgic.vctrl_base = vgic_vctrl_base;
1440 kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
1441 kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
1442
1443out:
1444 mutex_unlock(&kvm->lock);
1445 return ret;
1446}
1447
1224static bool vgic_ioaddr_overlap(struct kvm *kvm) 1448static bool vgic_ioaddr_overlap(struct kvm *kvm)
1225{ 1449{
1226 phys_addr_t dist = kvm->arch.vgic.vgic_dist_base; 1450 phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;