* [Qemu-devel] [PATCH v10 0/5] vGICv3 support
@ 2015-08-18 13:33 Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class Pavel Fedin
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: Pavel Fedin @ 2015-08-18 13:33 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz, Christoffer Dall,
Eric Auger
This series introduces support for GICv3 by KVM. Software emulation is
currently not supported.
v9 => v10
- Renamed "gicversion" option to "gic-version" (was forgotten in v9)
- Data pointer in kvm_gic_access() is now void * because in case of
vGICv3 this function is expected to operate on 64-bit registers too
(GICD_IROUTER for instance)
v8 => v9
- Removed all limitations on CPU and IRQ number from the base class
- Added back missing properties, interface is now the same as in GICv2
- Refactored reusable parts of vGICv2 code, decreased number of changes
- Removed GIC type check from kvm_arch_irqchip_create(), no more need to
specify GIC type early
- Fixed up all commit messages / logs
- Removed 'nvic' field assignment in virt machine (was forgotten in v8)
- CPU number limitation for 'virt' machine now comes from memory map
(how many redistributors can be placed). With current layout it appears
to be 126.
v7 => v8
- Removed all unused SW emulation code
- Removed unnecessary attributes from common class
- Set "unmigratable" flag for GICv3 device
- Removed unnecessary conditions from kvm_arm_gicv3_realize()
- Fixed GIC type setting in vexpress model, was done in wrong place
- Fixed condition style in hw/intc/Makefile.objs
- Cleaned up virt machine memory map
v6 => v7
- Wrap own GIC type definitions on top of KVM ones. Fixed build on
non-ARM-Linux hosts
v5 => v6
- Fixed various checkpatch.pl style warnings
- Removed TODO in gicv3_init_irqs_and_mmio(), relevant memory API patch
included
- gicv3_init_irqs_and_mmio() now takes 3 arguments instead of 4. It is more
convenient to pass MMIO descriptors as array
v4 => v5
- Do not reintroduce several constants shared with GICv2, reuse them instead.
- Added gicv3_init_irqs_and_mmio() in base class, to be used by both software
emulation and KVM code. Avoids code duplication.
- Do not add NULL msi-parent phandle to PCI device in the FDT
- Removed a couple of stale things from virt.c
v3 => v4
- Fixed stupid build breakage in patch 0002
- Rebased on top of current master, patch 0003 adjusted according to
kvm_irqchip_create() changes
- Added assertion against uninitialized kernel_irqchip_type
- Removed kernel_irqchip_type initialization from models which do not
use KVM vGIC
v2 => v3
- Removed some unrelated and unnecessary changes from virt machine,
occasionally slipped in; some of them caused qemu to crash on ARM32.
- Fixed build for ARM32; vGICv3 code requires definitions which are
present only in ARM64 kernel
v1 => v2
- Base class included, taken from the series by Shlomo Pongratz:
http://lists.nongnu.org/archive/html/qemu-devel/2015-06/msg01512.html
The code is refactored as little as possible in order to simplify
further addition of software emulation:
- Minor fixes in code style and comments, according to old reviews
- Removed REV_V3 definition because it's currently not used, and it does
not add any meaning to number 3.
- Removed reserved regions for MBI and ITS (except for 'virt' machine
memory map). These should go to separate classes when implemented.
- Improved commit messages
- vGIC patches restructured
- Use 'gicversion' option instead of virt-v3 machine
Pavel Fedin (4):
intc/gic: Extract some reusable vGIC code
arm_kvm: Do not assume particular GIC type in
kvm_arch_irqchip_create()
hw/intc: Initial implementation of vGICv3
hw/arm/virt: Add gic-version option to virt machine
Shlomo Pongratz (1):
hw/intc: Implement GIC-500 base class
hw/arm/virt.c | 111 ++++++++++++++++++++++-----
hw/intc/Makefile.objs | 2 +
hw/intc/arm_gic_kvm.c | 42 +++++------
hw/intc/arm_gicv3_common.c | 140 ++++++++++++++++++++++++++++++++++
hw/intc/arm_gicv3_kvm.c | 149 +++++++++++++++++++++++++++++++++++++
hw/intc/vgic_common.h | 55 ++++++++++++++
include/hw/arm/fdt.h | 2 +-
include/hw/arm/virt.h | 5 +-
include/hw/intc/arm_gicv3_common.h | 68 +++++++++++++++++
target-arm/kvm.c | 10 +--
target-arm/kvm_arm.h | 10 +++
target-arm/machine.c | 18 +++++
12 files changed, 557 insertions(+), 55 deletions(-)
create mode 100644 hw/intc/arm_gicv3_common.c
create mode 100644 hw/intc/arm_gicv3_kvm.c
create mode 100644 hw/intc/vgic_common.h
create mode 100644 include/hw/intc/arm_gicv3_common.h
--
1.9.5.msysgit.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class
2015-08-18 13:33 [Qemu-devel] [PATCH v10 0/5] vGICv3 support Pavel Fedin
@ 2015-08-18 13:33 ` Pavel Fedin
2015-08-18 15:54 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code Pavel Fedin
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Pavel Fedin @ 2015-08-18 13:33 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz, Christoffer Dall,
Eric Auger
From: Shlomo Pongratz <shlomo.pongratz@huawei.com>
This class is to be used by both software and KVM implementations of GICv3
Currently it is mostly a placeholder, but in future it is supposed to hold
qemu's representation of GICv3 state, which is necessary for migration.
The interface of this class is fully compatible with GICv2 one. This is
done in order to simplify integration with existing code.
Signed-off-by: Shlomo Pongratz <shlomo.pongratz@huawei.com>
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/intc/Makefile.objs | 1 +
hw/intc/arm_gicv3_common.c | 140 +++++++++++++++++++++++++++++++++++++
include/hw/intc/arm_gicv3_common.h | 68 ++++++++++++++++++
3 files changed, 209 insertions(+)
create mode 100644 hw/intc/arm_gicv3_common.c
create mode 100644 include/hw/intc/arm_gicv3_common.h
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 092d8a8..1317e5a 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-$(CONFIG_IOAPIC) += ioapic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o
+common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o
common-obj-$(CONFIG_OPENPIC) += openpic.o
obj-$(CONFIG_APIC) += apic.o apic_common.o
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
new file mode 100644
index 0000000..032ece2
--- /dev/null
+++ b/hw/intc/arm_gicv3_common.c
@@ -0,0 +1,140 @@
+/*
+ * ARM GICv3 support - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/intc/arm_gicv3_common.h"
+
+static void gicv3_pre_save(void *opaque)
+{
+ GICv3State *s = (GICv3State *)opaque;
+ ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+ if (c->pre_save) {
+ c->pre_save(s);
+ }
+}
+
+static int gicv3_post_load(void *opaque, int version_id)
+{
+ GICv3State *s = (GICv3State *)opaque;
+ ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+ if (c->post_load) {
+ c->post_load(s);
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_gicv3 = {
+ .name = "arm_gicv3",
+ .unmigratable = 1,
+ .pre_save = gicv3_pre_save,
+ .post_load = gicv3_post_load,
+};
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+ int i;
+
+ /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+ * GPIO array layout is thus:
+ * [0..N-1] spi
+ * [N..N+31] PPIs for CPU 0
+ * [N+32..N+63] PPIs for CPU 1
+ * ...
+ */
+ i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu;
+ qdev_init_gpio_in(DEVICE(s), handler, i);
+
+ s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+ s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+
+ 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]);
+ }
+
+ memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
+ "gicv3_dist", 0x10000);
+ memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
+ "gicv3_redist", 0x20000 * s->num_cpu);
+
+ sysbus_init_mmio(sbd, &s->iomem_dist);
+ sysbus_init_mmio(sbd, &s->iomem_redist);
+}
+
+static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
+{
+ GICv3State *s = ARM_GICV3_COMMON(dev);
+
+ /* revision property is actually reserved and currently used only in order
+ * to keep the interface compatible with GICv2 code, avoiding extra
+ * conditions. However, in future it could be used, for example, if we
+ * implement GICv4.
+ */
+ if (s->revision != 3) {
+ error_setg(errp, "unsupported GIC revision %d", s->revision);
+ return;
+ }
+}
+
+static void arm_gicv3_common_reset(DeviceState *dev)
+{
+ /* TODO */
+}
+
+static Property arm_gicv3_common_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
+ DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
+ DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+ DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = arm_gicv3_common_reset;
+ dc->realize = arm_gicv3_common_realize;
+ dc->props = arm_gicv3_common_properties;
+ dc->vmsd = &vmstate_gicv3;
+}
+
+static const TypeInfo arm_gicv3_common_type = {
+ .name = TYPE_ARM_GICV3_COMMON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GICv3State),
+ .class_size = sizeof(ARMGICv3CommonClass),
+ .class_init = arm_gicv3_common_class_init,
+ .abstract = true,
+};
+
+static void register_types(void)
+{
+ type_register_static(&arm_gicv3_common_type);
+}
+
+type_init(register_types)
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
new file mode 100644
index 0000000..516dc20
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -0,0 +1,68 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_GICV3_COMMON_H
+#define HW_ARM_GICV3_COMMON_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic_common.h"
+
+typedef struct GICv3State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ qemu_irq *parent_irq;
+ qemu_irq *parent_fiq;
+
+ MemoryRegion iomem_dist; /* Distributor */
+ MemoryRegion iomem_redist; /* Redistributor */
+
+ uint32_t num_cpu;
+ uint32_t num_irq;
+ uint32_t revision;
+ bool security_extn;
+
+ int dev_fd; /* kvm device fd if backed by kvm vgic support */
+} GICv3State;
+
+#define TYPE_ARM_GICV3_COMMON "arm_gicv3_common"
+#define ARM_GICV3_COMMON(obj) \
+ OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON)
+#define ARM_GICV3_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON)
+#define ARM_GICV3_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON)
+
+typedef struct ARMGICv3CommonClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ void (*pre_save)(GICv3State *s);
+ void (*post_load)(GICv3State *s);
+} ARMGICv3CommonClass;
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops);
+
+#endif
--
1.9.5.msysgit.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code
2015-08-18 13:33 [Qemu-devel] [PATCH v10 0/5] vGICv3 support Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class Pavel Fedin
@ 2015-08-18 13:33 ` Pavel Fedin
2015-08-18 15:53 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 3/5] arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create() Pavel Fedin
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Pavel Fedin @ 2015-08-18 13:33 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz, Christoffer Dall,
Eric Auger
These functions are useful also for vGICv3 implementation. Make them accessible
from within other modules.
Actually kvm_dist_get() and kvm_dist_put() could also be made reusable, but
they would require two extra parameters (s->dev_fd and s->num_cpu) as well as
lots of typecasts of 's' to DeviceState * and back to GICState *. This makes
the code very ugly so i decided to stop at this point. I tried also an
approach with making a base class for all possible GICs, but it would contain
only three variables (dev_fd, cpu_num and irq_num), and accessing them through
the rest of the code would be again tedious (either ugly casts or qemu-style
separate object pointer). So i disliked it too.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/intc/arm_gic_kvm.c | 42 +++++++++++++++++----------------------
hw/intc/vgic_common.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 24 deletions(-)
create mode 100644 hw/intc/vgic_common.h
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index e5d0f67..0c71ef8 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -23,6 +23,7 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "gic_internal.h"
+#include "vgic_common.h"
//#define DEBUG_GIC_KVM
@@ -52,7 +53,7 @@ typedef struct KVMARMGICClass {
void (*parent_reset)(DeviceState *dev);
} KVMARMGICClass;
-static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
+void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
{
/* Meaning of the 'irq' parameter:
* [0..N-1] : external interrupts
@@ -63,10 +64,9 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
* has separate fields in the irq number for type,
* CPU number and interrupt number.
*/
- GICState *s = (GICState *)opaque;
int kvm_irq, irqtype, cpu;
- if (irq < (s->num_irq - GIC_INTERNAL)) {
+ if (irq < (num_irq - GIC_INTERNAL)) {
/* External interrupt. The kernel numbers these like the GIC
* hardware, with external interrupt IDs starting after the
* internal ones.
@@ -77,7 +77,7 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
} else {
/* Internal interrupt: decode into (cpu, interrupt id) */
irqtype = KVM_ARM_IRQ_TYPE_PPI;
- irq -= (s->num_irq - GIC_INTERNAL);
+ irq -= (num_irq - GIC_INTERNAL);
cpu = irq / GIC_INTERNAL;
irq %= GIC_INTERNAL;
}
@@ -87,6 +87,13 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
kvm_set_irq(kvm_state, kvm_irq, !!level);
}
+static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
+{
+ GICState *s = (GICState *)opaque;
+
+ kvm_arm_gic_set_irq(s->num_irq, irq, level);
+}
+
static bool kvm_arm_gic_can_save_restore(GICState *s)
{
return s->dev_fd >= 0;
@@ -107,8 +114,8 @@ static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
}
-static void kvm_gic_access(GICState *s, int group, int offset,
- int cpu, uint32_t *val, bool write)
+void kvm_gic_access(int dev_fd, int group, int offset,
+ int cpu, void *val, bool write)
{
struct kvm_device_attr attr;
int type;
@@ -130,7 +137,7 @@ static void kvm_gic_access(GICState *s, int group, int offset,
type = KVM_GET_DEVICE_ATTR;
}
- err = kvm_device_ioctl(s->dev_fd, type, &attr);
+ err = kvm_device_ioctl(dev_fd, type, &attr);
if (err < 0) {
fprintf(stderr, "KVM_{SET/GET}_DEVICE_ATTR failed: %s\n",
strerror(-err));
@@ -138,20 +145,6 @@ static void kvm_gic_access(GICState *s, int group, int offset,
}
}
-static void kvm_gicd_access(GICState *s, int offset, int cpu,
- uint32_t *val, bool write)
-{
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
- offset, cpu, val, write);
-}
-
-static void kvm_gicc_access(GICState *s, int offset, int cpu,
- uint32_t *val, bool write)
-{
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
- offset, cpu, val, write);
-}
-
#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
@@ -559,7 +552,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
- gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL);
+ gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
qemu_irq irq = qdev_get_gpio_in(dev, i);
@@ -578,13 +571,14 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
uint32_t numirqs = s->num_irq;
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0, &numirqs, 1);
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0,
+ &numirqs, 1);
}
/* Tell the kernel to complete VGIC initialization now */
if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_CTRL_INIT)) {
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
}
diff --git a/hw/intc/vgic_common.h b/hw/intc/vgic_common.h
new file mode 100644
index 0000000..130ea64
--- /dev/null
+++ b/hw/intc/vgic_common.h
@@ -0,0 +1,55 @@
+/*
+ * ARM KVM vGIC utility functions
+ *
+ * Copyright (c) 2015 Samsung Electronics
+ * Written by Pavel Fedin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_ARM_VGIC_COMMON_H
+#define QEMU_ARM_VGIC_COMMON_H
+
+/**
+ * kvm_arm_gic_set_irq - Send an IRQ to the in-kernel vGIC
+ * @num_irq: Total number of IRQs configured for the GIC instance
+ * @irq: qemu internal IRQ line number:
+ * [0..N-1] : external interrupts
+ * [N..N+31] : PPI (internal) interrupts for CPU 0
+ * [N+32..N+63] : PPI (internal interrupts for CPU 1
+ * @level: level of the IRQ line.
+ */
+void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level);
+
+/**
+ * kvm_gic_access - Read or write vGIC memory-mapped register
+ * @dev_fd: fd of the device to act on
+ * @group: ID of the memory-mapped region
+ * @offset: offset within the region
+ * @cpu: vCPU number
+ * @val: pointer to the storage area for the data
+ * @write - true for writing and false for reading
+ */
+void kvm_gic_access(int dev_fd, int group, int offset, int cpu,
+ void *val, bool write);
+
+#define kvm_gicd_access(s, offset, cpu, val, write) \
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, \
+ offset, cpu, val, write)
+
+#define kvm_gicc_access(s, offset, cpu, val, write) \
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS, \
+ offset, cpu, val, write)
+
+#endif
--
1.9.5.msysgit.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v10 3/5] arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create()
2015-08-18 13:33 [Qemu-devel] [PATCH v10 0/5] vGICv3 support Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code Pavel Fedin
@ 2015-08-18 13:33 ` Pavel Fedin
2015-08-18 15:57 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3 Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 5/5] hw/arm/virt: Add gic-version option to virt machine Pavel Fedin
4 siblings, 1 reply; 14+ messages in thread
From: Pavel Fedin @ 2015-08-18 13:33 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz, Christoffer Dall,
Eric Auger
This allows to use different GIC types from v2. There are no kernels which
could advertise KVM_CAP_DEVICE_CTRL without the actual ability to create
GIC with it.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
target-arm/kvm.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index b278542..22383c5 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -585,18 +585,10 @@ void kvm_arch_init_irq_routing(KVMState *s)
int kvm_arch_irqchip_create(KVMState *s)
{
- int ret;
-
/* If we can create the VGIC using the newer device control API, we
* let the device do this when it initializes itself, otherwise we
* fall back to the old API */
-
- ret = kvm_create_device(s, KVM_DEV_TYPE_ARM_VGIC_V2, true);
- if (ret == 0) {
- return 1;
- }
-
- return 0;
+ return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL);
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
--
1.9.5.msysgit.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3
2015-08-18 13:33 [Qemu-devel] [PATCH v10 0/5] vGICv3 support Pavel Fedin
` (2 preceding siblings ...)
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 3/5] arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create() Pavel Fedin
@ 2015-08-18 13:33 ` Pavel Fedin
2015-08-18 16:11 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 5/5] hw/arm/virt: Add gic-version option to virt machine Pavel Fedin
4 siblings, 1 reply; 14+ messages in thread
From: Pavel Fedin @ 2015-08-18 13:33 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz, Christoffer Dall,
Eric Auger
This is the initial version of KVM-accelerated GICv3 support.
State load and save are not yet supported, live migration is
not possible.
In order to get correct class name in a simpler way, gicv3_class_name()
function is implemented, similar to gic_class_name().
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/intc/Makefile.objs | 1 +
hw/intc/arm_gicv3_kvm.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
target-arm/kvm_arm.h | 10 ++++
target-arm/machine.c | 18 ++++++
4 files changed, 178 insertions(+)
create mode 100644 hw/intc/arm_gicv3_kvm.c
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 1317e5a..004b0c2 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -17,6 +17,7 @@ common-obj-$(CONFIG_OPENPIC) += openpic.o
obj-$(CONFIG_APIC) += apic.o apic_common.o
obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
+obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_kvm.o
obj-$(CONFIG_STELLARIS) += armv7m_nvic.o
obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o
obj-$(CONFIG_GRLIB) += grlib_irqmp.o
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
new file mode 100644
index 0000000..8070a2a
--- /dev/null
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -0,0 +1,149 @@
+/*
+ * ARM Generic Interrupt Controller using KVM in-kernel support
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin
+ * Based on vGICv2 code by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/intc/arm_gicv3_common.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+#include "vgic_common.h"
+
+#ifdef DEBUG_GICV3_KVM
+#define DPRINTF(fmt, ...) \
+ do { fprintf(stderr, "kvm_gicv3: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+ do { } while (0)
+#endif
+
+#define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3"
+#define KVM_ARM_GICV3(obj) \
+ OBJECT_CHECK(GICv3State, (obj), TYPE_KVM_ARM_GICV3)
+#define KVM_ARM_GICV3_CLASS(klass) \
+ OBJECT_CLASS_CHECK(KVMARMGICv3Class, (klass), TYPE_KVM_ARM_GICV3)
+#define KVM_ARM_GICV3_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3)
+
+typedef struct KVMARMGICv3Class {
+ ARMGICv3CommonClass parent_class;
+ DeviceRealize parent_realize;
+ void (*parent_reset)(DeviceState *dev);
+} KVMARMGICv3Class;
+
+static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level)
+{
+ GICv3State *s = (GICv3State *)opaque;
+
+ kvm_arm_gic_set_irq(s->num_irq, irq, level);
+}
+
+static void kvm_arm_gicv3_put(GICv3State *s)
+{
+ /* TODO */
+ DPRINTF("Cannot put kernel gic state, no kernel interface\n");
+}
+
+static void kvm_arm_gicv3_get(GICv3State *s)
+{
+ /* TODO */
+ DPRINTF("Cannot get kernel gic state, no kernel interface\n");
+}
+
+static void kvm_arm_gicv3_reset(DeviceState *dev)
+{
+ GICv3State *s = ARM_GICV3_COMMON(dev);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
+
+ DPRINTF("Reset\n");
+
+ kgc->parent_reset(dev);
+ kvm_arm_gicv3_put(s);
+}
+
+static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
+{
+ GICv3State *s = KVM_ARM_GICV3(dev);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
+ Error *local_err = NULL;
+
+ DPRINTF("kvm_arm_gicv3_realize\n");
+
+ kgc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (s->security_extn) {
+ error_setg(errp, "the in-kernel VGICv3 does not implement the "
+ "security extensions");
+ return;
+ }
+
+ gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
+
+ /* Try to create the device via the device control API */
+ s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
+ if (s->dev_fd < 0) {
+ error_setg_errno(errp, -s->dev_fd, "error creating in-kernel VGIC");
+ return;
+ }
+
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
+ 0, 0, &s->num_irq, 1);
+
+ /* Tell the kernel to complete VGIC initialization now */
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
+
+ kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
+ kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
+}
+
+static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass);
+
+ agcc->pre_save = kvm_arm_gicv3_get;
+ agcc->post_load = kvm_arm_gicv3_put;
+ kgc->parent_realize = dc->realize;
+ kgc->parent_reset = dc->reset;
+ dc->realize = kvm_arm_gicv3_realize;
+ dc->reset = kvm_arm_gicv3_reset;
+}
+
+static const TypeInfo kvm_arm_gicv3_info = {
+ .name = TYPE_KVM_ARM_GICV3,
+ .parent = TYPE_ARM_GICV3_COMMON,
+ .instance_size = sizeof(GICv3State),
+ .class_init = kvm_arm_gicv3_class_init,
+ .class_size = sizeof(KVMARMGICv3Class),
+};
+
+static void kvm_arm_gicv3_register_types(void)
+{
+ type_register_static(&kvm_arm_gicv3_info);
+}
+
+type_init(kvm_arm_gicv3_register_types)
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index b3e0ab7..b6f5b69 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -196,4 +196,14 @@ static inline const char *gic_class_name(void)
return kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic";
}
+/**
+ * gicv3_class_name
+ *
+ * Return name of GICv3 class to use depending on whether KVM acceleration is
+ * in use. May throw an error if the chosen implementation is not available.
+ *
+ * Returns: class name to use
+ */
+const char *gicv3_class_name(void);
+
#endif
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 32adfe7..c6cdde2 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -1,5 +1,6 @@
#include "hw/hw.h"
#include "hw/boards.h"
+#include "qemu/error-report.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "internals.h"
@@ -328,3 +329,20 @@ const VMStateDescription vmstate_arm_cpu = {
NULL
}
};
+
+const char *gicv3_class_name(void)
+{
+ if (kvm_irqchip_in_kernel()) {
+#ifdef TARGET_AARCH64
+ return "kvm-arm-gicv3";
+#else
+ error_report("KVM GICv3 acceleration is not supported on this "
+ "platform\n");
+#endif
+ } else {
+ /* TODO: Software emulation is not implemented yet */
+ error_report("KVM is currently required for GICv3 emulation\n");
+ }
+
+ exit(1);
+}
--
1.9.5.msysgit.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v10 5/5] hw/arm/virt: Add gic-version option to virt machine
2015-08-18 13:33 [Qemu-devel] [PATCH v10 0/5] vGICv3 support Pavel Fedin
` (3 preceding siblings ...)
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3 Pavel Fedin
@ 2015-08-18 13:33 ` Pavel Fedin
2015-08-19 14:08 ` Eric Auger
4 siblings, 1 reply; 14+ messages in thread
From: Pavel Fedin @ 2015-08-18 13:33 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz, Christoffer Dall,
Eric Auger
Add gic_version to VirtMachineState, set it to value of the option
and pass it around where necessary. Instantiate devices and fdt
nodes according to the choice.
max_cpus for virt machine increased to 126 (calculated from redistributor
space available in the memory map). GICv2 compatibility check happens
inside arm_gic_common_realize().
ITS regions are added to the memory map too, however currently they
are not used, just reserved.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/arm/virt.c | 111 +++++++++++++++++++++++++++++++++++++++++---------
include/hw/arm/fdt.h | 2 +-
include/hw/arm/virt.h | 5 ++-
3 files changed, 96 insertions(+), 22 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index d5a8417..e090640 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -50,6 +50,7 @@
#include "hw/arm/fdt.h"
#include "hw/intc/arm_gic_common.h"
#include "kvm_arm.h"
+#include "qapi/visitor.h"
/* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 256
@@ -79,6 +80,7 @@ typedef struct {
typedef struct {
MachineState parent;
bool secure;
+ int32_t gic_version;
} VirtMachineState;
#define TYPE_VIRT_MACHINE "virt"
@@ -109,6 +111,9 @@ static const MemMapEntry a15memmap[] = {
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
+ [VIRT_ITS_CONTROL] = { 0x08020000, 0x00010000 },
+ [VIRT_ITS_TRANSLATION] = { 0x08030000, 0x00010000 },
+ [VIRT_GIC_REDIST] = { 0x08040000, 0x00FC0000 },
[VIRT_UART] = { 0x09000000, 0x00001000 },
[VIRT_RTC] = { 0x09010000, 0x00001000 },
[VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
@@ -258,10 +263,13 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
* they are edge-triggered.
*/
ARMCPU *armcpu;
+ uint32_t max;
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
+ /* Argument is 32 bit but 8 bits are reserved for flags */
+ max = (vbi->smp_cpus >= 24) ? 24 : vbi->smp_cpus;
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
- GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1);
+ GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << max) - 1);
qemu_fdt_add_subnode(vbi->fdt, "/timer");
@@ -285,6 +293,18 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
{
int cpu;
+ /*
+ * From Documentation/devicetree/bindings/arm/cpus.txt
+ * On ARM v8 64-bit systems value should be set to 2,
+ * that corresponds to the MPIDR_EL1 register size.
+ * If MPIDR_EL1[63:32] value is equal to 0 on all CPUs
+ * in the system, #address-cells can be set to 1, since
+ * MPIDR_EL1[63:32] bits are not used for CPUs
+ * identification.
+ *
+ * Now GIC500 doesn't support affinities 2 & 3 so currently
+ * #address-cells can stay 1 until future GIC
+ */
qemu_fdt_add_subnode(vbi->fdt, "/cpus");
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
@@ -321,25 +341,36 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->v2m_phandle);
}
-static void fdt_add_gic_node(VirtBoardInfo *vbi)
+static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
{
vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle);
qemu_fdt_add_subnode(vbi->fdt, "/intc");
- /* 'cortex-a15-gic' means 'GIC v2' */
- qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
- "arm,cortex-a15-gic");
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
- qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
- 2, vbi->memmap[VIRT_GIC_DIST].base,
- 2, vbi->memmap[VIRT_GIC_DIST].size,
- 2, vbi->memmap[VIRT_GIC_CPU].base,
- 2, vbi->memmap[VIRT_GIC_CPU].size);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2);
qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0);
+ if (type == 3) {
+ qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+ "arm,gic-v3");
+ qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
+ 2, vbi->memmap[VIRT_GIC_DIST].base,
+ 2, vbi->memmap[VIRT_GIC_DIST].size,
+ 2, vbi->memmap[VIRT_GIC_REDIST].base,
+ 2, vbi->memmap[VIRT_GIC_REDIST].size);
+ } else {
+ /* 'cortex-a15-gic' means 'GIC v2' */
+ qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+ "arm,cortex-a15-gic");
+ qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
+ 2, vbi->memmap[VIRT_GIC_DIST].base,
+ 2, vbi->memmap[VIRT_GIC_DIST].size,
+ 2, vbi->memmap[VIRT_GIC_CPU].base,
+ 2, vbi->memmap[VIRT_GIC_CPU].size);
+ }
+
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
}
@@ -362,18 +393,18 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
fdt_add_v2m_gic_node(vbi);
}
-static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type)
{
- /* We create a standalone GIC v2 */
+ /* We create a standalone GIC */
DeviceState *gicdev;
SysBusDevice *gicbusdev;
const char *gictype;
int i;
- gictype = gic_class_name();
+ gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
gicdev = qdev_create(NULL, gictype);
- qdev_prop_set_uint32(gicdev, "revision", 2);
+ qdev_prop_set_uint32(gicdev, "revision", type);
qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
/* Note that the num-irq property counts both internal and external
* interrupts; there are always 32 of the former (mandated by GIC spec).
@@ -382,7 +413,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
- sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
+ if (type == 3) {
+ sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_REDIST].base);
+ } else {
+ sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
+ }
/* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs, and the GIC's IRQ output to
@@ -417,9 +452,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
pic[i] = qdev_get_gpio_in(gicdev, i);
}
- fdt_add_gic_node(vbi);
+ fdt_add_gic_node(vbi, type);
- create_v2m(vbi, pic);
+ if (type == 2) {
+ create_v2m(vbi, pic);
+ }
}
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
@@ -723,7 +760,10 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic)
qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
nr_pcie_buses - 1);
- qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent", vbi->v2m_phandle);
+ if (vbi->v2m_phandle) {
+ qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
+ vbi->v2m_phandle);
+ }
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base_ecam, 2, size_ecam);
@@ -883,7 +923,7 @@ static void machvirt_init(MachineState *machine)
create_flash(vbi);
- create_gic(vbi, pic);
+ create_gic(vbi, pic, vms->gic_version);
create_uart(vbi, pic);
@@ -941,6 +981,26 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
vms->secure = value;
}
+static void virt_get_gic_version(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ visit_type_int32(v, &vms->gic_version, name, errp);
+}
+
+static void virt_set_gic_version(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ visit_type_int32(v, &vms->gic_version, name, errp);
+ if (vms->gic_version != 2 && vms->gic_version != 3) {
+ error_report ("Only GICv2 and GICv3 supported currently\n");
+ exit(1);
+ }
+}
+
static void virt_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -953,6 +1013,14 @@ static void virt_instance_init(Object *obj)
"Set on/off to enable/disable the ARM "
"Security Extensions (TrustZone)",
NULL);
+
+ /* Default GIC type is v2 */
+ vms->gic_version = 2;
+ object_property_add(obj, "gic-version", "int", virt_get_gic_version,
+ virt_set_gic_version, NULL, NULL, NULL);
+ object_property_set_description(obj, "gic-version",
+ "Set GIC version. "
+ "Valid values are 2 and 3", NULL);
}
static void virt_class_init(ObjectClass *oc, void *data)
@@ -962,7 +1030,10 @@ static void virt_class_init(ObjectClass *oc, void *data)
mc->name = TYPE_VIRT_MACHINE;
mc->desc = "ARM Virtual Machine",
mc->init = machvirt_init;
- mc->max_cpus = 8;
+ /* Our maximum number of CPUs depends on how many redistributors
+ * we can fit into memory map
+ */
+ mc->max_cpus = a15memmap[VIRT_GIC_REDIST].size / 0x20000;
mc->has_dynamic_sysbus = true;
mc->block_default_type = IF_VIRTIO;
mc->no_cdrom = 1;
diff --git a/include/hw/arm/fdt.h b/include/hw/arm/fdt.h
index c3d5015..dd794dd 100644
--- a/include/hw/arm/fdt.h
+++ b/include/hw/arm/fdt.h
@@ -29,6 +29,6 @@
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
#define GIC_FDT_IRQ_PPI_CPU_START 8
-#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
+#define GIC_FDT_IRQ_PPI_CPU_WIDTH 24
#endif
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index d22fd8e..6c5a9c9 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -46,6 +46,10 @@ enum {
VIRT_CPUPERIPHS,
VIRT_GIC_DIST,
VIRT_GIC_CPU,
+ VIRT_GIC_V2M,
+ VIRT_ITS_CONTROL,
+ VIRT_ITS_TRANSLATION,
+ VIRT_GIC_REDIST,
VIRT_UART,
VIRT_MMIO,
VIRT_RTC,
@@ -54,7 +58,6 @@ enum {
VIRT_PCIE_MMIO,
VIRT_PCIE_PIO,
VIRT_PCIE_ECAM,
- VIRT_GIC_V2M,
VIRT_PLATFORM_BUS,
};
--
1.9.5.msysgit.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code Pavel Fedin
@ 2015-08-18 15:53 ` Eric Auger
2015-08-19 6:36 ` Pavel Fedin
0 siblings, 1 reply; 14+ messages in thread
From: Eric Auger @ 2015-08-18 15:53 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Christoffer Dall, Shlomo Pongratz
Hi Pavel,
On 08/18/2015 03:33 PM, Pavel Fedin wrote:
> These functions are useful also for vGICv3 implementation. Make them accessible
> from within other modules.
I think it would be worth justifying the changes in signature:
removal of GICState* due to the introduction of GICV3State and also
justify replacement of uint32_t *val into void*.
>
> Actually kvm_dist_get() and kvm_dist_put() could also be made reusable, but
> they would require two extra parameters (s->dev_fd and s->num_cpu) as well as
> lots of typecasts of 's' to DeviceState * and back to GICState *. This makes
> the code very ugly so i decided to stop at this point. I tried also an
> approach with making a base class for all possible GICs, but it would contain
> only three variables (dev_fd, cpu_num and irq_num), and accessing them through
> the rest of the code would be again tedious (either ugly casts or qemu-style
> separate object pointer). So i disliked it too.
I would put the above paragraph below "---"
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
> hw/intc/arm_gic_kvm.c | 42 +++++++++++++++++----------------------
> hw/intc/vgic_common.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 73 insertions(+), 24 deletions(-)
> create mode 100644 hw/intc/vgic_common.h
>
> diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
> index e5d0f67..0c71ef8 100644
> --- a/hw/intc/arm_gic_kvm.c
> +++ b/hw/intc/arm_gic_kvm.c
> @@ -23,6 +23,7 @@
> #include "sysemu/kvm.h"
> #include "kvm_arm.h"
> #include "gic_internal.h"
> +#include "vgic_common.h"
>
> //#define DEBUG_GIC_KVM
>
> @@ -52,7 +53,7 @@ typedef struct KVMARMGICClass {
> void (*parent_reset)(DeviceState *dev);
> } KVMARMGICClass;
>
> -static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
> +void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
> {
> /* Meaning of the 'irq' parameter:
> * [0..N-1] : external interrupts
> @@ -63,10 +64,9 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
> * has separate fields in the irq number for type,
> * CPU number and interrupt number.
> */
> - GICState *s = (GICState *)opaque;
> int kvm_irq, irqtype, cpu;
>
> - if (irq < (s->num_irq - GIC_INTERNAL)) {
> + if (irq < (num_irq - GIC_INTERNAL)) {
> /* External interrupt. The kernel numbers these like the GIC
> * hardware, with external interrupt IDs starting after the
> * internal ones.
> @@ -77,7 +77,7 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
> } else {
> /* Internal interrupt: decode into (cpu, interrupt id) */
> irqtype = KVM_ARM_IRQ_TYPE_PPI;
> - irq -= (s->num_irq - GIC_INTERNAL);
> + irq -= (num_irq - GIC_INTERNAL);
> cpu = irq / GIC_INTERNAL;
> irq %= GIC_INTERNAL;
> }
> @@ -87,6 +87,13 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
> kvm_set_irq(kvm_state, kvm_irq, !!level);
> }
>
> +static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
inline?
> +{
> + GICState *s = (GICState *)opaque;
> +
> + kvm_arm_gic_set_irq(s->num_irq, irq, level);
> +}
> +
> static bool kvm_arm_gic_can_save_restore(GICState *s)
> {
> return s->dev_fd >= 0;
> @@ -107,8 +114,8 @@ static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
> return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
> }
>
> -static void kvm_gic_access(GICState *s, int group, int offset,
> - int cpu, uint32_t *val, bool write)
> +void kvm_gic_access(int dev_fd, int group, int offset,
> + int cpu, void *val, bool write)
> {
> struct kvm_device_attr attr;
> int type;
> @@ -130,7 +137,7 @@ static void kvm_gic_access(GICState *s, int group, int offset,
> type = KVM_GET_DEVICE_ATTR;
> }
>
> - err = kvm_device_ioctl(s->dev_fd, type, &attr);
> + err = kvm_device_ioctl(dev_fd, type, &attr);
> if (err < 0) {
> fprintf(stderr, "KVM_{SET/GET}_DEVICE_ATTR failed: %s\n",
> strerror(-err));
> @@ -138,20 +145,6 @@ static void kvm_gic_access(GICState *s, int group, int offset,
> }
> }
>
> -static void kvm_gicd_access(GICState *s, int offset, int cpu,
> - uint32_t *val, bool write)
> -{
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
> - offset, cpu, val, write);
> -}
> -
> -static void kvm_gicc_access(GICState *s, int offset, int cpu,
> - uint32_t *val, bool write)
> -{
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
> - offset, cpu, val, write);
> -}
> -
> #define for_each_irq_reg(_ctr, _max_irq, _field_width) \
> for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
>
> @@ -559,7 +552,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
> return;
> }
>
> - gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL);
> + gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
>
> for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
> qemu_irq irq = qdev_get_gpio_in(dev, i);
> @@ -578,13 +571,14 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
>
> if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
> uint32_t numirqs = s->num_irq;
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0, &numirqs, 1);
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0,
> + &numirqs, 1);
> }
>
> /* Tell the kernel to complete VGIC initialization now */
> if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
> KVM_DEV_ARM_VGIC_CTRL_INIT)) {
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
> }
>
> diff --git a/hw/intc/vgic_common.h b/hw/intc/vgic_common.h
> new file mode 100644
> index 0000000..130ea64
> --- /dev/null
> +++ b/hw/intc/vgic_common.h
> @@ -0,0 +1,55 @@
> +/*
> + * ARM KVM vGIC utility functions
> + *
> + * Copyright (c) 2015 Samsung Electronics
> + * Written by Pavel Fedin
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef QEMU_ARM_VGIC_COMMON_H
> +#define QEMU_ARM_VGIC_COMMON_H
> +
> +/**
> + * kvm_arm_gic_set_irq - Send an IRQ to the in-kernel vGIC
> + * @num_irq: Total number of IRQs configured for the GIC instance
> + * @irq: qemu internal IRQ line number:
> + * [0..N-1] : external interrupts
> + * [N..N+31] : PPI (internal) interrupts for CPU 0
> + * [N+32..N+63] : PPI (internal interrupts for CPU 1
> + * @level: level of the IRQ line.
> + */
> +void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level);
> +
> +/**
> + * kvm_gic_access - Read or write vGIC memory-mapped register
> + * @dev_fd: fd of the device to act on
> + * @group: ID of the memory-mapped region
> + * @offset: offset within the region
> + * @cpu: vCPU number
> + * @val: pointer to the storage area for the data
> + * @write - true for writing and false for reading
> + */
> +void kvm_gic_access(int dev_fd, int group, int offset, int cpu,
> + void *val, bool write);
> +
> +#define kvm_gicd_access(s, offset, cpu, val, write) \
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, \
> + offset, cpu, val, write)
> +
> +#define kvm_gicc_access(s, offset, cpu, val, write) \
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS, \
> + offset, cpu, val, write)
what is the point of moving kvm_gicd_access and kvm_gicc_access here? If
I am not mistaken, they only are used in arm_gic_kvm.c? I think they can
stay static in arm_gic_kvm.c?
Best Regards
Eric
> +
> +#endif
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class Pavel Fedin
@ 2015-08-18 15:54 ` Eric Auger
0 siblings, 0 replies; 14+ messages in thread
From: Eric Auger @ 2015-08-18 15:54 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Christoffer Dall, Shlomo Pongratz
On 08/18/2015 03:33 PM, Pavel Fedin wrote:
> From: Shlomo Pongratz <shlomo.pongratz@huawei.com>
>
> This class is to be used by both software and KVM implementations of GICv3
>
> Currently it is mostly a placeholder, but in future it is supposed to hold
> qemu's representation of GICv3 state, which is necessary for migration.
>
> The interface of this class is fully compatible with GICv2 one. This is
> done in order to simplify integration with existing code.
>
> Signed-off-by: Shlomo Pongratz <shlomo.pongratz@huawei.com>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
> hw/intc/Makefile.objs | 1 +
> hw/intc/arm_gicv3_common.c | 140 +++++++++++++++++++++++++++++++++++++
> include/hw/intc/arm_gicv3_common.h | 68 ++++++++++++++++++
> 3 files changed, 209 insertions(+)
> create mode 100644 hw/intc/arm_gicv3_common.c
> create mode 100644 include/hw/intc/arm_gicv3_common.h
>
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 092d8a8..1317e5a 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -12,6 +12,7 @@ common-obj-$(CONFIG_IOAPIC) += ioapic_common.o
> common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
> common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
> common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o
> +common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o
> common-obj-$(CONFIG_OPENPIC) += openpic.o
>
> obj-$(CONFIG_APIC) += apic.o apic_common.o
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> new file mode 100644
> index 0000000..032ece2
> --- /dev/null
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -0,0 +1,140 @@
> +/*
> + * ARM GICv3 support - common bits of emulated and KVM kernel model
> + *
> + * Copyright (c) 2012 Linaro Limited
> + * Copyright (c) 2015 Huawei.
> + * Written by Peter Maydell
> + * Extended to 64 cores by Shlomo Pongratz
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw/intc/arm_gicv3_common.h"
> +
> +static void gicv3_pre_save(void *opaque)
> +{
> + GICv3State *s = (GICv3State *)opaque;
> + ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
> +
> + if (c->pre_save) {
> + c->pre_save(s);
> + }
> +}
> +
> +static int gicv3_post_load(void *opaque, int version_id)
> +{
> + GICv3State *s = (GICv3State *)opaque;
> + ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
> +
> + if (c->post_load) {
> + c->post_load(s);
> + }
> + return 0;
> +}
> +
> +static const VMStateDescription vmstate_gicv3 = {
> + .name = "arm_gicv3",
> + .unmigratable = 1,
> + .pre_save = gicv3_pre_save,
> + .post_load = gicv3_post_load,
> +};
> +
> +void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
> + const MemoryRegionOps *ops)
> +{
> + SysBusDevice *sbd = SYS_BUS_DEVICE(s);
> + int i;
> +
> + /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
> + * GPIO array layout is thus:
> + * [0..N-1] spi
> + * [N..N+31] PPIs for CPU 0
> + * [N+32..N+63] PPIs for CPU 1
> + * ...
> + */
> + i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu;
> + qdev_init_gpio_in(DEVICE(s), handler, i);
> +
> + s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq));
> + s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq));
> +
> + 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]);
> + }
> +
> + memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
> + "gicv3_dist", 0x10000);
> + memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
> + "gicv3_redist", 0x20000 * s->num_cpu);
> +
> + sysbus_init_mmio(sbd, &s->iomem_dist);
> + sysbus_init_mmio(sbd, &s->iomem_redist);
> +}
> +
> +static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
> +{
> + GICv3State *s = ARM_GICV3_COMMON(dev);
> +
> + /* revision property is actually reserved and currently used only in order
> + * to keep the interface compatible with GICv2 code, avoiding extra
> + * conditions. However, in future it could be used, for example, if we
> + * implement GICv4.
> + */
> + if (s->revision != 3) {
> + error_setg(errp, "unsupported GIC revision %d", s->revision);
> + return;
> + }
> +}
> +
> +static void arm_gicv3_common_reset(DeviceState *dev)
> +{
> + /* TODO */
> +}
> +
> +static Property arm_gicv3_common_properties[] = {
> + DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
> + DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
> + DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
> + DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->reset = arm_gicv3_common_reset;
> + dc->realize = arm_gicv3_common_realize;
> + dc->props = arm_gicv3_common_properties;
> + dc->vmsd = &vmstate_gicv3;
> +}
> +
> +static const TypeInfo arm_gicv3_common_type = {
> + .name = TYPE_ARM_GICV3_COMMON,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(GICv3State),
> + .class_size = sizeof(ARMGICv3CommonClass),
> + .class_init = arm_gicv3_common_class_init,
> + .abstract = true,
> +};
> +
> +static void register_types(void)
> +{
> + type_register_static(&arm_gicv3_common_type);
> +}
> +
> +type_init(register_types)
> diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
> new file mode 100644
> index 0000000..516dc20
> --- /dev/null
> +++ b/include/hw/intc/arm_gicv3_common.h
> @@ -0,0 +1,68 @@
> +/*
> + * ARM GIC support
> + *
> + * Copyright (c) 2012 Linaro Limited
> + * Copyright (c) 2015 Huawei.
> + * Written by Peter Maydell
> + * Extended to 64 cores by Shlomo Pongratz
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef HW_ARM_GICV3_COMMON_H
> +#define HW_ARM_GICV3_COMMON_H
> +
> +#include "hw/sysbus.h"
> +#include "hw/intc/arm_gic_common.h"
> +
> +typedef struct GICv3State {
> + /*< private >*/
> + SysBusDevice parent_obj;
> + /*< public >*/
> +
> + qemu_irq *parent_irq;
> + qemu_irq *parent_fiq;
> +
> + MemoryRegion iomem_dist; /* Distributor */
> + MemoryRegion iomem_redist; /* Redistributor */
redistributors?
Besides Reviewed-by: Eric Auger <eric.auger@linaro.org>
> +
> + uint32_t num_cpu;
> + uint32_t num_irq;
> + uint32_t revision;
> + bool security_extn;
> +
> + int dev_fd; /* kvm device fd if backed by kvm vgic support */
> +} GICv3State;
> +
> +#define TYPE_ARM_GICV3_COMMON "arm_gicv3_common"
> +#define ARM_GICV3_COMMON(obj) \
> + OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON)
> +#define ARM_GICV3_COMMON_CLASS(klass) \
> + OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON)
> +#define ARM_GICV3_COMMON_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON)
> +
> +typedef struct ARMGICv3CommonClass {
> + /*< private >*/
> + SysBusDeviceClass parent_class;
> + /*< public >*/
> +
> + void (*pre_save)(GICv3State *s);
> + void (*post_load)(GICv3State *s);
> +} ARMGICv3CommonClass;
> +
> +void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
> + const MemoryRegionOps *ops);
> +
> +#endif
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 3/5] arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create()
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 3/5] arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create() Pavel Fedin
@ 2015-08-18 15:57 ` Eric Auger
0 siblings, 0 replies; 14+ messages in thread
From: Eric Auger @ 2015-08-18 15:57 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Christoffer Dall, Shlomo Pongratz
Reviewed-by: Eric Auger <eric.auger@linaro.org>
On 08/18/2015 03:33 PM, Pavel Fedin wrote:
> This allows to use different GIC types from v2. There are no kernels which
> could advertise KVM_CAP_DEVICE_CTRL without the actual ability to create
> GIC with it.
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
> target-arm/kvm.c | 10 +---------
> 1 file changed, 1 insertion(+), 9 deletions(-)
>
> diff --git a/target-arm/kvm.c b/target-arm/kvm.c
> index b278542..22383c5 100644
> --- a/target-arm/kvm.c
> +++ b/target-arm/kvm.c
> @@ -585,18 +585,10 @@ void kvm_arch_init_irq_routing(KVMState *s)
>
> int kvm_arch_irqchip_create(KVMState *s)
> {
> - int ret;
> -
> /* If we can create the VGIC using the newer device control API, we
> * let the device do this when it initializes itself, otherwise we
> * fall back to the old API */
> -
> - ret = kvm_create_device(s, KVM_DEV_TYPE_ARM_VGIC_V2, true);
> - if (ret == 0) {
> - return 1;
> - }
> -
> - return 0;
> + return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL);
> }
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3 Pavel Fedin
@ 2015-08-18 16:11 ` Eric Auger
2015-08-19 6:44 ` Pavel Fedin
0 siblings, 1 reply; 14+ messages in thread
From: Eric Auger @ 2015-08-18 16:11 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Christoffer Dall, Shlomo Pongratz
Hi Pavel,
On 08/18/2015 03:33 PM, Pavel Fedin wrote:
> This is the initial version of KVM-accelerated GICv3 support.
> State load and save are not yet supported, live migration is
> not possible.
>
> In order to get correct class name in a simpler way, gicv3_class_name()
> function is implemented, similar to gic_class_name().
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
in v8 you got Peter's R-b. Did you omit it willingly or did you make any
changes since that. A changelog would ease the review in any case.
> ---
> hw/intc/Makefile.objs | 1 +
> hw/intc/arm_gicv3_kvm.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
> target-arm/kvm_arm.h | 10 ++++
> target-arm/machine.c | 18 ++++++
> 4 files changed, 178 insertions(+)
> create mode 100644 hw/intc/arm_gicv3_kvm.c
>
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 1317e5a..004b0c2 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -17,6 +17,7 @@ common-obj-$(CONFIG_OPENPIC) += openpic.o
>
> obj-$(CONFIG_APIC) += apic.o apic_common.o
> obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
> +obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_kvm.o
> obj-$(CONFIG_STELLARIS) += armv7m_nvic.o
> obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o
> obj-$(CONFIG_GRLIB) += grlib_irqmp.o
> diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
> new file mode 100644
> index 0000000..8070a2a
> --- /dev/null
> +++ b/hw/intc/arm_gicv3_kvm.c
> @@ -0,0 +1,149 @@
> +/*
> + * ARM Generic Interrupt Controller using KVM in-kernel support
> + *
> + * Copyright (c) 2015 Samsung Electronics Co., Ltd.
> + * Written by Pavel Fedin
> + * Based on vGICv2 code by Peter Maydell
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw/intc/arm_gicv3_common.h"
> +#include "hw/sysbus.h"
> +#include "sysemu/kvm.h"
> +#include "kvm_arm.h"
> +#include "vgic_common.h"
> +
> +#ifdef DEBUG_GICV3_KVM
> +#define DPRINTF(fmt, ...) \
> + do { fprintf(stderr, "kvm_gicv3: " fmt, ## __VA_ARGS__); } while (0)
> +#else
> +#define DPRINTF(fmt, ...) \
> + do { } while (0)
> +#endif
> +
> +#define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3"
> +#define KVM_ARM_GICV3(obj) \
> + OBJECT_CHECK(GICv3State, (obj), TYPE_KVM_ARM_GICV3)
> +#define KVM_ARM_GICV3_CLASS(klass) \
> + OBJECT_CLASS_CHECK(KVMARMGICv3Class, (klass), TYPE_KVM_ARM_GICV3)
> +#define KVM_ARM_GICV3_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3)
> +
> +typedef struct KVMARMGICv3Class {
> + ARMGICv3CommonClass parent_class;
> + DeviceRealize parent_realize;
> + void (*parent_reset)(DeviceState *dev);
> +} KVMARMGICv3Class;
> +
> +static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level)
> +{
> + GICv3State *s = (GICv3State *)opaque;
> +
> + kvm_arm_gic_set_irq(s->num_irq, irq, level);
> +}
> +
> +static void kvm_arm_gicv3_put(GICv3State *s)
> +{
> + /* TODO */
> + DPRINTF("Cannot put kernel gic state, no kernel interface\n");
> +}
> +
> +static void kvm_arm_gicv3_get(GICv3State *s)
> +{
> + /* TODO */
> + DPRINTF("Cannot get kernel gic state, no kernel interface\n");
> +}
> +
> +static void kvm_arm_gicv3_reset(DeviceState *dev)
> +{
> + GICv3State *s = ARM_GICV3_COMMON(dev);
> + KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
> +
> + DPRINTF("Reset\n");
> +
> + kgc->parent_reset(dev);
> + kvm_arm_gicv3_put(s);
> +}
> +
> +static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
> +{
> + GICv3State *s = KVM_ARM_GICV3(dev);
> + KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
> + Error *local_err = NULL;
> +
> + DPRINTF("kvm_arm_gicv3_realize\n");
> +
> + kgc->parent_realize(dev, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + if (s->security_extn) {
> + error_setg(errp, "the in-kernel VGICv3 does not implement the "
> + "security extensions");
> + return;
> + }
> +
> + gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
> +
> + /* Try to create the device via the device control API */
> + s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
> + if (s->dev_fd < 0) {
> + error_setg_errno(errp, -s->dev_fd, "error creating in-kernel VGIC");
might be helful to tell which one we fail in creating
> + return;
> + }
> +
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
> + 0, 0, &s->num_irq, 1);
> +
> + /* Tell the kernel to complete VGIC initialization now */
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> + KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
> +
> + kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
> + KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
> + kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
> + KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
> +}
> +
> +static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);
> + KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass);
> +
> + agcc->pre_save = kvm_arm_gicv3_get;
> + agcc->post_load = kvm_arm_gicv3_put;
> + kgc->parent_realize = dc->realize;
> + kgc->parent_reset = dc->reset;
> + dc->realize = kvm_arm_gicv3_realize;
> + dc->reset = kvm_arm_gicv3_reset;
> +}
> +
> +static const TypeInfo kvm_arm_gicv3_info = {
> + .name = TYPE_KVM_ARM_GICV3,
> + .parent = TYPE_ARM_GICV3_COMMON,
> + .instance_size = sizeof(GICv3State),
> + .class_init = kvm_arm_gicv3_class_init,
> + .class_size = sizeof(KVMARMGICv3Class),
> +};
> +
> +static void kvm_arm_gicv3_register_types(void)
> +{
> + type_register_static(&kvm_arm_gicv3_info);
> +}
> +
> +type_init(kvm_arm_gicv3_register_types)
> diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
> index b3e0ab7..b6f5b69 100644
> --- a/target-arm/kvm_arm.h
> +++ b/target-arm/kvm_arm.h
> @@ -196,4 +196,14 @@ static inline const char *gic_class_name(void)
> return kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic";
> }
>
> +/**
> + * gicv3_class_name
> + *
> + * Return name of GICv3 class to use depending on whether KVM acceleration is
> + * in use. May throw an error if the chosen implementation is not available.
> + *
> + * Returns: class name to use
> + */
> +const char *gicv3_class_name(void);
> +
> #endif
> diff --git a/target-arm/machine.c b/target-arm/machine.c
> index 32adfe7..c6cdde2 100644
> --- a/target-arm/machine.c
> +++ b/target-arm/machine.c
> @@ -1,5 +1,6 @@
> #include "hw/hw.h"
> #include "hw/boards.h"
> +#include "qemu/error-report.h"
> #include "sysemu/kvm.h"
> #include "kvm_arm.h"
> #include "internals.h"
> @@ -328,3 +329,20 @@ const VMStateDescription vmstate_arm_cpu = {
> NULL
> }
> };
> +
> +const char *gicv3_class_name(void)
> +{
> + if (kvm_irqchip_in_kernel()) {
> +#ifdef TARGET_AARCH64
checkpatch reports a trailing whitespace error above
Best Regards
Eric
> + return "kvm-arm-gicv3";
> +#else
> + error_report("KVM GICv3 acceleration is not supported on this "
> + "platform\n");
> +#endif
> + } else {
> + /* TODO: Software emulation is not implemented yet */
> + error_report("KVM is currently required for GICv3 emulation\n");
> + }
> +
> + exit(1);
> +}
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code
2015-08-18 15:53 ` Eric Auger
@ 2015-08-19 6:36 ` Pavel Fedin
2015-08-19 7:13 ` Eric Auger
0 siblings, 1 reply; 14+ messages in thread
From: Pavel Fedin @ 2015-08-19 6:36 UTC (permalink / raw)
To: 'Eric Auger', qemu-devel
Cc: 'Peter Maydell', 'Shlomo Pongratz',
'Christoffer Dall', 'Shlomo Pongratz'
Hello!
> I think it would be worth justifying the changes in signature:
> removal of GICState* due to the introduction of GICV3State and also
> justify replacement of uint32_t *val into void*.
I described it in the cover letter. Right now you don't see usage for it, but here i started
prototyping live migration, and in some cases 'val' is going to be uint64_t. This is because
GICD_IROUTER registers are 64 bits wide. kvm_gic_access() by itself does not dereference the
pointer, just passes it to the kernel, therefore i decided to make it type-agnostic.
> what is the point of moving kvm_gicd_access and kvm_gicc_access here? If
> I am not mistaken, they only are used in arm_gic_kvm.c? I think they can
> stay static in arm_gic_kvm.c?
They will be used in future for live migration, at least kvm_gicd_access. kvm_gicc_access just
accompanies it to keep a single style for both.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3
2015-08-18 16:11 ` Eric Auger
@ 2015-08-19 6:44 ` Pavel Fedin
0 siblings, 0 replies; 14+ messages in thread
From: Pavel Fedin @ 2015-08-19 6:44 UTC (permalink / raw)
To: 'Eric Auger', qemu-devel
Cc: 'Peter Maydell', 'Shlomo Pongratz',
'Christoffer Dall', 'Shlomo Pongratz'
Hello!
> > Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> in v8 you got Peter's R-b. Did you omit it willingly or did you make any
> changes since that. A changelog would ease the review in any case.
Oops, i just forgot it. Thanks. Will fixup your notes and add it in v11.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code
2015-08-19 6:36 ` Pavel Fedin
@ 2015-08-19 7:13 ` Eric Auger
0 siblings, 0 replies; 14+ messages in thread
From: Eric Auger @ 2015-08-19 7:13 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: 'Peter Maydell', 'Shlomo Pongratz',
'Christoffer Dall', 'Shlomo Pongratz'
Hi Pavel,
On 08/19/2015 08:36 AM, Pavel Fedin wrote:
> Hello!
>
>> I think it would be worth justifying the changes in signature:
>> removal of GICState* due to the introduction of GICV3State and also
>> justify replacement of uint32_t *val into void*.
>
> I described it in the cover letter.
OK thanks for the explanations. I think they are useful to understand
the content of the patch and I would advise you to put them in the
commit message since the cover letter then is discarded when committing
the series.
Right now you don't see usage for it, but here i started
> prototyping live migration, and in some cases 'val' is going to be uint64_t. This is because
> GICD_IROUTER registers are 64 bits wide. kvm_gic_access() by itself does not dereference the
> pointer, just passes it to the kernel, therefore i decided to make it type-agnostic.
>
>> what is the point of moving kvm_gicd_access and kvm_gicc_access here? If
>> I am not mistaken, they only are used in arm_gic_kvm.c? I think they can
>> stay static in arm_gic_kvm.c?
>
> They will be used in future for live migration, at least kvm_gicd_access. kvm_gicc_access just
> accompanies it to keep a single style for both.
OK. Then either explain it in the commit msg or move them later when
live migration gets implemented.
Best Regards
Eric
>
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v10 5/5] hw/arm/virt: Add gic-version option to virt machine
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 5/5] hw/arm/virt: Add gic-version option to virt machine Pavel Fedin
@ 2015-08-19 14:08 ` Eric Auger
0 siblings, 0 replies; 14+ messages in thread
From: Eric Auger @ 2015-08-19 14:08 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Christoffer Dall, Shlomo Pongratz
Hi Pavel,
On 08/18/2015 03:33 PM, Pavel Fedin wrote:
> Add gic_version to VirtMachineState, set it to value of the option
> and pass it around where necessary. Instantiate devices and fdt
> nodes according to the choice.
>
> max_cpus for virt machine increased to 126 (calculated from redistributor
> space available in the memory map).
GICv2 compatibility check happens
> inside arm_gic_common_realize().
>
> ITS regions are added to the memory map too, however currently they
> are not used, just reserved.
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
> hw/arm/virt.c | 111 +++++++++++++++++++++++++++++++++++++++++---------
> include/hw/arm/fdt.h | 2 +-
> include/hw/arm/virt.h | 5 ++-
> 3 files changed, 96 insertions(+), 22 deletions(-)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index d5a8417..e090640 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -50,6 +50,7 @@
> #include "hw/arm/fdt.h"
> #include "hw/intc/arm_gic_common.h"
> #include "kvm_arm.h"
> +#include "qapi/visitor.h"
>
> /* Number of external interrupt lines to configure the GIC with */
> #define NUM_IRQS 256
> @@ -79,6 +80,7 @@ typedef struct {
> typedef struct {
> MachineState parent;
> bool secure;
> + int32_t gic_version;
> } VirtMachineState;
>
> #define TYPE_VIRT_MACHINE "virt"
> @@ -109,6 +111,9 @@ static const MemMapEntry a15memmap[] = {
> [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
> [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
> [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
> + [VIRT_ITS_CONTROL] = { 0x08020000, 0x00010000 },
> + [VIRT_ITS_TRANSLATION] = { 0x08030000, 0x00010000 },
> + [VIRT_GIC_REDIST] = { 0x08040000, 0x00FC0000 },
Although you put it in the commit msg, a comment saying it corresponds
to 2*64kB*126 CPUs may be worth I think
{ 0x09000000, 0x00001000 },
> [VIRT_RTC] = { 0x09010000, 0x00001000 },
> [VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
> @@ -258,10 +263,13 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
> * they are edge-triggered.
> */
> ARMCPU *armcpu;
> + uint32_t max;
> uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
>
> + /* Argument is 32 bit but 8 bits are reserved for flags */
it seems to exist a different semantic for his 3d cell depending on
GICv2/GICv3:
- in Documentation/devicetree/bindings/arm/gic.txt it is mentionned
bits[15:8] PPI interrupt cpu mask (so 8 bits only)
- in gic-v3.txt it is said the 3d cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
1 = edge triggered
4 = level triggered
> + max = (vbi->smp_cpus >= 24) ? 24 : vbi->smp_cpus;
> irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
> - GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1);
> + GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << max) - 1);
>
> qemu_fdt_add_subnode(vbi->fdt, "/timer");
>
> @@ -285,6 +293,18 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
> {
> int cpu;
>
> + /*
> + * From Documentation/devicetree/bindings/arm/cpus.txt
> + * On ARM v8 64-bit systems value should be set to 2,
> + * that corresponds to the MPIDR_EL1 register size.
> + * If MPIDR_EL1[63:32] value is equal to 0 on all CPUs
> + * in the system, #address-cells can be set to 1, since
> + * MPIDR_EL1[63:32] bits are not used for CPUs
> + * identification.
> + *
> + * Now GIC500 doesn't support affinities 2 & 3 so currently
> + * #address-cells can stay 1 until future GIC
> + */
> qemu_fdt_add_subnode(vbi->fdt, "/cpus");
> qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
> qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
> @@ -321,25 +341,36 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
> qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->v2m_phandle);
> }
>
> -static void fdt_add_gic_node(VirtBoardInfo *vbi)
> +static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
> {
> vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
> qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle);
>
> qemu_fdt_add_subnode(vbi->fdt, "/intc");
> - /* 'cortex-a15-gic' means 'GIC v2' */
> - qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
> - "arm,cortex-a15-gic");
> qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
> qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
> - qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
> - 2, vbi->memmap[VIRT_GIC_DIST].base,
> - 2, vbi->memmap[VIRT_GIC_DIST].size,
> - 2, vbi->memmap[VIRT_GIC_CPU].base,
> - 2, vbi->memmap[VIRT_GIC_CPU].size);
> qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2);
> qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2);
> qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0);
> + if (type == 3) {
> + qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
> + "arm,gic-v3");
> + qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
> + 2, vbi->memmap[VIRT_GIC_DIST].base,
> + 2, vbi->memmap[VIRT_GIC_DIST].size,
> + 2, vbi->memmap[VIRT_GIC_REDIST].base,
> + 2, vbi->memmap[VIRT_GIC_REDIST].size);
> + } else {
> + /* 'cortex-a15-gic' means 'GIC v2' */
> + qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
> + "arm,cortex-a15-gic");
> + qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
> + 2, vbi->memmap[VIRT_GIC_DIST].base,
> + 2, vbi->memmap[VIRT_GIC_DIST].size,
> + 2, vbi->memmap[VIRT_GIC_CPU].base,
> + 2, vbi->memmap[VIRT_GIC_CPU].size);
> + }
> +
> qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
> }
>
> @@ -362,18 +393,18 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
> fdt_add_v2m_gic_node(vbi);
> }
>
> -static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
> +static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type)
> {
> - /* We create a standalone GIC v2 */
> + /* We create a standalone GIC */
> DeviceState *gicdev;
> SysBusDevice *gicbusdev;
> const char *gictype;
> int i;
>
> - gictype = gic_class_name();
> + gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
>
> gicdev = qdev_create(NULL, gictype);
> - qdev_prop_set_uint32(gicdev, "revision", 2);
> + qdev_prop_set_uint32(gicdev, "revision", type);
> qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
> /* Note that the num-irq property counts both internal and external
> * interrupts; there are always 32 of the former (mandated by GIC spec).
> @@ -382,7 +413,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
> qdev_init_nofail(gicdev);
> gicbusdev = SYS_BUS_DEVICE(gicdev);
> sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
> - sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
> + if (type == 3) {
> + sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_REDIST].base);
> + } else {
> + sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
> + }
>
> /* Wire the outputs from each CPU's generic timer to the
> * appropriate GIC PPI inputs, and the GIC's IRQ output to
> @@ -417,9 +452,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
> pic[i] = qdev_get_gpio_in(gicdev, i);
> }
>
> - fdt_add_gic_node(vbi);
> + fdt_add_gic_node(vbi, type);
>
> - create_v2m(vbi, pic);
> + if (type == 2) {
> + create_v2m(vbi, pic);
> + }
> }
>
> static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
> @@ -723,7 +760,10 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic)
> qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
> nr_pcie_buses - 1);
>
> - qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent", vbi->v2m_phandle);
> + if (vbi->v2m_phandle) {
> + qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
> + vbi->v2m_phandle);
> + }
>
> qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
> 2, base_ecam, 2, size_ecam);
> @@ -883,7 +923,7 @@ static void machvirt_init(MachineState *machine)
>
> create_flash(vbi);
>
> - create_gic(vbi, pic);
> + create_gic(vbi, pic, vms->gic_version);
>
> create_uart(vbi, pic);
>
> @@ -941,6 +981,26 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
> vms->secure = value;
> }
>
> +static void virt_get_gic_version(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + VirtMachineState *vms = VIRT_MACHINE(obj);
> +
> + visit_type_int32(v, &vms->gic_version, name, errp);
> +}
> +
> +static void virt_set_gic_version(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + VirtMachineState *vms = VIRT_MACHINE(obj);
> +
> + visit_type_int32(v, &vms->gic_version, name, errp);
> + if (vms->gic_version != 2 && vms->gic_version != 3) {
> + error_report ("Only GICv2 and GICv3 supported currently\n");
checkpatch reports a warning: WARNING: space prohibited between function
name and open parenthesis '('. Also in v11 I think.
Best Regards
Eric
> + exit(1);
> + }
> +}
> +
> static void virt_instance_init(Object *obj)
> {
> VirtMachineState *vms = VIRT_MACHINE(obj);
> @@ -953,6 +1013,14 @@ static void virt_instance_init(Object *obj)
> "Set on/off to enable/disable the ARM "
> "Security Extensions (TrustZone)",
> NULL);
> +
> + /* Default GIC type is v2 */
> + vms->gic_version = 2;
> + object_property_add(obj, "gic-version", "int", virt_get_gic_version,
> + virt_set_gic_version, NULL, NULL, NULL);
> + object_property_set_description(obj, "gic-version",
> + "Set GIC version. "
> + "Valid values are 2 and 3", NULL);
> }
>
> static void virt_class_init(ObjectClass *oc, void *data)
> @@ -962,7 +1030,10 @@ static void virt_class_init(ObjectClass *oc, void *data)
> mc->name = TYPE_VIRT_MACHINE;
> mc->desc = "ARM Virtual Machine",
> mc->init = machvirt_init;
> - mc->max_cpus = 8;
> + /* Our maximum number of CPUs depends on how many redistributors
> + * we can fit into memory map
> + */
> + mc->max_cpus = a15memmap[VIRT_GIC_REDIST].size / 0x20000;
> mc->has_dynamic_sysbus = true;
> mc->block_default_type = IF_VIRTIO;
> mc->no_cdrom = 1;
> diff --git a/include/hw/arm/fdt.h b/include/hw/arm/fdt.h
> index c3d5015..dd794dd 100644
> --- a/include/hw/arm/fdt.h
> +++ b/include/hw/arm/fdt.h
> @@ -29,6 +29,6 @@
> #define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
>
> #define GIC_FDT_IRQ_PPI_CPU_START 8
> -#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
> +#define GIC_FDT_IRQ_PPI_CPU_WIDTH 24
>
> #endif
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index d22fd8e..6c5a9c9 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -46,6 +46,10 @@ enum {
> VIRT_CPUPERIPHS,
> VIRT_GIC_DIST,
> VIRT_GIC_CPU,
> + VIRT_GIC_V2M,
> + VIRT_ITS_CONTROL,
> + VIRT_ITS_TRANSLATION,
> + VIRT_GIC_REDIST,
> VIRT_UART,
> VIRT_MMIO,
> VIRT_RTC,
> @@ -54,7 +58,6 @@ enum {
> VIRT_PCIE_MMIO,
> VIRT_PCIE_PIO,
> VIRT_PCIE_ECAM,
> - VIRT_GIC_V2M,
> VIRT_PLATFORM_BUS,
> };
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-08-19 14:08 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-18 13:33 [Qemu-devel] [PATCH v10 0/5] vGICv3 support Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 1/5] hw/intc: Implement GIC-500 base class Pavel Fedin
2015-08-18 15:54 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code Pavel Fedin
2015-08-18 15:53 ` Eric Auger
2015-08-19 6:36 ` Pavel Fedin
2015-08-19 7:13 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 3/5] arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create() Pavel Fedin
2015-08-18 15:57 ` Eric Auger
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 4/5] hw/intc: Initial implementation of vGICv3 Pavel Fedin
2015-08-18 16:11 ` Eric Auger
2015-08-19 6:44 ` Pavel Fedin
2015-08-18 13:33 ` [Qemu-devel] [PATCH v10 5/5] hw/arm/virt: Add gic-version option to virt machine Pavel Fedin
2015-08-19 14:08 ` Eric Auger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).