From 1da41cc1c6c3efbe2ed47228068bd80dbdc49d0e Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Wed, 26 Feb 2014 17:20:00 +0000 Subject: arm: vgic device control api support Support creating the ARM vgic device through the device control API and setting the base address for the distributor and cpu interfaces in KVM VMs using this API. Because the older KVM_CREATE_IRQCHIP interface needs the irq chip to be created prior to creating the VCPUs, we first test if we can use the device control API in kvm_arch_irqchip_create (using the test flag from the device control API). If we cannot, it means we have to fall back to KVM_CREATE_IRQCHIP and use the older ioctl at this point in time. If however, we can use the device control API, we don't do anything and wait until the arm_gic_kvm driver initializes and let that use the device control API. Signed-off-by: Christoffer Dall Message-id: 1392687720-26806-5-git-send-email-christoffer.dall@linaro.org Signed-off-by: Peter Maydell --- hw/intc/arm_gic_kvm.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index 59a3da5a6b..964d4d7222 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -97,6 +97,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) GICState *s = KVM_ARM_GIC(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s); + int ret; kgc->parent_realize(dev, errp); if (error_is_set(errp)) { @@ -119,13 +120,27 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) for (i = 0; i < s->num_cpu; i++) { sysbus_init_irq(sbd, &s->parent_irq[i]); } + + /* Try to create the device via the device control API */ + s->dev_fd = -1; + ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false); + if (ret >= 0) { + s->dev_fd = ret; + } else if (ret != -ENODEV && ret != -ENOTSUP) { + error_setg_errno(errp, -ret, "error creating in-kernel VGIC"); + return; + } + /* Distributor */ memory_region_init_reservation(&s->iomem, OBJECT(s), "kvm-gic_dist", 0x1000); sysbus_init_mmio(sbd, &s->iomem); kvm_arm_register_device(&s->iomem, (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) - | KVM_VGIC_V2_ADDR_TYPE_DIST); + | KVM_VGIC_V2_ADDR_TYPE_DIST, + KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V2_ADDR_TYPE_DIST, + s->dev_fd); /* CPU interface for current core. Unlike arm_gic, we don't * provide the "interface for core #N" memory regions, because * cores with a VGIC don't have those. @@ -135,7 +150,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->cpuiomem[0]); kvm_arm_register_device(&s->cpuiomem[0], (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) - | KVM_VGIC_V2_ADDR_TYPE_CPU); + | KVM_VGIC_V2_ADDR_TYPE_CPU, + KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V2_ADDR_TYPE_CPU, + s->dev_fd); } static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) -- cgit v1.2.3