diff mbox

[v4,5/5] Add gicversion option to virt machine

Message ID 0c1f9bfc5a989591cffd59fd6b219cc09ac0b42b.1436859955.git.p.fedin@samsung.com
State New
Headers show

Commit Message

Pavel Fedin July 14, 2015, 7:54 a.m. UTC
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(-)

Comments

Diana Craciun July 15, 2015, 2:44 p.m. UTC | #1
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
diff mbox

Patch

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,
 };