[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support fo
From: |
Ashok Kumar |
Subject: |
[Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode |
Date: |
Thu, 14 May 2015 10:27:10 -0700 |
Added -M virt,gicversion=2,3 property to configure GICv2 or GICv3.
GICv3 save/restore is not supported as vgic-v3-emul.c is yet to support
them.
Signed-off-by: Ashok Kumar <address@hidden>
---
Tested KVM/GICv3 in ARM fastmodel.
Tested TCG/GICv2.
Not tested KVM/GICv2.
hw/arm/virt.c | 56 ++++++++++++++++++++++++++++++---
hw/intc/arm_gic_kvm.c | 68 ++++++++++++++++++++++++++--------------
hw/intc/gic_internal.h | 7 +++++
include/hw/intc/arm_gic_common.h | 5 ++-
target-arm/kvm.c | 5 +++
5 files changed, 111 insertions(+), 30 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 565f573..bb22d61 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -43,6 +43,7 @@
#include "qemu/bitops.h"
#include "qemu/error-report.h"
#include "hw/pci-host/gpex.h"
+#include "qapi/visitor.h"
#define NUM_VIRTIO_TRANSPORTS 32
@@ -87,6 +88,7 @@ typedef struct VirtBoardInfo {
void *fdt;
int fdt_size;
uint32_t clock_phandle;
+ int gic_version;
} VirtBoardInfo;
typedef struct {
@@ -330,16 +332,22 @@ static uint32_t fdt_add_gic_node(const VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", 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");
+ if (vbi->gic_version == 3)
+ qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+ "arm,gic-v3");
+ else
+ /* '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);
+ 2, vbi->gic_version == 3 ?
+ vbi->smp_cpus * 0x20000 :
+ vbi->memmap[VIRT_GIC_CPU].size);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
return gic_phandle;
@@ -356,9 +364,13 @@ static uint32_t create_gic(const VirtBoardInfo *vbi,
qemu_irq *pic)
if (kvm_irqchip_in_kernel()) {
gictype = "kvm-arm-gic";
}
+ else if (vbi->gic_version == 3) {
+ fprintf (stderr, "GICv3 is not yet supported in tcg mode\n");
+ exit (1);
+ }
gicdev = qdev_create(NULL, gictype);
- qdev_prop_set_uint32(gicdev, "revision", 2);
+ qdev_prop_set_uint32(gicdev, "revision", vbi->gic_version);
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).
@@ -853,6 +865,35 @@ 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)
+{
+ int64_t value = machines[0].gic_version;
+
+ visit_type_int(v, &value, name, errp);
+
+ return;
+}
+
+static void virt_set_gic_version(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ int64_t value;
+ int i;
+
+ visit_type_int(v, &value, name, errp);
+
+ if (value > 3 || value < 2) {
+ error_report ("Only GICv2 and GICv3 supported currently\n");
+ exit(1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(machines); i++)
+ machines[i].gic_version = value;
+
+ return;
+}
+
static void virt_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -865,6 +906,11 @@ static void virt_instance_init(Object *obj)
"Set on/off to enable/disable the ARM "
"Security Extensions (TrustZone)",
NULL);
+ 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)
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index e1952ad..0027dca 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -89,7 +89,8 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int
level)
static bool kvm_arm_gic_can_save_restore(GICState *s)
{
- return s->dev_fd >= 0;
+ /* GICv3 doesn't support save restore yet */
+ return s->dev_fd >= 0 && s->revision != REV_GICV3;
}
static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
@@ -529,6 +530,28 @@ static void kvm_arm_gic_reset(DeviceState *dev)
kvm_arm_gic_put(s);
}
+static void arm_gic_init_memory (GICState *s, SysBusDevice *sbd,
+ uint32_t gicver, uint32_t dist_t,
+ uint32_t distsz, uint32_t mem_t,
+ uint32_t memsz, MemoryRegion *mem,
+ char *name)
+{
+ /* Distributor */
+ memory_region_init_reservation(&s->iomem, OBJECT(s),
+ "kvm-gic_dist", distsz);
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ kvm_arm_register_device(&s->iomem, (gicver << KVM_ARM_DEVICE_ID_SHIFT) |
dist_t,
+ KVM_DEV_ARM_VGIC_GRP_ADDR, dist_t, s->dev_fd);
+
+ /* GICv2 - GICV cpu register interface region
+ * GICv3 - Redistributor register interface region */
+ memory_region_init_reservation(mem, OBJECT(s),
+ name, memsz);
+ sysbus_init_mmio(sbd, mem);
+ kvm_arm_register_device(mem, (gicver << KVM_ARM_DEVICE_ID_SHIFT) | mem_t,
+ KVM_DEV_ARM_VGIC_GRP_ADDR, mem_t, s->dev_fd);
+}
static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
{
int i;
@@ -563,7 +586,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error
**errp)
/* Try to create the device via the device control API */
s->dev_fd = -1;
- ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
+ if (s->revision == REV_GICV3)
+ ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
+ else
+ ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
if (ret >= 0) {
s->dev_fd = ret;
} else if (ret != -ENODEV && ret != -ENOTSUP) {
@@ -583,29 +609,23 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error
**errp)
KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
}
- /* Distributor */
- memory_region_init_reservation(&s->iomem, OBJECT(s),
- "kvm-gic_dist", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
- kvm_arm_register_device(&s->iomem,
- (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
- | KVM_VGIC_V2_ADDR_TYPE_DIST,
- KVM_DEV_ARM_VGIC_GRP_ADDR,
+ if (s->revision == REV_GICV3)
+ arm_gic_init_memory(s, sbd, KVM_ARM_DEVICE_VGIC_V3,
+ KVM_VGIC_V3_ADDR_TYPE_DIST,
+ KVM_VGIC_V3_DIST_SIZE,
+ KVM_VGIC_V3_ADDR_TYPE_REDIST,
+ KVM_VGIC_V3_REDIST_SIZE,
+ &s->rdistiomem[0], "kvm-gic_rdist");
+ else
+ /* CPU interface for current core. Unlike arm_gic, we don't
+ * provide the "interface for core #N" memory regions, because
+ * cores with a VGIC don't have those.
+ */
+ arm_gic_init_memory(s, sbd, KVM_ARM_DEVICE_VGIC_V2,
KVM_VGIC_V2_ADDR_TYPE_DIST,
- s->dev_fd);
- /* CPU interface for current core. Unlike arm_gic, we don't
- * provide the "interface for core #N" memory regions, because
- * cores with a VGIC don't have those.
- */
- memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s),
- "kvm-gic_cpu", 0x1000);
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
- kvm_arm_register_device(&s->cpuiomem[0],
- (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
- | KVM_VGIC_V2_ADDR_TYPE_CPU,
- KVM_DEV_ARM_VGIC_GRP_ADDR,
- KVM_VGIC_V2_ADDR_TYPE_CPU,
- s->dev_fd);
+ 0x1000, KVM_VGIC_V2_ADDR_TYPE_CPU,
+ 0x1000, &s->cpuiomem[0],
+ "kvm-gic_cpu");
}
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index e87ef36..9f9246b 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -53,8 +53,15 @@
/* The special cases for the revision property: */
#define REV_11MPCORE 0
+#define REV_GICV2 2
+#define REV_GICV3 3
#define REV_NVIC 0xffffffff
+/* Not defined in kernel. Hence defining it here
+ * until it is done in kernel */
+#define KVM_ARM_DEVICE_VGIC_V3 1
+
+#define SZ_64K 0x10000
void gic_set_pending_private(GICState *s, int cpu, int irq);
uint32_t gic_acknowledge_irq(GICState *s, int cpu);
void gic_complete_irq(GICState *s, int cpu, int irq);
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index f6887ed..d9be6ad 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -101,7 +101,10 @@ typedef struct GICState {
* both this GIC and which CPU interface we should be accessing.
*/
struct GICState *backref[GIC_NCPU];
- MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
+ union {
+ MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
+ MemoryRegion rdistiomem[GIC_NCPU + 1]; /* CPU interfaces */
+ };
uint32_t num_irq;
uint32_t revision;
int dev_fd; /* kvm device fd if backed by kvm vgic support */
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index fdd9ba3..ce94f70 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -590,6 +590,11 @@ int kvm_arch_irqchip_create(KVMState *s)
return 1;
}
+ ret = kvm_create_device(s, KVM_DEV_TYPE_ARM_VGIC_V3, true);
+ if (ret == 0) {
+ return 1;
+ }
+
return 0;
}
--
2.1.0
- [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode,
Ashok Kumar <=
Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode, Eric Auger, 2015/05/19
Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode, Eric Auger, 2015/05/18