From patchwork Wed Aug 5 07:05:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Fedin X-Patchwork-Id: 503904 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 30EEE1402C7 for ; Wed, 5 Aug 2015 17:06:36 +1000 (AEST) Received: from localhost ([::1]:39362 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZMsmY-0006uf-AS for incoming@patchwork.ozlabs.org; Wed, 05 Aug 2015 03:06:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33198) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZMslx-0005qX-1H for qemu-devel@nongnu.org; Wed, 05 Aug 2015 03:06:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZMslr-000472-UP for qemu-devel@nongnu.org; Wed, 05 Aug 2015 03:05:56 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:39074) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZMslr-00046S-LB for qemu-devel@nongnu.org; Wed, 05 Aug 2015 03:05:51 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NSL009EIL1PJ260@mailout2.w1.samsung.com> for qemu-devel@nongnu.org; Wed, 05 Aug 2015 08:05:49 +0100 (BST) X-AuditID: cbfec7f4-f79c56d0000012ee-b9-55c1b5ccad3c Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id DE.EC.04846.CC5B1C55; Wed, 5 Aug 2015 08:05:48 +0100 (BST) Received: from localhost ([106.109.131.169]) by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NSL00K35L1OIS90@eusync2.samsung.com>; Wed, 05 Aug 2015 08:05:48 +0100 (BST) From: Pavel Fedin To: qemu-devel@nongnu.org Date: Wed, 05 Aug 2015 10:05:45 +0300 Message-id: <8ea5b2781ef39cb5989420987fc73c70e377687d.1438758065.git.p.fedin@samsung.com> X-Mailer: git-send-email 1.9.5.msysgit.0 In-reply-to: References: In-reply-to: References: X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuplluLIzCtJLcpLzFFi42I5/e/4Fd0zWw+GGtxs1rR48fofo8X8LWdY LeacecBicbx3B4sDi8eda3vYPJ5c28wUwBTFZZOSmpNZllqkb5fAlfF6xwvGggVeFWdfbGJp YDxi1sXIySEhYCKxaOVidghbTOLCvfVsXYxcHEICSxkltsxvYoRwvjFKfP16mhGkik1AXeL0 1w8sILaIgKTE767TzCBFzAItjBI/995jBkkIC1hKPO/awtrFyMHBIqAq0T2xHiTMKxAtMefR FhaIbRoSi77MYQOxOQXMJQ6u+A1WLiRgJrFsgQsO4QmM/AsYGVYxiqaWJhcUJ6XnGuoVJ+YW l+al6yXn525ihATSlx2Mi49ZHWIU4GBU4uH94HwwVIg1say4MvcQowQHs5IIb9oEoBBvSmJl VWpRfnxRaU5q8SFGaQ4WJXHeubvehwgJpCeWpGanphakFsFkmTg4pRoYt9z2imBXX2qU8GT1 s6A649eW3m+Wqjx/+Ozbfp0ZInEvV76J7+xvyL8eFTPVg2HF0zChsrVbLifza5X7nCvZsu/Q i+OnKk7+SlGy1ijjEGLO1ciQDtMQ375oy0u/j0xM5w3CGKYKBH6U1NZhXfvsQmmvsHjETgdG 5Y+nnTp+im8umZhltMJdiaU4I9FQi7moOBEAXfO6ryACAAA= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 210.118.77.12 Cc: Peter Maydell , Christoffer Dall , Eric Auger Subject: [Qemu-devel] [PATCH v2 2/3] hw/arm/gic: Kill code duplication X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Extracted duplicated initialization code from SW-emulated and KVM GIC implementations and put into gic_init_irqs_and_mmio() Signed-off-by: Pavel Fedin --- hw/intc/arm_gic.c | 64 ++++++++++++---------------------------- hw/intc/arm_gic_common.c | 41 +++++++++++++++++++++++++ hw/intc/arm_gic_kvm.c | 28 +----------------- include/hw/intc/arm_gic_common.h | 3 ++ 4 files changed, 64 insertions(+), 72 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 454bfd7..a8c5d19 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -922,12 +922,6 @@ static MemTxResult gic_dist_write(void *opaque, hwaddr offset, uint64_t data, } } -static const MemoryRegionOps gic_dist_ops = { - .read_with_attrs = gic_dist_read, - .write_with_attrs = gic_dist_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, uint64_t *data, MemTxAttrs attrs) { @@ -1056,10 +1050,17 @@ static MemTxResult gic_do_cpu_write(void *opaque, hwaddr addr, return gic_cpu_write(s, id, addr, value, attrs); } -static const MemoryRegionOps gic_thiscpu_ops = { - .read_with_attrs = gic_thiscpu_read, - .write_with_attrs = gic_thiscpu_write, - .endianness = DEVICE_NATIVE_ENDIAN, +static const MemoryRegionOps gic_ops[2] = { + { + .read_with_attrs = gic_dist_read, + .write_with_attrs = gic_dist_write, + .endianness = DEVICE_NATIVE_ENDIAN, + }, + { + .read_with_attrs = gic_thiscpu_read, + .write_with_attrs = gic_thiscpu_write, + .endianness = DEVICE_NATIVE_ENDIAN, + } }; static const MemoryRegionOps gic_cpu_ops = { @@ -1068,31 +1069,10 @@ static const MemoryRegionOps gic_cpu_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +/* This function is used by nvic model */ void gic_init_irqs_and_distributor(GICState *s) { - SysBusDevice *sbd = SYS_BUS_DEVICE(s); - int i; - - i = s->num_irq - GIC_INTERNAL; - /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. - * GPIO array layout is thus: - * [0..N-1] SPIs - * [N..N+31] PPIs for CPU 0 - * [N+32..N+63] PPIs for CPU 1 - * ... - */ - if (s->revision != REV_NVIC) { - i += (GIC_INTERNAL * s->num_cpu); - } - qdev_init_gpio_in(DEVICE(s), gic_set_irq, i); - for (i = 0; i < NUM_CPU(s); i++) { - sysbus_init_irq(sbd, &s->parent_irq[i]); - } - for (i = 0; i < NUM_CPU(s); i++) { - sysbus_init_irq(sbd, &s->parent_fiq[i]); - } - memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s, - "gic_dist", 0x1000); + gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops); } static void arm_gic_realize(DeviceState *dev, Error **errp) @@ -1110,28 +1090,22 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) return; } - gic_init_irqs_and_distributor(s); + /* This creates distributor and main CPU interface (s->cpuiomem[0]) */ + gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops); - /* Memory regions for the CPU interfaces (NVIC doesn't have these): - * a region for "CPU interface for this core", then a region for - * "CPU interface for core 0", "for core 1", ... + /* Extra core-specific regions for the CPU interfaces. This is + * necessary for "franken-GIC" implementations, for example on + * Exynos 4. * NB that the memory region size of 0x100 applies for the 11MPCore * and also cores following the GIC v1 spec (ie A9). * GIC v2 defines a larger memory region (0x1000) so this will need * to be extended when we implement A15. */ - memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s, - "gic_cpu", 0x100); for (i = 0; i < NUM_CPU(s); i++) { s->backref[i] = s; memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops, &s->backref[i], "gic_cpu", 0x100); - } - /* Distributor */ - sysbus_init_mmio(sbd, &s->iomem); - /* cpu interfaces (one for "current cpu" plus one per cpu) */ - for (i = 0; i <= NUM_CPU(s); i++) { - sysbus_init_mmio(sbd, &s->cpuiomem[i]); + sysbus_init_mmio(sbd, &s->cpuiomem[i+1]); } } diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index a64d071..fe64b51 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -84,6 +84,47 @@ static const VMStateDescription vmstate_gic = { } }; +void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler, + const MemoryRegionOps *ops) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(s); + int i = s->num_irq - GIC_INTERNAL; + + /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. + * GPIO array layout is thus: + * [0..N-1] SPIs + * [N..N+31] PPIs for CPU 0 + * [N+32..N+63] PPIs for CPU 1 + * ... + */ + if (s->revision != REV_NVIC) { + i += (GIC_INTERNAL * s->num_cpu); + } + qdev_init_gpio_in(DEVICE(s), handler, i); + + for (i = 0; i < s->num_cpu; i++) { + sysbus_init_irq(sbd, &s->parent_irq[i]); + } + for (i = 0; i < s->num_cpu; i++) { + sysbus_init_irq(sbd, &s->parent_fiq[i]); + } + + /* Distributor */ + memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + + if (s->revision != REV_NVIC) { + /* This is the main CPU interface "for this core". It is always + * present because it is required by both software emulation and KVM. + * NVIC is not handled here because its CPU interface is different, + * neither it can use KVM. + */ + memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL, + s, "gic_cpu", s->revision == 2 ? 0x1000 : 0x100); + sysbus_init_mmio(sbd, &s->cpuiomem[0]); + } +} + static void arm_gic_common_realize(DeviceState *dev, Error **errp) { GICState *s = ARM_GIC_COMMON(dev); diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index f56bff1..e5d0f67 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -543,7 +543,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) { int i; GICState *s = KVM_ARM_GIC(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s); Error *local_err = NULL; int ret; @@ -560,32 +559,13 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) return; } - i = s->num_irq - GIC_INTERNAL; - /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. - * GPIO array layout is thus: - * [0..N-1] SPIs - * [N..N+31] PPIs for CPU 0 - * [N+32..N+63] PPIs for CPU 1 - * ... - */ - i += (GIC_INTERNAL * s->num_cpu); - qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i); + gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL); for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) { qemu_irq irq = qdev_get_gpio_in(dev, i); kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i); } - /* We never use our outbound IRQ/FIQ lines but provide them so that - * we maintain the same interface as the non-KVM GIC. - */ - for (i = 0; i < s->num_cpu; i++) { - sysbus_init_irq(sbd, &s->parent_irq[i]); - } - for (i = 0; i < s->num_cpu; i++) { - sysbus_init_irq(sbd, &s->parent_fiq[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); @@ -609,9 +589,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) } /* 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, @@ -622,9 +599,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) * provide the "interface for core #N" memory regions, because * cores with a VGIC don't have those. */ - memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s), - "kvm-gic_cpu", 0x1000); - 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, diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 899db3d..edca3e0 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -138,4 +138,7 @@ typedef struct ARMGICCommonClass { void (*post_load)(GICState *s); } ARMGICCommonClass; +void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler, + const MemoryRegionOps *ops); + #endif