* [Qemu-devel] [PATCH v4 0/5] vGICv3 support
@ 2015-07-14 7:54 Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 1/5] Implement GIC-500 base class Pavel Fedin
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Pavel Fedin @ 2015-07-14 7:54 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.
Differences from v3:
- 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
Differences from v2:
- 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
Differences from v1:
- 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):
Extract some reusable vGIC code
Introduce irqchip type specification for KVM
Initial implementation of vGICv3
Add gicversion option to virt machine
Shlomo Pongratz (1):
Implement GIC-500 base class
hw/arm/vexpress.c | 1 +
hw/arm/virt.c | 138 ++++++++++++++++++++----
hw/intc/Makefile.objs | 4 +
hw/intc/arm_gic_kvm.c | 84 +++++++--------
hw/intc/arm_gicv3_common.c | 216 +++++++++++++++++++++++++++++++++++++
hw/intc/arm_gicv3_kvm.c | 192 +++++++++++++++++++++++++++++++++
hw/intc/gicv3_internal.h | 156 +++++++++++++++++++++++++++
hw/intc/vgic_common.h | 43 ++++++++
include/hw/arm/fdt.h | 2 +-
include/hw/arm/virt.h | 6 +-
include/hw/boards.h | 1 +
include/hw/intc/arm_gicv3_common.h | 113 +++++++++++++++++++
include/sysemu/kvm.h | 3 +-
kvm-all.c | 2 +-
stubs/kvm.c | 2 +-
target-arm/kvm.c | 13 ++-
16 files changed, 903 insertions(+), 73 deletions(-)
create mode 100644 hw/intc/arm_gicv3_common.c
create mode 100644 hw/intc/arm_gicv3_kvm.c
create mode 100644 hw/intc/gicv3_internal.h
create mode 100644 hw/intc/vgic_common.h
create mode 100644 include/hw/intc/arm_gicv3_common.h
--
2.4.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 1/5] Implement GIC-500 base class
2015-07-14 7:54 [Qemu-devel] [PATCH v4 0/5] vGICv3 support Pavel Fedin
@ 2015-07-14 7:54 ` Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 2/5] Extract some reusable vGIC code Pavel Fedin
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Pavel Fedin @ 2015-07-14 7:54 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
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 | 216 +++++++++++++++++++++++++++++++++++++
hw/intc/gicv3_internal.h | 156 +++++++++++++++++++++++++++
include/hw/intc/arm_gicv3_common.h | 113 +++++++++++++++++++
4 files changed, 486 insertions(+)
create mode 100644 hw/intc/arm_gicv3_common.c
create mode 100644 hw/intc/gicv3_internal.h
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..86af129
--- /dev/null
+++ b/hw/intc/arm_gicv3_common.c
@@ -0,0 +1,216 @@
+/*
+ * 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 "gicv3_internal.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_irq_state = {
+ .name = "arm_gicv3_irq_state",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(pending, gicv3_irq_state),
+ VMSTATE_UINT64(active, gicv3_irq_state),
+ VMSTATE_UINT64(level, gicv3_irq_state),
+ VMSTATE_UINT64(group, gicv3_irq_state),
+ VMSTATE_BOOL(edge_trigger, gicv3_irq_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_gicv3_sgi_state = {
+ .name = "arm_gicv3_sgi_state",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64_ARRAY(pending, gicv3_sgi_state, GICV3_NCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_gicv3 = {
+ .name = "arm_gicv3",
+ .version_id = 7,
+ .minimum_version_id = 7,
+ .pre_save = gicv3_pre_save,
+ .post_load = gicv3_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ctlr, GICv3State),
+ VMSTATE_UINT32_ARRAY(cpu_ctlr, GICv3State, GICV3_NCPU),
+ VMSTATE_STRUCT_ARRAY(irq_state, GICv3State, GICV3_MAXIRQ, 1,
+ vmstate_gicv3_irq_state, gicv3_irq_state),
+ VMSTATE_UINT64_ARRAY(irq_target, GICv3State, GICV3_MAXIRQ),
+ VMSTATE_UINT8_2DARRAY(priority1, GICv3State, GICV3_INTERNAL,
+ GICV3_NCPU),
+ VMSTATE_UINT8_ARRAY(priority2, GICv3State,
+ GICV3_MAXIRQ - GICV3_INTERNAL),
+ VMSTATE_UINT16_2DARRAY(last_active, GICv3State, GICV3_MAXIRQ,
+ GICV3_NCPU),
+ VMSTATE_STRUCT_ARRAY(sgi_state, GICv3State, GICV3_NR_SGIS, 1,
+ vmstate_gicv3_sgi_state, gicv3_sgi_state),
+ VMSTATE_UINT16_ARRAY(priority_mask, GICv3State, GICV3_NCPU),
+ VMSTATE_UINT16_ARRAY(running_irq, GICv3State, GICV3_NCPU),
+ VMSTATE_UINT16_ARRAY(running_priority, GICv3State, GICV3_NCPU),
+ VMSTATE_UINT16_ARRAY(current_pending, GICv3State, GICV3_NCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
+{
+ GICv3State *s = ARM_GICV3_COMMON(dev);
+ int num_irq = s->num_irq;
+
+ if (s->num_cpu > GICV3_NCPU) {
+ error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
+ s->num_cpu, GICV3_NCPU);
+ return;
+ }
+ s->num_irq += GICV3_BASE_IRQ;
+ if (s->num_irq > GICV3_MAXIRQ) {
+ error_setg(errp,
+ "requested %u interrupt lines exceeds GIC maximum %d",
+ num_irq, GICV3_MAXIRQ);
+ return;
+ }
+ /* ITLinesNumber is represented as (N / 32) - 1 (see
+ * gic_dist_readb) so this is an implementation imposed
+ * restriction, not an architectural one:
+ */
+ if (s->num_irq < 32 || (s->num_irq % 32)) {
+ error_setg(errp,
+ "%d interrupt lines unsupported: not divisible by 32",
+ num_irq);
+ return;
+ }
+}
+
+static void arm_gicv3_common_reset(DeviceState *dev)
+{
+ GICv3State *s = ARM_GICV3_COMMON(dev);
+ int i;
+
+ /* Note num_cpu and num_irq are properties */
+
+ /* Don't reset anything assigned in arm_gic_realize or any property */
+
+ /* No GICv2 backwards computability support */
+ for (i = 0; i < s->num_cpu; i++) {
+ s->priority_mask[i] = 0;
+ s->current_pending[i] = 1023;
+ s->running_irq[i] = 1023;
+ s->running_priority[i] = 0x100;
+ s->cpu_ctlr[i] = 0;
+ }
+
+ memset(s->irq_state, 0, sizeof(s->irq_state));
+ /* GIC-500 comment 'j' SGI are always enabled */
+ for (i = 0; i < GICV3_NR_SGIS; i++) {
+ GIC_SET_ENABLED(i, ALL_CPU_MASK);
+ GIC_SET_EDGE_TRIGGER(i);
+ }
+ memset(s->sgi_state, 0, sizeof(s->sgi_state));
+ memset(s->irq_target, 0, sizeof(s->irq_target));
+ if (s->num_cpu == 1) {
+ /* For uniprocessor GICs all interrupts always target the sole CPU */
+ for (i = 0; i < GICV3_MAXIRQ; i++) {
+ s->irq_target[i] = 1;
+ }
+ }
+ memset(s->priority1, 0, sizeof(s->priority1));
+ memset(s->priority2, 0, sizeof(s->priority2));
+ memset(s->last_active, 0, sizeof(s->last_active));
+
+ /* With all configuration we don't support GICv2 backwards computability */
+ if (s->security_levels > 1) {
+ /* GICv3 5.3.20 With two security So DS is RAZ/WI ARE_NS is RAO/WI
+ * and ARE_S is RAO/WI
+ */
+ s->ctlr = GICD_CTLR_ARE_S | GICD_CTLR_ARE_NS;
+ } else {
+ /* GICv3 5.3.20 With one security So DS is RAO/WI ARE is RAO/WI
+ */
+ s->ctlr = GICD_CTLR_DS | GICD_CTLR_ARE;
+ }
+ /* Workaround!
+ * Linux (drivers/irqchip/irq-gic-v3.c) is enabling only group one,
+ * in gic_cpu_sys_reg_init it calls gic_write_grpen1(1);
+ * but it doesn't conigure any interrupt to be in group one
+ */
+ for (i = 0; i < s->num_irq; i++)
+ GIC_SET_GROUP(i, ALL_CPU_MASK);
+}
+
+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),
+ /* How many security levels are supported */
+ DEFINE_PROP_BOOL("security-levels", GICv3State, security_levels, 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/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
new file mode 100644
index 0000000..a0d4228
--- /dev/null
+++ b/hw/intc/gicv3_internal.h
@@ -0,0 +1,156 @@
+/*
+ * ARM GIC support - internal interfaces
+ *
+ * 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 QEMU_ARM_GICV3_INTERNAL_H
+#define QEMU_ARM_GICV3_INTERNAL_H
+
+#include "hw/intc/arm_gicv3_common.h"
+
+#define ALL_CPU_MASK ((uint64_t) (0xffffffffffffffff))
+
+/* Keep this macro so it will be easy to compare the code to GICv2 code.
+ * The compiler will optimize any +/- operation involving this macro
+ */
+#define GICV3_BASE_IRQ (0)
+
+#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
+#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
+#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
+#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
+#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
+#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
+#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
+#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
+#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
+#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level |= (cm)
+#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
+#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
+#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
+#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false
+#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
+#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GICV3_INTERNAL) ? \
+ s->priority1[irq][cpu] : \
+ s->priority2[(irq) - GICV3_INTERNAL])
+#define GIC_TARGET(irq) s->irq_target[irq]
+#define GIC_CLEAR_GROUP(irq, cm) (s->irq_state[irq].group &= ~(cm))
+#define GIC_SET_GROUP(irq, cm) (s->irq_state[irq].group |= (cm))
+#define GIC_TEST_GROUP(irq, cm) ((s->irq_state[irq].group & (cm)) != 0)
+
+static inline bool gic_test_pending(GICv3State *s, int irq, uint64_t cm)
+{
+ /* Edge-triggered interrupts are marked pending on a rising edge, but
+ * level-triggered interrupts are either considered pending when the
+ * level is active or if software has explicitly written to
+ * GICD_ISPENDR to set the state pending.
+ */
+ return (s->irq_state[irq].pending & cm) ||
+ (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_LEVEL(irq, cm));
+}
+
+#define GICD_CTLR 0x0000
+#define GICD_TYPER 0x0004
+#define GICD_IIDR 0x0008
+#define GICD_STATUSR 0x0010
+#define GICD_SETSPI_NSR 0x0040
+#define GICD_CLRSPI_NSR 0x0048
+#define GICD_SETSPI_SR 0x0050
+#define GICD_CLRSPI_SR 0x0058
+#define GICD_SEIR 0x0068
+#define GICD_ISENABLER 0x0100
+#define GICD_ICENABLER 0x0180
+#define GICD_ISPENDR 0x0200
+#define GICD_ICPENDR 0x0280
+#define GICD_ISACTIVER 0x0300
+#define GICD_ICACTIVER 0x0380
+#define GICD_IPRIORITYR 0x0400
+#define GICD_ICFGR 0x0C00
+#define GICD_IROUTER 0x6000
+#define GICD_PIDR2 0xFFE8
+
+/* GICD_CTLR fields */
+#define GICD_CTLR_EN_GRP0 (1U << 0)
+#define GICD_CTLR_EN_GRP1NS (1U << 1) /* GICv3 5.3.20 */
+#define GICD_CTLR_EN_GRP1S (1U << 2)
+#define GICD_CTLR_EN_GRP1_ALL (GICD_CTLR_EN_GRP1NS | GICD_CTLR_EN_GRP1S)
+#define GICD_CTLR_ARE (1U << 4)
+#define GICD_CTLR_ARE_S (1U << 4)
+#define GICD_CTLR_ARE_NS (1U << 5)
+#define GICD_CTLR_DS (1U << 6)
+#define GICD_CTLR_RWP (1U << 31)
+
+#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
+#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)
+
+#define GIC_PIDR2_ARCH_MASK 0xf0
+#define GIC_PIDR2_ARCH_GICv3 0x30
+#define GIC_PIDR2_ARCH_GICv4 0x40
+
+/*
+ * Re-Distributor registers, offsets from RD_base
+ */
+#define GICR_CTLR GICD_CTLR
+#define GICR_IIDR 0x0004
+#define GICR_TYPER 0x0008
+#define GICR_STATUSR GICD_STATUSR
+#define GICR_WAKER 0x0014
+#define GICR_SETLPIR 0x0040
+#define GICR_CLRLPIR 0x0048
+#define GICR_SEIR GICD_SEIR
+#define GICR_PROPBASER 0x0070
+#define GICR_PENDBASER 0x0078
+#define GICR_INVLPIR 0x00A0
+#define GICR_INVALLR 0x00B0
+#define GICR_SYNCR 0x00C0
+#define GICR_MOVLPIR 0x0100
+#define GICR_MOVALLR 0x0110
+#define GICR_PIDR2 GICD_PIDR2
+
+#define GICR_WAKER_ProcessorSleep (1U << 1)
+#define GICR_WAKER_ChildrenAsleep (1U << 2)
+
+/*
+ * Re-Distributor registers, offsets from SGI_base
+ */
+#define GICR_ISENABLER0 GICD_ISENABLER
+#define GICR_ICENABLER0 GICD_ICENABLER
+#define GICR_ISPENDR0 GICD_ISPENDR
+#define GICR_ICPENDR0 GICD_ICPENDR
+#define GICR_ISACTIVER0 GICD_ISACTIVER
+#define GICR_ICACTIVER0 GICD_ICACTIVER
+#define GICR_IPRIORITYR0 GICD_IPRIORITYR
+#define GICR_ICFGR0 GICD_ICFGR
+
+#define GICR_TYPER_VLPIS (1U << 1)
+#define GICR_TYPER_LAST (1U << 4)
+
+/*
+ * Simulated used system registers
+ */
+#define GICC_CTLR_EN_GRP0 (1U << 0)
+#define GICC_CTLR_EN_GRP1 (1U << 1)
+#define GICC_CTLR_ACK_CTL (1U << 2)
+#define GICC_CTLR_FIQ_EN (1U << 3)
+#define GICC_CTLR_CBPR (1U << 4) /* GICv1: SBPR */
+#define GICC_CTLR_EOIMODE (1U << 9)
+#define GICC_CTLR_EOIMODE_NS (1U << 10)
+
+#endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
new file mode 100644
index 0000000..7e4b358
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -0,0 +1,113 @@
+/*
+ * 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"
+
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GICV3_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GICV3_INTERNAL 32
+#define GICV3_NR_SGIS 16
+#define GICV3_NCPU 64
+
+#define MAX_NR_GROUP_PRIO 128
+
+typedef struct gicv3_irq_state {
+ /* The enable bits are only banked for per-cpu interrupts. */
+ uint64_t enabled;
+ uint64_t pending;
+ uint64_t active;
+ uint64_t level;
+ uint64_t group;
+ bool edge_trigger; /* true: edge-triggered, false: level-triggered */
+} gicv3_irq_state;
+
+typedef struct gicv3_sgi_state {
+ uint64_t pending[GICV3_NCPU];
+} gicv3_sgi_state;
+
+typedef struct GICv3State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ qemu_irq parent_irq[GICV3_NCPU];
+ qemu_irq parent_fiq[GICV3_NCPU];
+ /* GICD_CTLR; for a GIC with the security extensions the NS banked version
+ * of this register is just an alias of bit 1 of the S banked version.
+ */
+ uint32_t ctlr;
+ /* Sim GICC_CTLR; again, the NS banked version is just aliases of bits of
+ * the S banked register, so our state only needs to store the S version.
+ */
+ uint32_t cpu_ctlr[GICV3_NCPU];
+ bool cpu_enabled[GICV3_NCPU];
+
+ gicv3_irq_state irq_state[GICV3_MAXIRQ];
+ uint64_t irq_target[GICV3_MAXIRQ];
+ uint8_t priority1[GICV3_INTERNAL][GICV3_NCPU];
+ uint8_t priority2[GICV3_MAXIRQ - GICV3_INTERNAL];
+ uint16_t last_active[GICV3_MAXIRQ][GICV3_NCPU];
+ /* For each SGI on the target CPU, we store 64 bits
+ * indicating which source CPUs have made this SGI
+ * pending on the target CPU. These correspond to
+ * the bytes in the GIC_SPENDSGIR* registers as
+ * read by the target CPU.
+ */
+ gicv3_sgi_state sgi_state[GICV3_NR_SGIS];
+
+ uint16_t priority_mask[GICV3_NCPU];
+ uint16_t running_irq[GICV3_NCPU];
+ uint16_t running_priority[GICV3_NCPU];
+ uint16_t current_pending[GICV3_NCPU];
+
+ uint32_t cpu_mask; /* For redistributor */
+ uint32_t num_cpu;
+ MemoryRegion iomem_dist; /* Distributor */
+ MemoryRegion iomem_lpi; /* Redistributor */
+ uint32_t num_irq;
+ uint32_t revision;
+ bool security_levels;
+ 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;
+
+#endif
--
2.4.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 2/5] Extract some reusable vGIC code
2015-07-14 7:54 [Qemu-devel] [PATCH v4 0/5] vGICv3 support Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 1/5] Implement GIC-500 base class Pavel Fedin
@ 2015-07-14 7:54 ` Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 3/5] Introduce irqchip type specification for KVM Pavel Fedin
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Pavel Fedin @ 2015-07-14 7:54 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 | 84 ++++++++++++++++++++++++---------------------------
hw/intc/vgic_common.h | 43 ++++++++++++++++++++++++++
2 files changed, 82 insertions(+), 45 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 f56bff1..9b6d702 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,12 +87,19 @@ 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;
}
-static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
+bool kvm_gic_supports_attr(int dev_fd, int group, int attrnum)
{
struct kvm_device_attr attr = {
.group = group,
@@ -100,14 +107,14 @@ static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
.flags = 0,
};
- if (s->dev_fd == -1) {
+ if (dev_fd == -1) {
return false;
}
- return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
+ return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
}
-static void kvm_gic_access(GICState *s, int group, int offset,
+void kvm_gic_access(int dev_fd, int group, int offset,
int cpu, uint32_t *val, bool write)
{
struct kvm_device_attr attr;
@@ -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++)
@@ -291,7 +284,7 @@ static void kvm_dist_get(GICState *s, uint32_t offset, int width,
irq = i * regsz;
cpu = 0;
while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
- kvm_gicd_access(s, offset, cpu, ®, false);
+ kvm_gicd_access(s->dev_fd, offset, cpu, ®, false);
for (j = 0; j < regsz; j++) {
field = extract32(reg, j * width, width);
translate_fn(s, irq + j, cpu, &field, false);
@@ -324,7 +317,7 @@ static void kvm_dist_put(GICState *s, uint32_t offset, int width,
translate_fn(s, irq + j, cpu, &field, true);
reg = deposit32(reg, j * width, width, field);
}
- kvm_gicd_access(s, offset, cpu, ®, true);
+ kvm_gicd_access(s->dev_fd, offset, cpu, ®, true);
cpu++;
}
@@ -355,10 +348,10 @@ static void kvm_arm_gic_put(GICState *s)
/* s->ctlr -> GICD_CTLR */
reg = s->ctlr;
- kvm_gicd_access(s, 0x0, 0, ®, true);
+ kvm_gicd_access(s->dev_fd, 0x0, 0, ®, true);
/* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */
- kvm_gicd_access(s, 0x4, 0, ®, false);
+ kvm_gicd_access(s->dev_fd, 0x4, 0, ®, false);
num_irq = ((reg & 0x1f) + 1) * 32;
num_cpu = ((reg & 0xe0) >> 5) + 1;
@@ -416,24 +409,24 @@ static void kvm_arm_gic_put(GICState *s)
for (cpu = 0; cpu < s->num_cpu; cpu++) {
/* s->cpu_ctlr[cpu] -> GICC_CTLR */
reg = s->cpu_ctlr[cpu];
- kvm_gicc_access(s, 0x00, cpu, ®, true);
+ kvm_gicc_access(s->dev_fd, 0x00, cpu, ®, true);
/* s->priority_mask[cpu] -> GICC_PMR */
reg = (s->priority_mask[cpu] & 0xff);
- kvm_gicc_access(s, 0x04, cpu, ®, true);
+ kvm_gicc_access(s->dev_fd, 0x04, cpu, ®, true);
/* s->bpr[cpu] -> GICC_BPR */
reg = (s->bpr[cpu] & 0x7);
- kvm_gicc_access(s, 0x08, cpu, ®, true);
+ kvm_gicc_access(s->dev_fd, 0x08, cpu, ®, true);
/* s->abpr[cpu] -> GICC_ABPR */
reg = (s->abpr[cpu] & 0x7);
- kvm_gicc_access(s, 0x1c, cpu, ®, true);
+ kvm_gicc_access(s->dev_fd, 0x1c, cpu, ®, true);
/* s->apr[n][cpu] -> GICC_APRn */
for (i = 0; i < 4; i++) {
reg = s->apr[i][cpu];
- kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, true);
+ kvm_gicc_access(s->dev_fd, 0xd0 + i * 4, cpu, ®, true);
}
}
}
@@ -454,11 +447,11 @@ static void kvm_arm_gic_get(GICState *s)
*/
/* GICD_CTLR -> s->ctlr */
- kvm_gicd_access(s, 0x0, 0, ®, false);
+ kvm_gicd_access(s->dev_fd, 0x0, 0, ®, false);
s->ctlr = reg;
/* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */
- kvm_gicd_access(s, 0x4, 0, ®, false);
+ kvm_gicd_access(s->dev_fd, 0x4, 0, ®, false);
s->num_irq = ((reg & 0x1f) + 1) * 32;
s->num_cpu = ((reg & 0xe0) >> 5) + 1;
@@ -469,7 +462,7 @@ static void kvm_arm_gic_get(GICState *s)
}
/* GICD_IIDR -> ? */
- kvm_gicd_access(s, 0x8, 0, ®, false);
+ kvm_gicd_access(s->dev_fd, 0x8, 0, ®, false);
/* Clear all the IRQ settings */
for (i = 0; i < s->num_irq; i++) {
@@ -507,24 +500,24 @@ static void kvm_arm_gic_get(GICState *s)
for (cpu = 0; cpu < s->num_cpu; cpu++) {
/* GICC_CTLR -> s->cpu_ctlr[cpu] */
- kvm_gicc_access(s, 0x00, cpu, ®, false);
+ kvm_gicc_access(s->dev_fd, 0x00, cpu, ®, false);
s->cpu_ctlr[cpu] = reg;
/* GICC_PMR -> s->priority_mask[cpu] */
- kvm_gicc_access(s, 0x04, cpu, ®, false);
+ kvm_gicc_access(s->dev_fd, 0x04, cpu, ®, false);
s->priority_mask[cpu] = (reg & 0xff);
/* GICC_BPR -> s->bpr[cpu] */
- kvm_gicc_access(s, 0x08, cpu, ®, false);
+ kvm_gicc_access(s->dev_fd, 0x08, cpu, ®, false);
s->bpr[cpu] = (reg & 0x7);
/* GICC_ABPR -> s->abpr[cpu] */
- kvm_gicc_access(s, 0x1c, cpu, ®, false);
+ kvm_gicc_access(s->dev_fd, 0x1c, cpu, ®, false);
s->abpr[cpu] = (reg & 0x7);
/* GICC_APRn -> s->apr[n][cpu] */
for (i = 0; i < 4; i++) {
- kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, false);
+ kvm_gicc_access(s->dev_fd, 0xd0 + i * 4, cpu, ®, false);
s->apr[i][cpu] = reg;
}
}
@@ -569,7 +562,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
* ...
*/
i += (GIC_INTERNAL * s->num_cpu);
- qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i);
+ qdev_init_gpio_in(dev, kvm_arm_gicv2_set_irq, i);
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
qemu_irq irq = qdev_get_gpio_in(dev, i);
@@ -596,15 +589,16 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
- if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
+ if (kvm_gic_supports_attr(s->dev_fd, 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,
+ if (kvm_gic_supports_attr(s->dev_fd, 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..67241d3
--- /dev/null
+++ b/hw/intc/vgic_common.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+
+void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level);
+bool kvm_gic_supports_attr(int dev_fd, int group, int attrnum);
+void kvm_gic_access(int dev_fd, int group, int offset, int cpu,
+ uint32_t *val, bool write);
+
+static inline void kvm_gicd_access(int dev_fd, int offset, int cpu,
+ uint32_t *val, bool write)
+{
+ kvm_gic_access(dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ offset, cpu, val, write);
+}
+
+static inline void kvm_gicc_access(int dev_fd, int offset, int cpu,
+ uint32_t *val, bool write)
+{
+ kvm_gic_access(dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+ offset, cpu, val, write);
+}
+
+#endif
--
2.4.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 3/5] Introduce irqchip type specification for KVM
2015-07-14 7:54 [Qemu-devel] [PATCH v4 0/5] vGICv3 support Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 1/5] Implement GIC-500 base class Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 2/5] Extract some reusable vGIC code Pavel Fedin
@ 2015-07-14 7:54 ` Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3 Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine Pavel Fedin
4 siblings, 0 replies; 9+ messages in thread
From: Pavel Fedin @ 2015-07-14 7:54 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz,
Christoffer Dall, Eric Auger
This patch introduces kernel_irqchip_type member in Machine class, which
it passed to kvm_arch_irqchip_create. It allows machine models to specify
correct GIC type during KVM capability verification. The variable is
defined as int in order to be architecture-agnostic for potential future
uses by other architectures.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/arm/vexpress.c | 1 +
hw/arm/virt.c | 3 +++
include/hw/boards.h | 1 +
include/sysemu/kvm.h | 3 ++-
kvm-all.c | 2 +-
stubs/kvm.c | 2 +-
target-arm/kvm.c | 13 +++++++++++--
7 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index da21788..0675a00 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -556,6 +556,7 @@ static void vexpress_common_init(MachineState *machine)
const hwaddr *map = daughterboard->motherboard_map;
int i;
+ machine->kernel_irqchip_type = KVM_DEV_TYPE_ARM_VGIC_V2;
daughterboard->init(vms, machine->ram_size, machine->cpu_model, pic);
/*
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 4846892..2e7d858 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -945,6 +945,9 @@ 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->parent.kernel_irqchip_type = KVM_DEV_TYPE_ARM_VGIC_V2;
}
static void virt_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 2aec9cb..37eb767 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -127,6 +127,7 @@ struct MachineState {
char *accel;
bool kernel_irqchip_allowed;
bool kernel_irqchip_required;
+ int kernel_irqchip_type;
int kvm_shadow_mem;
char *dtb;
char *dumpdtb;
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 983e99e..8f4d485 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -434,6 +434,7 @@ void kvm_init_irq_routing(KVMState *s);
/**
* kvm_arch_irqchip_create:
* @KVMState: The KVMState pointer
+ * @type: irqchip type, architecture-specific
*
* Allow architectures to create an in-kernel irq chip themselves.
*
@@ -441,7 +442,7 @@ void kvm_init_irq_routing(KVMState *s);
* 0: irq chip was not created
* > 0: irq chip was created
*/
-int kvm_arch_irqchip_create(KVMState *s);
+int kvm_arch_irqchip_create(KVMState *s, int type);
/**
* kvm_set_one_reg - set a register value in KVM via KVM_SET_ONE_REG ioctl
diff --git a/kvm-all.c b/kvm-all.c
index 06e06f2..8df938d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1395,7 +1395,7 @@ static void kvm_irqchip_create(MachineState *machine, KVMState *s)
/* First probe and see if there's a arch-specific hook to create the
* in-kernel irqchip for us */
- ret = kvm_arch_irqchip_create(s);
+ ret = kvm_arch_irqchip_create(s, machine->kernel_irqchip_type);
if (ret == 0) {
ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
}
diff --git a/stubs/kvm.c b/stubs/kvm.c
index e7c60b6..a8505ff 100644
--- a/stubs/kvm.c
+++ b/stubs/kvm.c
@@ -1,7 +1,7 @@
#include "qemu-common.h"
#include "sysemu/kvm.h"
-int kvm_arch_irqchip_create(KVMState *s)
+int kvm_arch_irqchip_create(KVMState *s, int type)
{
return 0;
}
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 548bfd7..3992c1f 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -579,19 +579,28 @@ void kvm_arch_init_irq_routing(KVMState *s)
{
}
-int kvm_arch_irqchip_create(KVMState *s)
+int kvm_arch_irqchip_create(KVMState *s, int type)
{
int ret;
+ /* Failure here means forgotten initialization of
+ * machine->kernel_irqchip_type in model code
+ */
+ assert(type != 0);
+
/* 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);
+ ret = kvm_create_device(s, type, true);
if (ret == 0) {
return 1;
}
+ /* Fallback will create VGIC v2 */
+ if (type != KVM_DEV_TYPE_ARM_VGIC_V2) {
+ return ret;
+ }
return 0;
}
--
2.4.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3
2015-07-14 7:54 [Qemu-devel] [PATCH v4 0/5] vGICv3 support Pavel Fedin
` (2 preceding siblings ...)
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 3/5] Introduce irqchip type specification for KVM Pavel Fedin
@ 2015-07-14 7:54 ` Pavel Fedin
2015-07-15 14:38 ` Diana Craciun
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine Pavel Fedin
4 siblings, 1 reply; 9+ messages in thread
From: Pavel Fedin @ 2015-07-14 7:54 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz,
Christoffer Dall, Eric Auger
Get/put routines are missing, live migration is not possible.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/intc/Makefile.objs | 3 +
hw/intc/arm_gicv3_kvm.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 195 insertions(+)
create mode 100644 hw/intc/arm_gicv3_kvm.c
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 1317e5a..e2525a8 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -17,6 +17,9 @@ common-obj-$(CONFIG_OPENPIC) += openpic.o
obj-$(CONFIG_APIC) += apic.o apic_common.o
obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
+ifeq ($(ARCH), aarch64) # Only 64-bit KVM can use these
+obj-$(CONFIG_ARM_GIC_KVM) += arm_gicv3_kvm.o
+endif
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..4bc8f25
--- /dev/null
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -0,0 +1,192 @@
+/*
+ * 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/sysbus.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+#include "gicv3_internal.h"
+#include "vgic_common.h"
+
+#ifdef DEBUG_GICV3_KVM
+static const int debug_gicv3_kvm = 1;
+#else
+static const int debug_gicv3_kvm = 0;
+#endif
+
+#define DPRINTF(fmt, ...) do { \
+ if (debug_gicv3_kvm) { \
+ printf("kvm_gicv3: " fmt , ## __VA_ARGS__); \
+ } \
+ } while (0)
+
+#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)
+{
+ int i;
+ GICv3State *s = KVM_ARM_GICV3(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
+ Error *local_err = NULL;
+ int ret;
+
+ DPRINTF("kvm_arm_gicv3_realize\n");
+
+ kgc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ i = s->num_irq - GICV3_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 += (GICV3_INTERNAL * s->num_cpu);
+ qdev_init_gpio_in(dev, kvm_arm_gicv3_set_irq, i);
+ /* We never use our outbound IRQ 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_V3, false);
+ if (ret >= 0) {
+ s->dev_fd = ret;
+ } else if (ret != -ENODEV && ret != -ENOTSUP) {
+ error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
+ return;
+ }
+
+ if (kvm_gic_supports_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
+ uint32_t numirqs = s->num_irq;
+ DPRINTF("KVM_DEV_ARM_VGIC_GRP_NR_IRQS = %u\n", numirqs);
+ 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->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT)) {
+ DPRINTF("KVM_DEV_ARM_VGIC_CTRL_INIT\n");
+ kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
+ }
+
+ /* Distributor */
+ memory_region_init_reservation(&s->iomem_dist, OBJECT(s),
+ "kvm-gicv3_dist", 0x10000);
+ sysbus_init_mmio(sbd, &s->iomem_dist);
+ kvm_arm_register_device(&s->iomem_dist, -1,
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V3_ADDR_TYPE_DIST,
+ s->dev_fd);
+
+ /* Redistributor */
+ memory_region_init_reservation(&s->iomem_lpi, OBJECT(s),
+ "kvm-gicv3_lpi", 0x800000);
+ sysbus_init_mmio(sbd, &s->iomem_lpi);
+ kvm_arm_register_device(&s->iomem_lpi, -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)
--
2.4.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine
2015-07-14 7:54 [Qemu-devel] [PATCH v4 0/5] vGICv3 support Pavel Fedin
` (3 preceding siblings ...)
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3 Pavel Fedin
@ 2015-07-14 7:54 ` Pavel Fedin
2015-07-15 14:44 ` Diana Craciun
4 siblings, 1 reply; 9+ messages in thread
From: Pavel Fedin @ 2015-07-14 7:54 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Shlomo Pongratz,
Christoffer Dall, Eric Auger
Set kernel_irqchip_type according to value of the option and pass it
around where necessary. Instantiate devices and fdt nodes according
to the choice.
mac_cpus for virt machine increased to 64. GICv2 compatibility check
happens inside arm_gic_common_realize().
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
hw/arm/virt.c | 135 ++++++++++++++++++++++++++++++++++++++++++--------
include/hw/arm/fdt.h | 2 +-
include/hw/arm/virt.h | 6 ++-
3 files changed, 120 insertions(+), 23 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 2e7d858..df69dc8 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -48,6 +48,8 @@
#include "hw/arm/sysbus-fdt.h"
#include "hw/platform-bus.h"
#include "hw/arm/fdt.h"
+#include "linux/kvm.h" /* For KVM_DEV_TYPE_ARM_VGIC_V{2|3} */
+#include "qapi/visitor.h"
/* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 256
@@ -67,6 +69,7 @@ typedef struct VirtBoardInfo {
uint32_t clock_phandle;
uint32_t gic_phandle;
uint32_t v2m_phandle;
+ const char *class_name;
} VirtBoardInfo;
typedef struct {
@@ -80,6 +83,7 @@ typedef struct {
} VirtMachineState;
#define TYPE_VIRT_MACHINE "virt"
+#define TYPE_VIRTV3_MACHINE "virt-v3"
#define VIRT_MACHINE(obj) \
OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
#define VIRT_MACHINE_GET_CLASS(obj) \
@@ -106,7 +110,12 @@ static const MemMapEntry a15memmap[] = {
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
- [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
+ [VIRT_GIC_V2M] = { 0x08020000, 0x00010000 },
+ /* On v3 VIRT_GIC_DIST_MBI and VIRT_ITS_CONTROL take place of
+ * VIRT_GIC_CPU and VIRT_GIC_V2M respectively
+ */
+ [VIRT_ITS_TRANSLATION] = { 0x08030000, 0x00010000 },
+ [VIRT_LPI] = { 0x08040000, 0x00800000 },
[VIRT_UART] = { 0x09000000, 0x00001000 },
[VIRT_RTC] = { 0x09010000, 0x00001000 },
[VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
@@ -256,10 +265,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");
@@ -283,6 +295,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);
@@ -319,25 +343,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 == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ 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_LPI].base,
+ 2, vbi->memmap[VIRT_LPI].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);
}
@@ -360,20 +395,35 @@ 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 */
DeviceState *gicdev;
SysBusDevice *gicbusdev;
- const char *gictype = "arm_gic";
+ const char *gictype;
int i;
- if (kvm_irqchip_in_kernel()) {
- gictype = "kvm-arm-gic";
+ if (type == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ /* TODO: Software emulation is not implemented yet */
+ if (!kvm_irqchip_in_kernel()) {
+ fprintf(stderr, "KVM is currently required for GICv3 emulation\n");
+ exit(1);
+ }
+ gictype = "kvm-arm-gicv3";
+ } else {
+ gictype = kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic";
}
gicdev = qdev_create(NULL, gictype);
- qdev_prop_set_uint32(gicdev, "revision", 2);
+
+ for (i = 0; i < vbi->smp_cpus; i++) {
+ CPUState *cpu = qemu_get_cpu(i);
+ CPUARMState *env = cpu->env_ptr;
+ env->nvic = gicdev;
+ }
+
+ qdev_prop_set_uint32(gicdev, "revision",
+ type == KVM_DEV_TYPE_ARM_VGIC_V3 ? 3 : 2);
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 +432,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 == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_LPI].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
@@ -409,9 +463,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 == KVM_DEV_TYPE_ARM_VGIC_V2) {
+ create_v2m(vbi, pic);
+ }
}
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
@@ -875,7 +931,7 @@ static void machvirt_init(MachineState *machine)
create_flash(vbi);
- create_gic(vbi, pic);
+ create_gic(vbi, pic, machine->kernel_irqchip_type);
create_uart(vbi, pic);
@@ -933,6 +989,37 @@ 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)
+{
+ MachineState *ms = MACHINE(obj);
+ int32_t value = (ms->kernel_irqchip_type == KVM_DEV_TYPE_ARM_VGIC_V3) ?
+ 3 : 2;
+
+ visit_type_int32(v, &value, name, errp);
+}
+
+static void virt_set_gic_version(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+ int32_t value;
+
+ visit_type_int32(v, &value, name, errp);
+
+ switch (value) {
+ case 3:
+ ms->kernel_irqchip_type = KVM_DEV_TYPE_ARM_VGIC_V3;
+ break;
+ case 2:
+ ms->kernel_irqchip_type = KVM_DEV_TYPE_ARM_VGIC_V2;
+ break;
+ default:
+ error_report ("Only GICv2 and GICv3 supported currently\n");
+ exit(1);
+ }
+}
+
static void virt_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -948,6 +1035,11 @@ static void virt_instance_init(Object *obj)
/* Default GIC type is v2 */
vms->parent.kernel_irqchip_type = KVM_DEV_TYPE_ARM_VGIC_V2;
+ object_property_add(obj, "gicversion", "int", virt_get_gic_version,
+ virt_set_gic_version, NULL, NULL, NULL);
+ object_property_set_description(obj, "gicversion",
+ "Set GIC version. "
+ "Valid values are 2 and 3", NULL);
}
static void virt_class_init(ObjectClass *oc, void *data)
@@ -957,7 +1049,8 @@ 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;
+ /* With gic3 full implementation (with bitops) rase the lmit to 128 */
+ mc->max_cpus = 64;
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..852efb9 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -46,6 +46,11 @@ enum {
VIRT_CPUPERIPHS,
VIRT_GIC_DIST,
VIRT_GIC_CPU,
+ VIRT_GIC_V2M,
+ VIRT_GIC_DIST_MBI = VIRT_GIC_CPU,
+ VIRT_ITS_CONTROL = VIRT_GIC_V2M,
+ VIRT_ITS_TRANSLATION,
+ VIRT_LPI,
VIRT_UART,
VIRT_MMIO,
VIRT_RTC,
@@ -54,7 +59,6 @@ enum {
VIRT_PCIE_MMIO,
VIRT_PCIE_PIO,
VIRT_PCIE_ECAM,
- VIRT_GIC_V2M,
VIRT_PLATFORM_BUS,
};
--
2.4.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3 Pavel Fedin
@ 2015-07-15 14:38 ` Diana Craciun
2015-07-15 15:32 ` Pavel Fedin
0 siblings, 1 reply; 9+ messages in thread
From: Diana Craciun @ 2015-07-15 14:38 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Eric Auger, Christoffer Dall,
Shlomo Pongratz
Hi,
On 07/14/2015 10:54 AM, Pavel Fedin wrote:
> Get/put routines are missing, live migration is not possible.
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
> hw/intc/Makefile.objs | 3 +
> hw/intc/arm_gicv3_kvm.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 195 insertions(+)
> create mode 100644 hw/intc/arm_gicv3_kvm.c
>
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 1317e5a..e2525a8 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -17,6 +17,9 @@ common-obj-$(CONFIG_OPENPIC) += openpic.o
>
> obj-$(CONFIG_APIC) += apic.o apic_common.o
> obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
> +ifeq ($(ARCH), aarch64) # Only 64-bit KVM can use these
> +obj-$(CONFIG_ARM_GIC_KVM) += arm_gicv3_kvm.o
> +endif
> 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..4bc8f25
> --- /dev/null
> +++ b/hw/intc/arm_gicv3_kvm.c
> @@ -0,0 +1,192 @@
> +/*
> + * 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/sysbus.h"
> +#include "sysemu/kvm.h"
> +#include "kvm_arm.h"
> +#include "gicv3_internal.h"
> +#include "vgic_common.h"
> +
> +#ifdef DEBUG_GICV3_KVM
> +static const int debug_gicv3_kvm = 1;
> +#else
> +static const int debug_gicv3_kvm = 0;
> +#endif
> +
> +#define DPRINTF(fmt, ...) do { \
> + if (debug_gicv3_kvm) { \
> + printf("kvm_gicv3: " fmt , ## __VA_ARGS__); \
> + } \
> + } while (0)
> +
> +#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)
> +{
> + int i;
> + GICv3State *s = KVM_ARM_GICV3(dev);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> + KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
> + Error *local_err = NULL;
> + int ret;
> +
> + DPRINTF("kvm_arm_gicv3_realize\n");
> +
> + kgc->parent_realize(dev, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + i = s->num_irq - GICV3_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 += (GICV3_INTERNAL * s->num_cpu);
Here GICV3_INTERNAL is used, but kvm_arch_gicv3_set_irq relies on
kvm_arm_gic_set_irq which is using GIC_INTERNAL, so the GICv3 related
code is using both defines.
> + qdev_init_gpio_in(dev, kvm_arm_gicv3_set_irq, i);
> + /* We never use our outbound IRQ 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_V3, false);
> + if (ret >= 0) {
> + s->dev_fd = ret;
> + } else if (ret != -ENODEV && ret != -ENOTSUP) {
> + error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
> + return;
> + }
> +
> + if (kvm_gic_supports_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
> + uint32_t numirqs = s->num_irq;
> + DPRINTF("KVM_DEV_ARM_VGIC_GRP_NR_IRQS = %u\n", numirqs);
> + 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->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> + KVM_DEV_ARM_VGIC_CTRL_INIT)) {
> + DPRINTF("KVM_DEV_ARM_VGIC_CTRL_INIT\n");
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> + KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
> + }
> +
> + /* Distributor */
> + memory_region_init_reservation(&s->iomem_dist, OBJECT(s),
> + "kvm-gicv3_dist", 0x10000);
> + sysbus_init_mmio(sbd, &s->iomem_dist);
> + kvm_arm_register_device(&s->iomem_dist, -1,
> + KVM_DEV_ARM_VGIC_GRP_ADDR,
> + KVM_VGIC_V3_ADDR_TYPE_DIST,
> + s->dev_fd);
> +
> + /* Redistributor */
> + memory_region_init_reservation(&s->iomem_lpi, OBJECT(s),
> + "kvm-gicv3_lpi", 0x800000);
> + sysbus_init_mmio(sbd, &s->iomem_lpi);
> + kvm_arm_register_device(&s->iomem_lpi, -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)
Diana
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine Pavel Fedin
@ 2015-07-15 14:44 ` Diana Craciun
0 siblings, 0 replies; 9+ messages in thread
From: Diana Craciun @ 2015-07-15 14:44 UTC (permalink / raw)
To: Pavel Fedin, qemu-devel
Cc: Peter Maydell, Shlomo Pongratz, Eric Auger, Christoffer Dall,
Shlomo Pongratz
Hi,
On 07/14/2015 10:54 AM, Pavel Fedin wrote:
> Set kernel_irqchip_type according to value of the option and pass it
> around where necessary. Instantiate devices and fdt nodes according
> to the choice.
>
> mac_cpus for virt machine increased to 64. GICv2 compatibility check
> happens inside arm_gic_common_realize().
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
> hw/arm/virt.c | 135 ++++++++++++++++++++++++++++++++++++++++++--------
> include/hw/arm/fdt.h | 2 +-
> include/hw/arm/virt.h | 6 ++-
> 3 files changed, 120 insertions(+), 23 deletions(-)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 2e7d858..df69dc8 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -48,6 +48,8 @@
> #include "hw/arm/sysbus-fdt.h"
> #include "hw/platform-bus.h"
> #include "hw/arm/fdt.h"
> +#include "linux/kvm.h" /* For KVM_DEV_TYPE_ARM_VGIC_V{2|3} */
> +#include "qapi/visitor.h"
>
> /* Number of external interrupt lines to configure the GIC with */
> #define NUM_IRQS 256
> @@ -67,6 +69,7 @@ typedef struct VirtBoardInfo {
> uint32_t clock_phandle;
> uint32_t gic_phandle;
> uint32_t v2m_phandle;
> + const char *class_name;
> } VirtBoardInfo;
>
> typedef struct {
> @@ -80,6 +83,7 @@ typedef struct {
> } VirtMachineState;
>
> #define TYPE_VIRT_MACHINE "virt"
> +#define TYPE_VIRTV3_MACHINE "virt-v3"
> #define VIRT_MACHINE(obj) \
> OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
> #define VIRT_MACHINE_GET_CLASS(obj) \
> @@ -106,7 +110,12 @@ static const MemMapEntry a15memmap[] = {
> /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
> [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
> [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
> - [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
> + [VIRT_GIC_V2M] = { 0x08020000, 0x00010000 },
> + /* On v3 VIRT_GIC_DIST_MBI and VIRT_ITS_CONTROL take place of
> + * VIRT_GIC_CPU and VIRT_GIC_V2M respectively
> + */
> + [VIRT_ITS_TRANSLATION] = { 0x08030000, 0x00010000 },
> + [VIRT_LPI] = { 0x08040000, 0x00800000 },
> [VIRT_UART] = { 0x09000000, 0x00001000 },
> [VIRT_RTC] = { 0x09010000, 0x00001000 },
> [VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
> @@ -256,10 +265,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");
>
> @@ -283,6 +295,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);
> @@ -319,25 +343,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 == KVM_DEV_TYPE_ARM_VGIC_V3) {
> + 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_LPI].base,
> + 2, vbi->memmap[VIRT_LPI].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);
> }
>
> @@ -360,20 +395,35 @@ 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 */
> DeviceState *gicdev;
> SysBusDevice *gicbusdev;
> - const char *gictype = "arm_gic";
> + const char *gictype;
> int i;
>
> - if (kvm_irqchip_in_kernel()) {
> - gictype = "kvm-arm-gic";
> + if (type == KVM_DEV_TYPE_ARM_VGIC_V3) {
> + /* TODO: Software emulation is not implemented yet */
> + if (!kvm_irqchip_in_kernel()) {
> + fprintf(stderr, "KVM is currently required for GICv3 emulation\n");
> + exit(1);
> + }
> + gictype = "kvm-arm-gicv3";
> + } else {
> + gictype = kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic";
> }
>
> gicdev = qdev_create(NULL, gictype);
> - qdev_prop_set_uint32(gicdev, "revision", 2);
> +
> + for (i = 0; i < vbi->smp_cpus; i++) {
> + CPUState *cpu = qemu_get_cpu(i);
> + CPUARMState *env = cpu->env_ptr;
> + env->nvic = gicdev;
> + }
> +
> + qdev_prop_set_uint32(gicdev, "revision",
> + type == KVM_DEV_TYPE_ARM_VGIC_V3 ? 3 : 2);
> 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 +432,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 == KVM_DEV_TYPE_ARM_VGIC_V3) {
> + sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_LPI].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
> @@ -409,9 +463,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 == KVM_DEV_TYPE_ARM_VGIC_V2) {
> + create_v2m(vbi, pic);
> + }
> }
As we do not have yet support for ITS implementation in QEMU the device
tree for a GICv3 guest will have a msi-parent property in the device
tree which will point to nothing:
"msi-parent = <0x0>"
Diana
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3
2015-07-15 14:38 ` Diana Craciun
@ 2015-07-15 15:32 ` Pavel Fedin
0 siblings, 0 replies; 9+ messages in thread
From: Pavel Fedin @ 2015-07-15 15:32 UTC (permalink / raw)
To: 'Diana Craciun', qemu-devel
Cc: 'Peter Maydell', 'Shlomo Pongratz',
'Shlomo Pongratz', 'Christoffer Dall',
'Eric Auger'
Hello!
> Here GICV3_INTERNAL is used, but kvm_arch_gicv3_set_irq relies on
> kvm_arm_gic_set_irq which is using GIC_INTERNAL, so the GICv3 related
> code is using both defines.
The change relies on these definitions being equal. Ok, i agree this is a kind of hack and will
redo this in v5.
> As we do not have yet support for ITS implementation in QEMU the device
> tree for a GICv3 guest will have a msi-parent property in the device
> tree which will point to nothing:
>
> "msi-parent = <0x0>"
Oops, thank you, i forgot about this. Will fix.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-07-15 15:32 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-14 7:54 [Qemu-devel] [PATCH v4 0/5] vGICv3 support Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 1/5] Implement GIC-500 base class Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 2/5] Extract some reusable vGIC code Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 3/5] Introduce irqchip type specification for KVM Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 4/5] Initial implementation of vGICv3 Pavel Fedin
2015-07-15 14:38 ` Diana Craciun
2015-07-15 15:32 ` Pavel Fedin
2015-07-14 7:54 ` [Qemu-devel] [PATCH v4 5/5] Add gicversion option to virt machine Pavel Fedin
2015-07-15 14:44 ` Diana Craciun
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.