All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
@ 2015-05-14 17:27 Ashok Kumar
  2015-05-15  6:42 ` Pavel Fedin
  2015-05-18 15:44 ` Eric Auger
  0 siblings, 2 replies; 11+ messages in thread
From: Ashok Kumar @ 2015-05-14 17:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Ashok Kumar

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 <ashoks@broadcom.com>
---
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

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-14 17:27 [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode Ashok Kumar
@ 2015-05-15  6:42 ` Pavel Fedin
  2015-05-19 12:50   ` Eric Auger
  2015-05-19 16:45   ` Eric Auger
  2015-05-18 15:44 ` Eric Auger
  1 sibling, 2 replies; 11+ messages in thread
From: Pavel Fedin @ 2015-05-15  6:42 UTC (permalink / raw)
  To: 'Ashok Kumar', qemu-devel; +Cc: 'Shlomo Pongratz'

 Hello!

> 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 <ashoks@broadcom.com>

 I also work on this, just not published yet. Some notes about your version:
1. May be there should be hw/intc/arm_gicv3_kvm.c file created for GICv3? As far as i can
see, save/restore code should differ a lot.
2. kvm_arch_irqchip_create() should probe only for type we want to get. It has to be
passed there somehow from the virt machine initializer. And, if we want GICv3, then upon
failure it should return error, not zero. This is because when kvm_arch_irqchip_create()
returns zero, a fallback code is used, which will create GICv2.
3. Perhaps you should base your work on these patch sets:
    https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg00941.html
    https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg01505.html

 I added Shlomo to cc because he might also be interested.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-14 17:27 [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode Ashok Kumar
  2015-05-15  6:42 ` Pavel Fedin
@ 2015-05-18 15:44 ` Eric Auger
  2015-05-19 12:52   ` Eric Auger
  1 sibling, 1 reply; 11+ messages in thread
From: Eric Auger @ 2015-05-18 15:44 UTC (permalink / raw)
  To: Ashok Kumar, qemu-devel

Hi Ashok,
On 05/14/2015 07:27 PM, Ashok Kumar wrote:
> 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 <ashoks@broadcom.com>
> ---
> Tested KVM/GICv3 in ARM fastmodel.
> Tested TCG/GICv2.
> Not tested KVM/GICv2.

I reproduced your test case on fast model too and it boots fine. I
encountered a small compilation issue related to arm_gic_init_memory
proto (needed a const char *name).

As a general comment you should run checkpatch.pl since you have qemu
style issues. Also the patch would deserve to be split into several
patch files and a cover letter would be needed I think with enriched
description. At least you could separate arm_gic_kvm additions from virt
ones, all the more so it could grow in the future...
> 
>  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;
I wonder whether it wouldn't be better located in VirtMachineState as
uint32_t and add a version uint32_t arg to fdt_add_gic_node & create_gic.

Or why not using a string property that you then convert into an enum
value. This would pave the way for GICv2m addition. This would also
remove the need for adding qapi/visitor.h I guess

>  } 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 :
when reaching 128 (is it the max?) cores may overwrite VIRT_UART base?
> +                                     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;
may be simplified if str prop and enum stored in VirtMachineState?
> +
> +    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);
default value could be documented
>  }
>  
>  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,
kvm_arm_gic_init_memory?
> +                                        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_DIST_SIZE?
 KVM_VGIC_V2_ADDR_TYPE_CPU,
> +                            0x1000,
KVM_VGIC_V2_DIST_SIZE?
 &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
Wouldn't it make sense to include that in hw/intc/arm_gic.h to reuse
that in virt.c?

Best Regards

Eric
>  #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;
> +    }
The 2d creation overwrites the 1st one at kernel level  (kvm_vgic_create
in vgic.c) so as Pavel said, we need to reconsider that part or call path.

Best Regards

Eric
> +
>      return 0;
>  }
>  
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-15  6:42 ` Pavel Fedin
@ 2015-05-19 12:50   ` Eric Auger
  2015-05-21  6:47     ` Pavel Fedin
  2015-05-19 16:45   ` Eric Auger
  1 sibling, 1 reply; 11+ messages in thread
From: Eric Auger @ 2015-05-19 12:50 UTC (permalink / raw)
  To: Pavel Fedin, 'Ashok Kumar', qemu-devel; +Cc: 'Shlomo Pongratz'

Dear all,
On 05/15/2015 08:42 AM, Pavel Fedin wrote:
>  Hello!
> 
>> 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 <ashoks@broadcom.com>
> 
>  I also work on this, just not published yet. Some notes about your version:
> 1. May be there should be hw/intc/arm_gicv3_kvm.c file created for GICv3? As far as i can
> see, save/restore code should differ a lot.
> 2. kvm_arch_irqchip_create() should probe only for type we want to get. It has to be
> passed there somehow from the virt machine initializer.
After a closer look, kvm_arch_irqchip_create is called here with test
mode = true. With that option, at kernel level, we only check the kvm
device registered its ops and do not go further (see
kvm_ioctl_create_device in kvm_main.c): typically the gic kvm_device is
not created at that stage. So if my understanding is correct, that piece
of code only should & does check either GICv2 or GICV3 was seen in the
host dt and accordingly registered. I think Ashok
kvm_arch_irqchip_create code is good here. Actual device creation is
handled in the device itself with test mode = false.

Do you share this understanding?

Best Regards

Eric
 And, if we want GICv3, then upon
> failure it should return error, not zero. This is because when kvm_arch_irqchip_create()
> returns zero, a fallback code is used, which will create GICv2.
> 3. Perhaps you should base your work on these patch sets:
>     https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg00941.html
>     https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg01505.html
> 
>  I added Shlomo to cc because he might also be interested.
> 
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
> 
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-18 15:44 ` Eric Auger
@ 2015-05-19 12:52   ` Eric Auger
  0 siblings, 0 replies; 11+ messages in thread
From: Eric Auger @ 2015-05-19 12:52 UTC (permalink / raw)
  To: Ashok Kumar, qemu-devel

On 05/18/2015 05:44 PM, Eric Auger wrote:
> Hi Ashok,
> On 05/14/2015 07:27 PM, Ashok Kumar wrote:
>> 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 <ashoks@broadcom.com>
>> ---
>> Tested KVM/GICv3 in ARM fastmodel.
>> Tested TCG/GICv2.
>> Not tested KVM/GICv2.
> 
> I reproduced your test case on fast model too and it boots fine. I
> encountered a small compilation issue related to arm_gic_init_memory
> proto (needed a const char *name).
> 
> As a general comment you should run checkpatch.pl since you have qemu
> style issues. Also the patch would deserve to be split into several
> patch files and a cover letter would be needed I think with enriched
> description. At least you could separate arm_gic_kvm additions from virt
> ones, all the more so it could grow in the future...
>>
>>  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;
> I wonder whether it wouldn't be better located in VirtMachineState as
> uint32_t and add a version uint32_t arg to fdt_add_gic_node & create_gic.
> 
> Or why not using a string property that you then convert into an enum
> value. This would pave the way for GICv2m addition. This would also
> remove the need for adding qapi/visitor.h I guess
> 
>>  } 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 :
> when reaching 128 (is it the max?) cores may overwrite VIRT_UART base?
>> +                                     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;
> may be simplified if str prop and enum stored in VirtMachineState?
>> +
>> +    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);
> default value could be documented
>>  }
>>  
>>  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,
> kvm_arm_gic_init_memory?
>> +                                        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_DIST_SIZE?
>  KVM_VGIC_V2_ADDR_TYPE_CPU,
>> +                            0x1000,
> KVM_VGIC_V2_DIST_SIZE?
>  &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
> Wouldn't it make sense to include that in hw/intc/arm_gic.h to reuse
> that in virt.c?
> 
> Best Regards
> 
> Eric
>>  #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;
>> +    }
> The 2d creation overwrites the 1st one at kernel level  (kvm_vgic_create
> in vgic.c) so as Pavel said, we need to reconsider that part or call path.
Hi Ashok,
so please ignore that last comment
Thanks
Eric
> 
> Best Regards
> 
> Eric
>> +
>>      return 0;
>>  }
>>  
>>
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-15  6:42 ` Pavel Fedin
  2015-05-19 12:50   ` Eric Auger
@ 2015-05-19 16:45   ` Eric Auger
  1 sibling, 0 replies; 11+ messages in thread
From: Eric Auger @ 2015-05-19 16:45 UTC (permalink / raw)
  To: Pavel Fedin, 'Ashok Kumar', qemu-devel; +Cc: 'Shlomo Pongratz'

On 05/15/2015 08:42 AM, Pavel Fedin wrote:
>  Hello!
> 
>> 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 <ashoks@broadcom.com>
> 
>  I also work on this, just not published yet. Some notes about your version:
> 1. May be there should be hw/intc/arm_gicv3_kvm.c file created for GICv3? As far as i can
> see, save/restore code should differ a lot.
Hi,

I agree with you Pavel, the code currently uses a GICState supporting
max 8 CPU. So looks like we should use Shlomo's version and move code in
a new arm_gicv3_kvm.c.

Best Regards

Eric
> 2. kvm_arch_irqchip_create() should probe only for type we want to get. It has to be
> passed there somehow from the virt machine initializer. And, if we want GICv3, then upon
> failure it should return error, not zero. This is because when kvm_arch_irqchip_create()
> returns zero, a fallback code is used, which will create GICv2.
> 3. Perhaps you should base your work on these patch sets:
>     https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg00941.html
>     https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg01505.html
> 
>  I added Shlomo to cc because he might also be interested.
> 
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
> 
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-19 12:50   ` Eric Auger
@ 2015-05-21  6:47     ` Pavel Fedin
  2015-05-21  8:59       ` Eric Auger
  0 siblings, 1 reply; 11+ messages in thread
From: Pavel Fedin @ 2015-05-21  6:47 UTC (permalink / raw)
  To: 'Eric Auger', 'Ashok Kumar', qemu-devel
  Cc: 'Shlomo Pongratz'

 Hello! Sorry, missed this message, catching up...

> After a closer look, kvm_arch_irqchip_create is called here with test
> mode = true. With that option, at kernel level, we only check the kvm
> device registered its ops and do not go further (see
> kvm_ioctl_create_device in kvm_main.c): typically the gic kvm_device is
> not created at that stage.

 Ah, sorry, yes. I missed KVM_CREATE_DEVICE_TEST flag.

> So if my understanding is correct, that piece
> of code only should & does check either GICv2 or GICV3 was seen in the
> host dt and accordingly registered. I think Ashok
> kvm_arch_irqchip_create code is good here.

 IMHO not really because from the beginning we want only a particular GIC type instead of
just something. And there can be a situation where we want e.g. GICv3 in our virtual
machine, but only GICv2 is supported by the KVM (because of hardware). Or vice versa, we
could ask for GICv2, but KVM could do only GICv3 (not all GICv3's have backwards
compatibility option).
 Ashok's code would become confused in this case. It will probe for anything and return
OK, while the kernel actually cannot do what we really want.
 And one more glitch. In case if we want GICv3, we should not return just false, because
in this case qemu falls back to KVM_CREATE_IRQCHIP ioctl, which does not have test mode,
and will actually instantiate GICv2. I believe this can cause problems.
 To be more clear, here is a snip from my code. I can post the whole thing as RFC patches,
but they are not quite ready yet.
--- cut ---
int kvm_arch_irqchip_create(KVMState *s, int type)
{
    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, type, true);
    if (ret == 0) {
        return 1;
    }

    /* Fallback will create VGIC v2 */
    if (type != KVM_DEV_TYPE_ARM_VGIC_V2) {
        return ret;
    }
    return 0;
}
--- cut ---
 'type' here comes from MachineState (see my last virt-v3 patch):
--- cut ---
static int kvm_irqchip_create(MachineState *machine, KVMState *s)
{
    int ret;

    if (!machine_kernel_irqchip_allowed(machine) ||
        (!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
         (kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
        return 0;
    }

    /* 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, machine->kernel_irqchip_type);
    if (ret < 0) {
        return ret;
    } else if (ret == 0) {
        ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
        if (ret < 0) {
            fprintf(stderr, "Create kernel irqchip failed\n");
            return ret;
        }
    }
--- cut ---

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-21  6:47     ` Pavel Fedin
@ 2015-05-21  8:59       ` Eric Auger
  2015-05-21 14:10         ` Pavel Fedin
  0 siblings, 1 reply; 11+ messages in thread
From: Eric Auger @ 2015-05-21  8:59 UTC (permalink / raw)
  To: Pavel Fedin, 'Ashok Kumar', qemu-devel; +Cc: 'Shlomo Pongratz'

Hi Pavel,
On 05/21/2015 08:47 AM, Pavel Fedin wrote:
>  Hello! Sorry, missed this message, catching up...
> 
>> After a closer look, kvm_arch_irqchip_create is called here with test
>> mode = true. With that option, at kernel level, we only check the kvm
>> device registered its ops and do not go further (see
>> kvm_ioctl_create_device in kvm_main.c): typically the gic kvm_device is
>> not created at that stage.
> 
>  Ah, sorry, yes. I missed KVM_CREATE_DEVICE_TEST flag.
> 
>> So if my understanding is correct, that piece
>> of code only should & does check either GICv2 or GICV3 was seen in the
>> host dt and accordingly registered. I think Ashok
>> kvm_arch_irqchip_create code is good here.
> 
>  IMHO not really because from the beginning we want only a particular GIC type instead of
> just something.

 And there can be a situation where we want e.g. GICv3 in our virtual
> machine, but only GICv2 is supported by the KVM (because of hardware).
 Or vice versa, we
> could ask for GICv2, but KVM could do only GICv3 (not all GICv3's have backwards
> compatibility option).
>  Ashok's code would become confused in this case. It will probe for anything and return
> OK, while the kernel actually cannot do what we really want.
>  And one more glitch. In case if we want GICv3, we should not return just false, because
> in this case qemu falls back to KVM_CREATE_IRQCHIP ioctl, which does not have test mode,
> and will actually instantiate GICv2.
here is my current understanding:

It is said in Linux Documentation/virtual/kvm/api.txt that the GICv3
must be instantiated through KVM_CREATE_DEVICE and not with
KVM_CREATE_IRQCHIP. If KVM_CREATE_DEVICE(GICV3,test mode=true) fails
this means either we have a recent kernel supporting KVM_CREATE_DEVICE
but we do not have GICV3 HW or we have an old kernel that does not
support KVM_CREATE_DEVICE for GICV3. In both cases we cannot instantiate
GICv3. QEMU KVM GICv3 device would also fail instantiating GICV3 through
KVM_CREATE_DEVICE (non test mode) and prevent the VM from starting.

So to me it is sensible to instantiate GICV2 through legacy
KVM_CREATE_IRQCHIP API if both KVM_CREATE_DEVICE(test mode=true) failed.

To me kvm_arch_irqchip_create code only is meant to handle the case  new
KVM_CREATE_DEVICE is NOT supported. In that case only the GICv2 is
instantiable through the legacy API.

In all other cases, the instantiation should be handled in the very QEMU
vGIC device through KVM_CREATE_DEVICE. There you can use test mode to
know whether the device supports V2 compat mode since
KVM_CREATE_DEVICE(GICV2,test mode=true) should succeed. So to me we have
ways to discriminate all combinations without kernel addition but I
would rather put that code in the QEMU GIC device instead of
kvm_arch_irqchip_create.

Let me know what you think. Ashok, any opinion?

Best Regards

Eric

 I believe this can cause problems.
>  To be more clear, here is a snip from my code. I can post the whole thing as RFC patches,
> but they are not quite ready yet.
> --- cut ---
> int kvm_arch_irqchip_create(KVMState *s, int type)
> {
>     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, type, true);
>     if (ret == 0) {
>         return 1;
>     }
> 
>     /* Fallback will create VGIC v2 */
>     if (type != KVM_DEV_TYPE_ARM_VGIC_V2) {
>         return ret;
>     }
>     return 0;
> }
> --- cut ---
>  'type' here comes from MachineState (see my last virt-v3 patch):
> --- cut ---
> static int kvm_irqchip_create(MachineState *machine, KVMState *s)
> {
>     int ret;
> 
>     if (!machine_kernel_irqchip_allowed(machine) ||
>         (!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
>          (kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
>         return 0;
>     }
> 
>     /* 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, machine->kernel_irqchip_type);
>     if (ret < 0) {
>         return ret;
>     } else if (ret == 0) {
>         ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
>         if (ret < 0) {
>             fprintf(stderr, "Create kernel irqchip failed\n");
>             return ret;
>         }
>     }
> --- cut ---
> 
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-21  8:59       ` Eric Auger
@ 2015-05-21 14:10         ` Pavel Fedin
  2015-05-21 14:24           ` Eric Auger
  0 siblings, 1 reply; 11+ messages in thread
From: Pavel Fedin @ 2015-05-21 14:10 UTC (permalink / raw)
  To: 'Eric Auger', 'Ashok Kumar', qemu-devel
  Cc: 'Shlomo Pongratz'

 Hello!

> So to me it is sensible to instantiate GICV2 through legacy
> KVM_CREATE_IRQCHIP API if both KVM_CREATE_DEVICE(test mode=true) failed.

 I disagree because at this point we already know which GIC version the user wants. This
is because kvm_irqchip_create() is called after machine instance is created (and
virt_instance_init() has been called). At this point we already know all the options. At
this point i think the scenario should be:
 a) If we want GICv3 - test for KVM_CREATE_DEVICE(GICv3) and fail if we don't have one.
 b) If we want GICv2 - test for KVM_CREATE_DEVICE(GICv2). If it fails, try
KVM_CREATE_IRQCHIP.
 IMHO there is little sense to fall back from v3 to v2 or vice versa because other
important parameters (like number of CPUs) depend on it.
 Implementing this behavior costs only one more integer in MachineState structure. Is it
too large ? If you want, i can post my patches as RFC, i think now they are more or less
OK.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
  2015-05-21 14:10         ` Pavel Fedin
@ 2015-05-21 14:24           ` Eric Auger
  0 siblings, 0 replies; 11+ messages in thread
From: Eric Auger @ 2015-05-21 14:24 UTC (permalink / raw)
  To: Pavel Fedin, 'Ashok Kumar', qemu-devel; +Cc: 'Shlomo Pongratz'

On 05/21/2015 04:10 PM, Pavel Fedin wrote:
>  Hello!
> 
>> So to me it is sensible to instantiate GICV2 through legacy
>> KVM_CREATE_IRQCHIP API if both KVM_CREATE_DEVICE(test mode=true) failed.
> 
>  I disagree because at this point we already know which GIC version the user wants. This
> is because kvm_irqchip_create() is called after machine instance is created (and
> virt_instance_init() has been called). At this point we already know all the options. At
> this point i think the scenario should be:
>  a) If we want GICv3 - test for KVM_CREATE_DEVICE(GICv3) and fail if we don't have one.
>  b) If we want GICv2 - test for KVM_CREATE_DEVICE(GICv2). If it fails, try
> KVM_CREATE_IRQCHIP.
>  IMHO there is little sense to fall back from v3 to v2 or vice versa because other
> important parameters (like number of CPUs) depend on it.
>  Implementing this behavior costs only one more integer in MachineState structure. Is it
> too large ? If you want, i can post my patches as RFC, i think now they are more or less
> OK.

Hi Pavel,

yes sure please post your RFC and let's wait for other reviewer
feedback. I just shared my understanding ;-)

Best Regards

Eric
> 
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode
@ 2015-05-14 20:13 Ashok Kumar
  0 siblings, 0 replies; 11+ messages in thread
From: Ashok Kumar @ 2015-05-14 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Ashok Kumar

Added -M virt,gicversion=2,3 property to configure GICv2 or GICv3.
GICv3 save/restore is not supported as linux kernel's vgic-v3-emul.c
is yet to support them.

Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
---
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

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-05-21 14:24 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-14 17:27 [Qemu-devel] [RFC PATCH] hw/arm/virt: Added preliminary GICv3 support for kvm mode Ashok Kumar
2015-05-15  6:42 ` Pavel Fedin
2015-05-19 12:50   ` Eric Auger
2015-05-21  6:47     ` Pavel Fedin
2015-05-21  8:59       ` Eric Auger
2015-05-21 14:10         ` Pavel Fedin
2015-05-21 14:24           ` Eric Auger
2015-05-19 16:45   ` Eric Auger
2015-05-18 15:44 ` Eric Auger
2015-05-19 12:52   ` Eric Auger
2015-05-14 20:13 Ashok Kumar

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.