diff mbox

[v7,2/6] Implement GIC-500 base class

Message ID 1694c9da0a9d58f9d84e65665a00657682dc15b5.1437731107.git.p.fedin@samsung.com
State New
Headers show

Commit Message

Pavel Fedin July 24, 2015, 9:55 a.m. UTC
From: Shlomo Pongratz <shlomo.pongratz@huawei.com>

This class is to be used by both software and KVM implementations of GICv3

Signed-off-by: Shlomo Pongratz <shlomo.pongratz@huawei.com>
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
 hw/intc/Makefile.objs              |   1 +
 hw/intc/arm_gicv3_common.c         | 249 +++++++++++++++++++++++++++++++++++++
 hw/intc/gicv3_internal.h           | 156 +++++++++++++++++++++++
 include/hw/intc/arm_gicv3_common.h | 112 +++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 hw/intc/arm_gicv3_common.c
 create mode 100644 hw/intc/gicv3_internal.h
 create mode 100644 include/hw/intc/arm_gicv3_common.h

Comments

Peter Maydell July 24, 2015, 4:37 p.m. UTC | #1
On 24 July 2015 at 10:55, Pavel Fedin <p.fedin@samsung.com> wrote:
> From: Shlomo Pongratz <shlomo.pongratz@huawei.com>
>
> This class is to be used by both software and KVM implementations of GICv3
>

> +++ b/include/hw/intc/arm_gicv3_common.h
> @@ -0,0 +1,112 @@
> +/*
> + * ARM GIC support
> + *
> + * Copyright (c) 2012 Linaro Limited
> + * Copyright (c) 2015 Huawei.
> + * Written by Peter Maydell
> + * Extended to 64 cores by Shlomo Pongratz
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef HW_ARM_GICV3_COMMON_H
> +#define HW_ARM_GICV3_COMMON_H
> +
> +#include "hw/sysbus.h"
> +#include "hw/intc/arm_gic_common.h"
> +
> +/* Maximum number of possible interrupts, determined by the GIC architecture */
> +#define GICV3_MAXIRQ 1020

So how do LPIs work? They have IDs above 1023.

> +#define GICV3_NCPU 64

Where does '64' come from as a maximum limit?

> +
> +typedef struct gicv3_irq_state {
> +    /* The enable bits are only banked for per-cpu interrupts.  */
> +    uint64_t enabled;
> +    uint64_t pending;
> +    uint64_t active;
> +    uint64_t level;
> +    uint64_t group;

Why are these uint64_t ?

> +    bool edge_trigger; /* true: edge-triggered, false: level-triggered  */
> +} gicv3_irq_state;
> +
> +typedef struct gicv3_sgi_state {
> +    uint64_t pending[GICV3_NCPU];
> +} gicv3_sgi_state;
> +
> +typedef struct GICv3State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    qemu_irq parent_irq[GICV3_NCPU];
> +    qemu_irq parent_fiq[GICV3_NCPU];
> +    /* GICD_CTLR; for a GIC with the security extensions the NS banked version
> +     * of this register is just an alias of bit 1 of the S banked version.
> +     */
> +    uint32_t ctlr;
> +    /* Sim GICC_CTLR; again, the NS banked version is just aliases of bits of
> +     * the S banked register, so our state only needs to store the S version.
> +     */

"Sim" ?

> +    uint32_t cpu_ctlr[GICV3_NCPU];
> +    bool cpu_enabled[GICV3_NCPU];
> +
> +    gicv3_irq_state irq_state[GICV3_MAXIRQ];
> +    uint64_t irq_target[GICV3_MAXIRQ];
> +    uint8_t priority1[GIC_INTERNAL][GICV3_NCPU];
> +    uint8_t priority2[GICV3_MAXIRQ - GIC_INTERNAL];
> +    uint16_t last_active[GICV3_MAXIRQ][GICV3_NCPU];
> +    /* For each SGI on the target CPU, we store 64 bits
> +     * indicating which source CPUs have made this SGI
> +     * pending on the target CPU. These correspond to
> +     * the bytes in the GIC_SPENDSGIR* registers as
> +     * read by the target CPU.

This comment doesn't make any sense. You can't fit
64 bits into a byte, and GIC_SPENDSGIR<n> only hold
8 set-pending bits per SGI.

> +     */
> +    gicv3_sgi_state sgi_state[GIC_NR_SGIS];
> +
> +    uint16_t priority_mask[GICV3_NCPU];
> +    uint16_t running_irq[GICV3_NCPU];
> +    uint16_t running_priority[GICV3_NCPU];
> +    uint16_t current_pending[GICV3_NCPU];
> +
> +    uint32_t cpu_mask; /* For redistributor */
> +    uint32_t num_cpu;
> +    MemoryRegion iomem_dist; /* Distributor */
> +    MemoryRegion iomem_lpi; /* Redistributor */
> +    uint32_t num_irq;
> +    uint32_t revision;
> +    bool security_levels;
> +    int dev_fd; /* kvm device fd if backed by kvm vgic support */
> +} GICv3State;

This whole struct reads like "we just took the GICv2 state
and changed it as little as possible beyond bumping the
NCPU define a bit". That doesn't make me very confident
that it's actually correct for GICv3...

thanks
-- PMM
Pavel Fedin July 26, 2015, 1:52 p.m. UTC | #2
Hello!

> So how do LPIs work? They have IDs above 1023.

 Currently we don't have LPIs. Shlomo's SW emulation did not include them.

> > +#define GICV3_NCPU 64
> 
> Where does '64' come from as a maximum limit?

 We don't use Aff2 field as far as i know. It's Shlomo's limitation, not my one.

> This whole struct reads like "we just took the GICv2 state
> and changed it as little as possible beyond bumping the
> NCPU define a bit". That doesn't make me very confident
> that it's actually correct for GICv3...

 At least, with complete Shlomo's SW emulation code, it works.
 And could you be not so strict on this file? It's actually Shlomo's work, not my one, i include it only because i need to base on something. He will fix up the rest of SW emulation stuff.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
Pavel Fedin July 26, 2015, 2:03 p.m. UTC | #3
Hello!

> > +
> > +typedef struct gicv3_irq_state {
> > +    /* The enable bits are only banked for per-cpu interrupts.  */
> > +    uint64_t enabled;
> > +    uint64_t pending;
> > +    uint64_t active;
> > +    uint64_t level;
> > +    uint64_t group;
> 
> Why are these uint64_t ?

 I studied the code for a little bit more. These are bitmasks, where bit represents a CPU. Take a look at gicv3_internal.h, GIC_SET/CLEAR/TEST_xxx macros. 'cm' stands for 'cpu mask'.
 This is currently not used by my code, this is mainly for Shlomo's SW emulation. However, there is some usage in common class initialization code.

 And i will fix up all badly understood comments.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
Shlomo Pongratz July 26, 2015, 2:45 p.m. UTC | #4
Hi,

See inline.

On Friday, July 24, 2015, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 24 July 2015 at 10:55, Pavel Fedin <p.fedin@samsung.com <javascript:;>>
> wrote:
> > From: Shlomo Pongratz <shlomo.pongratz@huawei.com <javascript:;>>
> >
> > This class is to be used by both software and KVM implementations of
> GICv3
> >
>
> > +++ b/include/hw/intc/arm_gicv3_common.h
> > @@ -0,0 +1,112 @@
> > +/*
> > + * ARM GIC support
> > + *
> > + * Copyright (c) 2012 Linaro Limited
> > + * Copyright (c) 2015 Huawei.
> > + * Written by Peter Maydell
> > + * Extended to 64 cores by Shlomo Pongratz
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation, either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> along
> > + * with this program; if not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#ifndef HW_ARM_GICV3_COMMON_H
> > +#define HW_ARM_GICV3_COMMON_H
> > +
> > +#include "hw/sysbus.h"
> > +#include "hw/intc/arm_gic_common.h"
> > +
> > +/* Maximum number of possible interrupts, determined by the GIC
> architecture */
> > +#define GICV3_MAXIRQ 1020
>
> So how do LPIs work? They have IDs above 1023.
>

Currently I don't use LPI as the virt virtual machine doesn't use it. There
is no point to write something I can't test.

>
> > +#define GICV3_NCPU 64
>
> Where does '64' come from as a maximum limit?
>
The goal is 128 (the GIC500 limitation) but since the largest builtin is
uint64_t this will require the usage of bitfiled library. Therefore I
thought it should be delayed to future version after the logic part is
debugged.

>
> > +
> > +typedef struct gicv3_irq_state {
> > +    /* The enable bits are only banked for per-cpu interrupts.  */
> > +    uint64_t enabled;
> > +    uint64_t pending;
> > +    uint64_t active;
> > +    uint64_t level;
> > +    uint64_t group;
>
> Why are these uint64_t ?
>

These are bitfields. which were enlarged from 8 (old limit) to 64 (new
limit)

>
> > +    bool edge_trigger; /* true: edge-triggered, false: level-triggered
> */
> > +} gicv3_irq_state;
> > +
> > +typedef struct gicv3_sgi_state {
> > +    uint64_t pending[GICV3_NCPU];
> > +} gicv3_sgi_state;
> > +
> > +typedef struct GICv3State {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +    /*< public >*/
> > +
> > +    qemu_irq parent_irq[GICV3_NCPU];
> > +    qemu_irq parent_fiq[GICV3_NCPU];
> > +    /* GICD_CTLR; for a GIC with the security extensions the NS banked
> version
> > +     * of this register is just an alias of bit 1 of the S banked
> version.
> > +     */
> > +    uint32_t ctlr;
> > +    /* Sim GICC_CTLR; again, the NS banked version is just aliases of
> bits of
> > +     * the S banked register, so our state only needs to store the S
> version.
> > +     */
>
> "Sim" ?
>

Should be simulate as I only support system registers and not memory mapped
registers, but keeping this variable makes the code more close to GICv2
code.

>
> > +    uint32_t cpu_ctlr[GICV3_NCPU];
> > +    bool cpu_enabled[GICV3_NCPU];
> > +
> > +    gicv3_irq_state irq_state[GICV3_MAXIRQ];
> > +    uint64_t irq_target[GICV3_MAXIRQ];
> > +    uint8_t priority1[GIC_INTERNAL][GICV3_NCPU];
> > +    uint8_t priority2[GICV3_MAXIRQ - GIC_INTERNAL];
> > +    uint16_t last_active[GICV3_MAXIRQ][GICV3_NCPU];
> > +    /* For each SGI on the target CPU, we store 64 bits
> > +     * indicating which source CPUs have made this SGI
> > +     * pending on the target CPU. These correspond to
> > +     * the bytes in the GIC_SPENDSGIR* registers as
> > +     * read by the target CPU.
>
> This comment doesn't make any sense. You can't fit
> 64 bits into a byte, and GIC_SPENDSGIR<n> only hold
> 8 set-pending bits per SGI.
>
Correct, the comment is wrong and should be removed as spi_mending was
replaced by a structure.
The usage of a structure and not by a uint64_t vector is because there is
no serialization macro for it.

>
> > +     */
> > +    gicv3_sgi_state sgi_state[GIC_NR_SGIS];
> > +
> > +    uint16_t priority_mask[GICV3_NCPU];u
> > +    uint16_t running_irq[GICV3_NCPU];
> > +    uint16_t running_priority[GICV3_NCPU];
> > +    uint16_t current_pending[GICV3_NCPU];
> > +
> > +    uint32_t cpu_mask; /* For redistributor */
> > +    uint32_t num_cpu;
> > +    MemoryRegion iomem_dist; /* Distributor */
> > +    MemoryRegion iomem_lpi; /* Redistributor */
> > +    uint32_t num_irq;
> > +    uint32_t revision;
> > +    bool security_levels;
> > +    int dev_fd; /* kvm device fd if backed by kvm vgic support */
> > +} GICv3State;
>
> This whole struct reads like "we just took the GICv2 state
> and changed it as little as possible beyond bumping the
> NCPU define a bit". That doesn't make me very confident
> that it's actually correct for GICv3...
>
I admit that the intention of the first is to make as little changes a
possible and yet to be able to boot 64 Linux kernel (which was achieved).
Note that the kernel identified and used the GICv3 driver.

>
> thanks
> -- PMM
>
Peter Maydell July 26, 2015, 7:10 p.m. UTC | #5
On 26 July 2015 at 14:52, Pavel Fedin <p.fedin@samsung.com> wrote:

>> This whole struct reads like "we just took the GICv2 state
>> and changed it as little as possible beyond bumping the
>> NCPU define a bit". That doesn't make me very confident
>> that it's actually correct for GICv3...
>
>  At least, with complete Shlomo's SW emulation code, it works.
>  And could you be not so strict on this file? It's actually Shlomo's
> work, not my one, i include it only because i need to base on
> something. He will fix up the rest of SW emulation stuff.

Data structures are important -- they're the foundation on
which everything else rests (and at some point they get
baked into VM migration formats, though we aren't at that
point yet). It's worth getting them right from the start.

thanks
-- PMM
Peter Maydell July 31, 2015, 3:38 p.m. UTC | #6
On 26 July 2015 at 14:52, Pavel Fedin <p.fedin@samsung.com> wrote:
>  And could you be not so strict on this file?

OK, so having thought about this this week, this is what I
suggest.

For this patch series we should retain this class hierarchy,
but remove all the fields corresponding to state information
which isn't used by the KVM subclass (and all the accessor
macro definitions, and that GICV3_NCPU definition, and so on).
We should have a migration information struct which says
"not migratable".

That gives us the right structure into which we can
add the correct state fields when we get the design
right (and for whichever of emulation and KVM state
save/load gets there first).

We do need to make sure we get right:
 * the class hierarchy
 * the API to the rest of QEMU (meaning of GPIO pins,
   memory regions, any qdev/qom properties)

(and in the other parts of the patchset, also that we get
the right memory map for the virt board with the GICv3
in it and that the mechanism for selecting GICv2 or GICv3
or "whatever you've got" is good.)

thanks
-- PMM
Pavel Fedin Aug. 3, 2015, 12:18 p.m. UTC | #7
Hello!

> For this patch series we should retain this class hierarchy,
> but remove all the fields corresponding to state information
> which isn't used by the KVM subclass (and all the accessor
> macro definitions, and that GICV3_NCPU definition, and so on).
> We should have a migration information struct which says
> "not migratable".

 Ok. I am wating for my GICv2 refactor review which includes memory API change.

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

Patch

diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 092d8a8..1317e5a 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -12,6 +12,7 @@  common-obj-$(CONFIG_IOAPIC) += ioapic_common.o
 common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
 common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
 common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o
+common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o
 common-obj-$(CONFIG_OPENPIC) += openpic.o
 
 obj-$(CONFIG_APIC) += apic.o apic_common.o
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
new file mode 100644
index 0000000..5a10784
--- /dev/null
+++ b/hw/intc/arm_gicv3_common.c
@@ -0,0 +1,249 @@ 
+/*
+ * ARM GICv3 support - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gicv3_internal.h"
+
+static void gicv3_pre_save(void *opaque)
+{
+    GICv3State *s = (GICv3State *)opaque;
+    ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+    if (c->pre_save) {
+        c->pre_save(s);
+    }
+}
+
+static int gicv3_post_load(void *opaque, int version_id)
+{
+    GICv3State *s = (GICv3State *)opaque;
+    ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+    if (c->post_load) {
+        c->post_load(s);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_gicv3_irq_state = {
+    .name = "arm_gicv3_irq_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(pending, gicv3_irq_state),
+        VMSTATE_UINT64(active, gicv3_irq_state),
+        VMSTATE_UINT64(level, gicv3_irq_state),
+        VMSTATE_UINT64(group, gicv3_irq_state),
+        VMSTATE_BOOL(edge_trigger, gicv3_irq_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_gicv3_sgi_state = {
+    .name = "arm_gicv3_sgi_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(pending, gicv3_sgi_state, GICV3_NCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_gicv3 = {
+    .name = "arm_gicv3",
+    .version_id = 7,
+    .minimum_version_id = 7,
+    .pre_save = gicv3_pre_save,
+    .post_load = gicv3_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ctlr, GICv3State),
+        VMSTATE_UINT32_ARRAY(cpu_ctlr, GICv3State, GICV3_NCPU),
+        VMSTATE_STRUCT_ARRAY(irq_state, GICv3State, GICV3_MAXIRQ, 1,
+                             vmstate_gicv3_irq_state, gicv3_irq_state),
+        VMSTATE_UINT64_ARRAY(irq_target, GICv3State, GICV3_MAXIRQ),
+        VMSTATE_UINT8_2DARRAY(priority1, GICv3State, GIC_INTERNAL,
+                              GICV3_NCPU),
+        VMSTATE_UINT8_ARRAY(priority2, GICv3State,
+                            GICV3_MAXIRQ - GIC_INTERNAL),
+        VMSTATE_UINT16_2DARRAY(last_active, GICv3State, GICV3_MAXIRQ,
+                               GICV3_NCPU),
+        VMSTATE_STRUCT_ARRAY(sgi_state, GICv3State, GIC_NR_SGIS, 1,
+                             vmstate_gicv3_sgi_state, gicv3_sgi_state),
+        VMSTATE_UINT16_ARRAY(priority_mask, GICv3State, GICV3_NCPU),
+        VMSTATE_UINT16_ARRAY(running_irq, GICv3State, GICV3_NCPU),
+        VMSTATE_UINT16_ARRAY(running_priority, GICv3State, GICV3_NCPU),
+        VMSTATE_UINT16_ARRAY(current_pending, GICv3State, GICV3_NCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+                              const MemoryRegionOps *ops)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+    int i;
+
+    /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+     * GPIO array layout is thus:
+     *  [0..N-1] spi
+     *  [N..N+31] PPIs for CPU 0
+     *  [N+32..N+63] PPIs for CPU 1
+     *   ...
+     */
+    i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu;
+    qdev_init_gpio_in(DEVICE(s), handler, i);
+
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_irq[i]);
+    }
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_fiq[i]);
+    }
+
+    memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
+                          "gicv3_dist", 0x10000);
+    memory_region_init_io(&s->iomem_lpi, OBJECT(s), ops ? &ops[1] : NULL, s,
+                          "gicv3_redist", 0x800000);
+
+    sysbus_init_mmio(sbd, &s->iomem_dist);
+    sysbus_init_mmio(sbd, &s->iomem_lpi);
+}
+
+static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
+{
+    GICv3State *s = ARM_GICV3_COMMON(dev);
+    int num_irq = s->num_irq;
+
+    if (s->num_cpu > GICV3_NCPU) {
+        error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
+                   s->num_cpu, GICV3_NCPU);
+        return;
+    }
+    s->num_irq += GICV3_BASE_IRQ;
+    if (s->num_irq > GICV3_MAXIRQ) {
+        error_setg(errp,
+                   "requested %u interrupt lines exceeds GIC maximum %d",
+                   num_irq, GICV3_MAXIRQ);
+        return;
+    }
+    /* ITLinesNumber is represented as (N / 32) - 1 (see
+     * gic_dist_readb) so this is an implementation imposed
+     * restriction, not an architectural one:
+     */
+    if (s->num_irq < 32 || (s->num_irq % 32)) {
+        error_setg(errp,
+                   "%d interrupt lines unsupported: not divisible by 32",
+                   num_irq);
+        return;
+    }
+}
+
+static void arm_gicv3_common_reset(DeviceState *dev)
+{
+    GICv3State *s = ARM_GICV3_COMMON(dev);
+    int i;
+
+    /* Note num_cpu and num_irq are properties */
+
+    /* Don't reset anything assigned in arm_gic_realize or any property */
+
+    /* No GICv2 backwards computability support */
+    for (i = 0; i < s->num_cpu; i++) {
+        s->priority_mask[i] = 0;
+        s->current_pending[i] = 1023;
+        s->running_irq[i] = 1023;
+        s->running_priority[i] = 0x100;
+        s->cpu_ctlr[i] = 0;
+    }
+
+    memset(s->irq_state, 0, sizeof(s->irq_state));
+    /* GIC-500 comment 'j' SGI are always enabled */
+    for (i = 0; i < GIC_NR_SGIS; i++) {
+        GIC_SET_ENABLED(i, ALL_CPU_MASK);
+        GIC_SET_EDGE_TRIGGER(i);
+    }
+    memset(s->sgi_state, 0, sizeof(s->sgi_state));
+    memset(s->irq_target, 0, sizeof(s->irq_target));
+    if (s->num_cpu == 1) {
+        /* For uniprocessor GICs all interrupts always target the sole CPU */
+        for (i = 0; i < GICV3_MAXIRQ; i++) {
+            s->irq_target[i] = 1;
+        }
+    }
+    memset(s->priority1, 0, sizeof(s->priority1));
+    memset(s->priority2, 0, sizeof(s->priority2));
+    memset(s->last_active, 0, sizeof(s->last_active));
+
+    /* With all configuration we don't support GICv2 backwards computability */
+    if (s->security_levels > 1) {
+        /* GICv3 5.3.20 With two security So DS is RAZ/WI ARE_NS is RAO/WI
+         * and ARE_S is RAO/WI
+         */
+         s->ctlr = GICD_CTLR_ARE_S | GICD_CTLR_ARE_NS;
+    } else {
+        /* GICv3 5.3.20 With one security So DS is RAO/WI ARE is RAO/WI
+         */
+        s->ctlr = GICD_CTLR_DS | GICD_CTLR_ARE;
+    }
+    /* Workaround!
+     * Linux (drivers/irqchip/irq-gic-v3.c) is enabling only group one,
+     * in gic_cpu_sys_reg_init it calls gic_write_grpen1(1);
+     * but it doesn't conigure any interrupt to be in group one
+     */
+    for (i = 0; i < s->num_irq; i++) {
+        GIC_SET_GROUP(i, ALL_CPU_MASK);
+    }
+}
+
+static Property arm_gicv3_common_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
+    DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
+    DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+    /* How many security levels are supported */
+    DEFINE_PROP_BOOL("security-levels", GICv3State, security_levels, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = arm_gicv3_common_reset;
+    dc->realize = arm_gicv3_common_realize;
+    dc->props = arm_gicv3_common_properties;
+    dc->vmsd = &vmstate_gicv3;
+}
+
+static const TypeInfo arm_gicv3_common_type = {
+    .name = TYPE_ARM_GICV3_COMMON,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(GICv3State),
+    .class_size = sizeof(ARMGICv3CommonClass),
+    .class_init = arm_gicv3_common_class_init,
+    .abstract = true,
+};
+
+static void register_types(void)
+{
+    type_register_static(&arm_gicv3_common_type);
+}
+
+type_init(register_types)
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
new file mode 100644
index 0000000..589baca
--- /dev/null
+++ b/hw/intc/gicv3_internal.h
@@ -0,0 +1,156 @@ 
+/*
+ * ARM GIC support - internal interfaces
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_ARM_GICV3_INTERNAL_H
+#define QEMU_ARM_GICV3_INTERNAL_H
+
+#include "hw/intc/arm_gicv3_common.h"
+
+#define ALL_CPU_MASK ((uint64_t) (0xffffffffffffffff))
+
+/* Keep this macro so it will be easy to compare the code to GICv2 code.
+ * The compiler will optimize any +/- operation involving this macro
+ */
+#define GICV3_BASE_IRQ (0)
+
+#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
+#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
+#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
+#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
+#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
+#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
+#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
+#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
+#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
+#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level |= (cm)
+#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
+#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
+#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
+#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false
+#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
+#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?          \
+                                    s->priority1[irq][cpu] :            \
+                                    s->priority2[(irq) - GIC_INTERNAL])
+#define GIC_TARGET(irq) s->irq_target[irq]
+#define GIC_CLEAR_GROUP(irq, cm) (s->irq_state[irq].group &= ~(cm))
+#define GIC_SET_GROUP(irq, cm) (s->irq_state[irq].group |= (cm))
+#define GIC_TEST_GROUP(irq, cm) ((s->irq_state[irq].group & (cm)) != 0)
+
+static inline bool gic_test_pending(GICv3State *s, int irq, uint64_t cm)
+{
+    /* Edge-triggered interrupts are marked pending on a rising edge, but
+     * level-triggered interrupts are either considered pending when the
+     * level is active or if software has explicitly written to
+     * GICD_ISPENDR to set the state pending.
+     */
+    return (s->irq_state[irq].pending & cm) ||
+        (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_LEVEL(irq, cm));
+}
+
+#define GICD_CTLR            0x0000
+#define GICD_TYPER           0x0004
+#define GICD_IIDR            0x0008
+#define GICD_STATUSR         0x0010
+#define GICD_SETSPI_NSR      0x0040
+#define GICD_CLRSPI_NSR      0x0048
+#define GICD_SETSPI_SR       0x0050
+#define GICD_CLRSPI_SR       0x0058
+#define GICD_SEIR            0x0068
+#define GICD_ISENABLER       0x0100
+#define GICD_ICENABLER       0x0180
+#define GICD_ISPENDR         0x0200
+#define GICD_ICPENDR         0x0280
+#define GICD_ISACTIVER       0x0300
+#define GICD_ICACTIVER       0x0380
+#define GICD_IPRIORITYR      0x0400
+#define GICD_ICFGR           0x0C00
+#define GICD_IROUTER         0x6000
+#define GICD_PIDR2           0xFFE8
+
+/* GICD_CTLR fields  */
+#define GICD_CTLR_EN_GRP0           (1U << 0)
+#define GICD_CTLR_EN_GRP1NS         (1U << 1) /* GICv3 5.3.20 */
+#define GICD_CTLR_EN_GRP1S          (1U << 2)
+#define GICD_CTLR_EN_GRP1_ALL       (GICD_CTLR_EN_GRP1NS | GICD_CTLR_EN_GRP1S)
+#define GICD_CTLR_ARE               (1U << 4)
+#define GICD_CTLR_ARE_S             (1U << 4)
+#define GICD_CTLR_ARE_NS            (1U << 5)
+#define GICD_CTLR_DS                (1U << 6)
+#define GICD_CTLR_RWP               (1U << 31)
+
+#define GICD_IROUTER_SPI_MODE_ONE    (0U << 31)
+#define GICD_IROUTER_SPI_MODE_ANY    (1U << 31)
+
+#define GIC_PIDR2_ARCH_MASK   0xf0
+#define GIC_PIDR2_ARCH_GICv3  0x30
+#define GIC_PIDR2_ARCH_GICv4  0x40
+
+/*
+ * Re-Distributor registers, offsets from RD_base
+ */
+#define GICR_CTLR             GICD_CTLR
+#define GICR_IIDR             0x0004
+#define GICR_TYPER            0x0008
+#define GICR_STATUSR          GICD_STATUSR
+#define GICR_WAKER            0x0014
+#define GICR_SETLPIR          0x0040
+#define GICR_CLRLPIR          0x0048
+#define GICR_SEIR             GICD_SEIR
+#define GICR_PROPBASER        0x0070
+#define GICR_PENDBASER        0x0078
+#define GICR_INVLPIR          0x00A0
+#define GICR_INVALLR          0x00B0
+#define GICR_SYNCR            0x00C0
+#define GICR_MOVLPIR          0x0100
+#define GICR_MOVALLR          0x0110
+#define GICR_PIDR2            GICD_PIDR2
+
+#define GICR_WAKER_ProcessorSleep    (1U << 1)
+#define GICR_WAKER_ChildrenAsleep    (1U << 2)
+
+/*
+ * Re-Distributor registers, offsets from SGI_base
+ */
+#define GICR_ISENABLER0         GICD_ISENABLER
+#define GICR_ICENABLER0         GICD_ICENABLER
+#define GICR_ISPENDR0           GICD_ISPENDR
+#define GICR_ICPENDR0           GICD_ICPENDR
+#define GICR_ISACTIVER0         GICD_ISACTIVER
+#define GICR_ICACTIVER0         GICD_ICACTIVER
+#define GICR_IPRIORITYR0        GICD_IPRIORITYR
+#define GICR_ICFGR0             GICD_ICFGR
+
+#define GICR_TYPER_VLPIS        (1U << 1)
+#define GICR_TYPER_LAST         (1U << 4)
+
+/*
+ * Simulated used system registers
+ */
+#define GICC_CTLR_EN_GRP0    (1U << 0)
+#define GICC_CTLR_EN_GRP1    (1U << 1)
+#define GICC_CTLR_ACK_CTL    (1U << 2)
+#define GICC_CTLR_FIQ_EN     (1U << 3)
+#define GICC_CTLR_CBPR       (1U << 4) /* GICv1: SBPR */
+#define GICC_CTLR_EOIMODE    (1U << 9)
+#define GICC_CTLR_EOIMODE_NS (1U << 10)
+
+#endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
new file mode 100644
index 0000000..c8cc24e
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -0,0 +1,112 @@ 
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_GICV3_COMMON_H
+#define HW_ARM_GICV3_COMMON_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic_common.h"
+
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GICV3_MAXIRQ 1020
+#define GICV3_NCPU 64
+
+typedef struct gicv3_irq_state {
+    /* The enable bits are only banked for per-cpu interrupts.  */
+    uint64_t enabled;
+    uint64_t pending;
+    uint64_t active;
+    uint64_t level;
+    uint64_t group;
+    bool edge_trigger; /* true: edge-triggered, false: level-triggered  */
+} gicv3_irq_state;
+
+typedef struct gicv3_sgi_state {
+    uint64_t pending[GICV3_NCPU];
+} gicv3_sgi_state;
+
+typedef struct GICv3State {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    qemu_irq parent_irq[GICV3_NCPU];
+    qemu_irq parent_fiq[GICV3_NCPU];
+    /* GICD_CTLR; for a GIC with the security extensions the NS banked version
+     * of this register is just an alias of bit 1 of the S banked version.
+     */
+    uint32_t ctlr;
+    /* Sim GICC_CTLR; again, the NS banked version is just aliases of bits of
+     * the S banked register, so our state only needs to store the S version.
+     */
+    uint32_t cpu_ctlr[GICV3_NCPU];
+    bool cpu_enabled[GICV3_NCPU];
+
+    gicv3_irq_state irq_state[GICV3_MAXIRQ];
+    uint64_t irq_target[GICV3_MAXIRQ];
+    uint8_t priority1[GIC_INTERNAL][GICV3_NCPU];
+    uint8_t priority2[GICV3_MAXIRQ - GIC_INTERNAL];
+    uint16_t last_active[GICV3_MAXIRQ][GICV3_NCPU];
+    /* For each SGI on the target CPU, we store 64 bits
+     * indicating which source CPUs have made this SGI
+     * pending on the target CPU. These correspond to
+     * the bytes in the GIC_SPENDSGIR* registers as
+     * read by the target CPU.
+     */
+    gicv3_sgi_state sgi_state[GIC_NR_SGIS];
+
+    uint16_t priority_mask[GICV3_NCPU];
+    uint16_t running_irq[GICV3_NCPU];
+    uint16_t running_priority[GICV3_NCPU];
+    uint16_t current_pending[GICV3_NCPU];
+
+    uint32_t cpu_mask; /* For redistributor */
+    uint32_t num_cpu;
+    MemoryRegion iomem_dist; /* Distributor */
+    MemoryRegion iomem_lpi; /* Redistributor */
+    uint32_t num_irq;
+    uint32_t revision;
+    bool security_levels;
+    int dev_fd; /* kvm device fd if backed by kvm vgic support */
+} GICv3State;
+
+#define TYPE_ARM_GICV3_COMMON "arm_gicv3_common"
+#define ARM_GICV3_COMMON(obj) \
+     OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON)
+#define ARM_GICV3_COMMON_CLASS(klass) \
+     OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON)
+#define ARM_GICV3_COMMON_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON)
+
+typedef struct ARMGICv3CommonClass {
+    /*< private >*/
+    SysBusDeviceClass parent_class;
+    /*< public >*/
+
+    void (*pre_save)(GICv3State *s);
+    void (*post_load)(GICv3State *s);
+} ARMGICv3CommonClass;
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+                              const MemoryRegionOps *ops);
+
+#endif