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