Hello! > -----Original Message----- > From: Shlomo Pongratz [mailto:shlomopongr...@gmail.com] > Sent: Wednesday, October 21, 2015 6:09 AM > To: qemu-devel@nongnu.org > Cc: p.fe...@samsung.com; peter.mayd...@linaro.org; eric.au...@linaro.org; > shannon.z...@linaro.org; imamm...@redhat.com; ash...@broadcom.com; Shlomo > Pongratz > Subject: [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files > > From: Shlomo Pongratz <shlomo.pongr...@huawei.com> > > Add files need to maintain the GIC-500 state. > Use bitmaps for managing per cpu flags. > As the largest "atomic" data structure is uint64 supporting > more than 64 cores requires to change some data structures > to bitmap. > > Add mp_affinity poroperty vector to hold a copy of the > cpu's affinity. > > Signed-off-by: Shlomo Pongratz <shlomo.pongr...@huawei.com> > --- > hw/intc/arm_gicv3_common.c | 251 > ++++++++++++++++++++++++++++++++++++- > hw/intc/gicv3_internal.h | 210 +++++++++++++++++++++++++++++++ > include/hw/intc/arm_gicv3.h | 44 +++++++ > include/hw/intc/arm_gicv3_common.h | 78 +++++++++++- > 4 files changed, 577 insertions(+), 6 deletions(-) > create mode 100644 hw/intc/gicv3_internal.h > create mode 100644 include/hw/intc/arm_gicv3.h > > diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c > index 032ece2..3c9bd34 100644 > --- a/hw/intc/arm_gicv3_common.c > +++ b/hw/intc/arm_gicv3_common.c > @@ -21,6 +21,7 @@ > */ > > #include "hw/intc/arm_gicv3_common.h" > +#include "gicv3_internal.h" > > static void gicv3_pre_save(void *opaque) > { > @@ -43,11 +44,89 @@ static int gicv3_post_load(void *opaque, int version_id) > return 0; > } > > +static const VMStateDescription vmstate_gicv3_irq_state = { > + .name = "arm_gicv3/arm_gicv3_irq_state", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_BITMAP(enabled, gicv3_irq_state, 0, num_cpu), > + VMSTATE_BITMAP(pending, gicv3_irq_state, 0, num_cpu), > + VMSTATE_BITMAP(active, gicv3_irq_state, 0, num_cpu), > + VMSTATE_BITMAP(level, gicv3_irq_state, 0, num_cpu), > + VMSTATE_BITMAP(group, gicv3_irq_state, 0, num_cpu), > + VMSTATE_BOOL(edge_trigger, gic_irq_state), > + VMSTATE_BITMAP(target, gicv3_irq_state, 0, num_cpu), > + VMSTATE_VARRAY_INT32(last_active, gicv3_irq_state, num_cpu, > + 0, vmstate_info_uint16, uint16_t), > + VMSTATE_INT32(num_cpu, gicv3_irq_state), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static const VMStateDescription vmstate_gicv3_Priority = { > + .name = "arm_gicv3/priority1", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_VARRAY_INT32(p, gicv3_Priority, num_cpu, > + 0, vmstate_info_uint8, uint8_t), > + VMSTATE_INT32(num_cpu, gicv3_Priority), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static const VMStateDescription vmstate_gicv3_sgi_state = { > + .name = "arm_gicv3/arm_gicv3_sgi/arm_gicv3_sgi_state", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_BITMAP(pending, gicv3_sgi_state, 0, num_cpu), > + VMSTATE_INT32(num_cpu, gicv3_sgi_state), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static const VMStateDescription vmstate_gicv3_sgi_vec = { > + .name = "arm_gicv3/arm_gicv3_sgi_vec", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_STRUCT_VARRAY_INT32(state, gicv3_sgi_vec, num_cpu, > + 0, vmstate_gicv3_sgi_state, > gicv3_sgi_state), > + VMSTATE_INT32(num_cpu, gicv3_sgi_vec), > + VMSTATE_END_OF_LIST() > + } > +}; > + > static const VMStateDescription vmstate_gicv3 = { > .name = "arm_gicv3", > .unmigratable = 1, > .pre_save = gicv3_pre_save, > .post_load = gicv3_post_load, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32(ctlr, GICv3State), > + VMSTATE_VARRAY_UINT32(cpu_ctlr, GICv3State, num_cpu, > + 0, vmstate_info_uint32, uint32_t), > + VMSTATE_STRUCT_ARRAY(irq_state, GICv3State, GICV3_MAXIRQ, 1, > + vmstate_gicv3_irq_state, gicv3_irq_state), > + VMSTATE_STRUCT_ARRAY(priority1, GICv3State, GICV3_INTERNAL, 1, > + vmstate_gicv3_Priority, gicv3_Priority), > + VMSTATE_UINT8_ARRAY(priority2, GICv3State, GICV3_MAXIRQ - > GICV3_INTERNAL), > + VMSTATE_STRUCT_ARRAY(sgi, GICv3State, GICV3_NR_SGIS, 1, > + vmstate_gicv3_sgi_vec, gicv3_sgi_vec), > + VMSTATE_VARRAY_UINT32(priority_mask, GICv3State, num_cpu, 0, > + vmstate_info_uint16, uint16_t), > + VMSTATE_VARRAY_UINT32(running_irq, GICv3State, num_cpu, 0, > + vmstate_info_uint16, uint16_t), > + VMSTATE_VARRAY_UINT32(running_priority, GICv3State, num_cpu, 0, > + vmstate_info_uint16, uint16_t), > + VMSTATE_VARRAY_UINT32(current_pending, GICv3State, num_cpu, 0, > + vmstate_info_uint16, uint16_t), > + VMSTATE_VARRAY_UINT32(mp_affinity, GICv3State, num_mp_affinity, 0, > + vmstate_info_uint64, uint64_t), > + VMSTATE_UINT32(num_cpu, GICv3State), > + VMSTATE_END_OF_LIST() > + } > };
If you look at our conversation with Peter, first i implemented similar data structures, and he disliked it. He suggested to separate SPIs and PPIs. So, i came up with fixed-size bitmaps, and two structures: global data and per-CPU data. SPIs are stored in global structure, SGIs/PPIs - in per-CPU one. I cc'ed all my patches to you, have you seen them? > > void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, > @@ -63,11 +142,11 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, > qemu_irq_handler handler, > * [N+32..N+63] PPIs for CPU 1 > * ... > */ > - i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu; > + i = s->num_irq - GICV3_INTERNAL + GICV3_INTERNAL * s->num_cpu; GICV3_INTERNAL was criticised long time ago, because kvm_arm_gic_set_irq(), used by both vGIC implementations, uses GIC_INTERNAL. Anyway, these two constants are the same. > qdev_init_gpio_in(DEVICE(s), handler, i); > > - s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq)); > - s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq)); > + s->parent_irq = g_new0(qemu_irq, s->num_cpu); > + s->parent_fiq = g_new0(qemu_irq, s->num_cpu); > > for (i = 0; i < s->num_cpu; i++) { > sysbus_init_irq(sbd, &s->parent_irq[i]); > @@ -88,6 +167,10 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, > qemu_irq_handler handler, > static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) > { > GICv3State *s = ARM_GICV3_COMMON(dev); > + int num_irq = s->num_irq; > + gicv3_irq_state *irq_state; > + gicv3_sgi_vec *sgi_vec; > + int i; > > /* revision property is actually reserved and currently used only in > order > * to keep the interface compatible with GICv2 code, avoiding extra > @@ -98,18 +181,176 @@ static void arm_gicv3_common_realize(DeviceState *dev, > Error **errp) > error_setg(errp, "unsupported GIC revision %d", s->revision); > 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; > + } > + > + /* s->parent_irq and s->parent_fiq are initialized in > + * gicv3_init_irqs_and_mmio > + */ > + s->priority_mask = g_new0(uint16_t, s->num_cpu); > + s->current_pending = g_new(uint16_t, s->num_cpu); > + s->running_irq = g_new(uint16_t, s->num_cpu); > + s->running_priority = g_new(uint16_t, s->num_cpu); > + s->cpu_ctlr = g_new0(uint32_t, s->num_cpu); > + s->cpu_enabled = bitmap_new(s->num_cpu); > + bitmap_zero(s->cpu_enabled, s->num_cpu); > + /* Don't ovreride mp_affinity it is a prop */ > + > + for (i = 0; i < s->num_cpu; i++) { > + s->current_pending[i] = 1023; > + s->running_irq[i] = 1023; > + s->running_priority[i] = 0x100; > + } > + > + irq_state = s->irq_state; > + for (i = 0; i < GICV3_MAXIRQ; i++) { > + irq_state->num_cpu = s->num_cpu; > + irq_state->enabled = bitmap_new(s->num_cpu); > + bitmap_zero(irq_state->enabled, s->num_cpu); > + irq_state->pending = bitmap_new(s->num_cpu); > + bitmap_zero(irq_state->pending, s->num_cpu); > + irq_state->active = bitmap_new(s->num_cpu); > + bitmap_zero(irq_state->active, s->num_cpu); > + irq_state->level = bitmap_new(s->num_cpu); > + bitmap_zero(irq_state->level, s->num_cpu); > + irq_state->group = bitmap_new(s->num_cpu); > + bitmap_zero(irq_state->group, s->num_cpu); > + irq_state->edge_trigger = false; > + irq_state->target = bitmap_new(s->num_cpu); > + bitmap_zero(irq_state->target, s->num_cpu); > + irq_state->last_active = g_new0(uint16_t, s->num_cpu); > + irq_state++; > + } > + > + sgi_vec = s->sgi; > + for (i = 0; i < GICV3_NR_SGIS; i++) { > + int j; > + struct gicv3_sgi_state *sgi_state; > + sgi_vec->num_cpu = s->num_cpu; > + sgi_vec->state = g_new0(gicv3_sgi_state, s->num_cpu); > + sgi_state = sgi_vec->state; > + for (j = 0; j < s->num_cpu; j++) { > + sgi_state->num_cpu = s->num_cpu; > + sgi_state->pending = bitmap_new(s->num_cpu); > + bitmap_zero(sgi_state->pending, s->num_cpu); > + sgi_state++; > + } > + sgi_vec++; > + } > + > + for (i = 0; i < GICV3_INTERNAL; i++) { > + s->priority1[i].num_cpu = s->num_cpu; > + s->priority1[i].p = g_new0(uint8_t, s->num_cpu); > + } > } > > static void arm_gicv3_common_reset(DeviceState *dev) > { > - /* TODO */ > + GICv3State *s = ARM_GICV3_COMMON(dev); > + gicv3_irq_state *irq_state; > + gicv3_sgi_vec *sgi_vec; > + 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; > + /* Don't tuch mp_affinity set in virt.c */ > + } > + > + irq_state = s->irq_state; > + for (i = 0; i < GICV3_MAXIRQ; i++) { > + /* Reset every filed in irq_state */ > + bitmap_zero(irq_state->enabled, s->num_cpu); > + bitmap_zero(irq_state->pending, s->num_cpu); > + bitmap_zero(irq_state->active, s->num_cpu); > + bitmap_zero(irq_state->level, s->num_cpu); > + bitmap_zero(irq_state->group, s->num_cpu); > + bitmap_zero(irq_state->target, s->num_cpu); > + memset(irq_state->last_active, 0, > + s->num_cpu * sizeof(*irq_state->last_active)); > + irq_state->edge_trigger = 0; > + irq_state++; > + } > + /* GIC-500 comment 'j' SGI are always enabled */ > + for (i = 0; i < GICV3_NR_SGIS; i++) { > + GIC_SET_ENABLED(i, ALL_CPU_MASK); > + GIC_SET_EDGE_TRIGGER(i); > + } > + > + sgi_vec = s->sgi; > + for (i = 0; i < GICV3_NR_SGIS; i++) { > + struct gicv3_sgi_state *sgi_state = sgi_vec->state; > + int j; > + for (j = 0; j < s->num_cpu; j++) { > + bitmap_zero(sgi_state->pending, s->num_cpu); > + sgi_state++; > + } > + sgi_vec++; > + } > + > + if (s->num_cpu == 1) { > + /* For uniprocessor GICs all interrupts always target the sole CPU */ > + for (i = 0; i < GICV3_MAXIRQ; i++) { > + set_bit(0, s->irq_state[i].target); > + } > + } > + > + for (i = 0; i < GICV3_INTERNAL; i++) > + memset(s->priority1[i].p, 0, s->num_cpu * > sizeof(*s->priority1[i].p)); > + memset(s->priority2, 0, sizeof(s->priority2)); > + > + /* 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), > - DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, > 0), > + DEFINE_PROP_UINT8("security-levels", GICv3State, security_levels, 0), Why this change? Anyway, we either have or don't have trustzone support. So, what's wrong with "has-security-extensions" boolean? It would be convenient to have the same interface for all GIC versions. > + DEFINE_PROP_ARRAY("mp-affinity", GICv3State, num_mp_affinity, > mp_affinity, > + qdev_prop_uint64, uint64_t), Hmmm... Is it convenient to use? In my experimental code i added this property to CPU, iterated over CPUs and compared value of the property with IROUTER. > DEFINE_PROP_END_OF_LIST(), > }; > > diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h > new file mode 100644 > index 0000000..e0b4a08 > --- /dev/null > +++ b/hw/intc/gicv3_internal.h > @@ -0,0 +1,210 @@ > +/* > + * 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.h" > + > +/* Marks all CPUs */ > +#define ALL_CPU_MASK ((int) -1) > +#define ALL_CPU_MASK_COMPAT ((unsigned)(0xff)) > + > +/* 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) > + > +static inline void auto_or(GICv3State *s, unsigned long *target, unsigned > long *bm) > +{ > + bitmap_or(target, target, bm, s->num_cpu); > +} > + > +static inline int auto_test(GICv3State *s, unsigned long *target, unsigned > long *bm) > +{ > + /* Result used for test */ > + return bitmap_intersects(target, bm, s->num_cpu); > +} > + > +static inline void auto_andnot(GICv3State *s, unsigned long *target, > unsigned long *bm) > +{ > + /* Ignore status */ > + (void) bitmap_andnot(target, target, bm, s->num_cpu); > +} > + > +static inline void gic_set(GICv3State *s, unsigned long *bm, int cpu) > +{ > + if (cpu < 0) /* All CPUs */ > + bitmap_fill(bm, s->num_cpu); > + else > + set_bit(cpu, bm); > +} > + > +static inline void gic_clr(GICv3State *s, unsigned long *bm, int cpu) > +{ > + if (cpu < 0) /* All CPUs */ > + bitmap_zero(bm, s->num_cpu); > + else > + clear_bit(cpu, bm); > +} > + > +static inline int gic_test(GICv3State *s, unsigned long *bm, int cpu) > +{ > + if (cpu < 0) /* ANY CPUs */ > + return !bitmap_empty(bm, s->num_cpu); > + else > + return test_bit(cpu, bm); > +} > + > +#define GIC_SET_ENABLED(irq, cm) gic_set(s, s->irq_state[irq].enabled, cm) > +#define GIC_CLEAR_ENABLED(irq, cm) gic_clr(s, s->irq_state[irq].enabled, cm) > +#define GIC_TEST_ENABLED(irq, cm) gic_test(s, s->irq_state[irq].enabled, cm) > +#define GIC_SET_PENDING(irq, cm) gic_set(s, s->irq_state[irq].pending, cm) > +#define GIC_SET_PENDING_MASK(irq, bm) auto_or(s, s->irq_state[irq].pending, > bm) > +#define GIC_TEST_PENDING(irq, cm) gic_test(s, s->irq_state[irq].pending, cm) > +#define GIC_CLEAR_PENDING(irq, cm) gic_clr(s, s->irq_state[irq].pending, cm) > +#define GIC_SET_ACTIVE(irq, cm) gic_set(s, s->irq_state[irq].active, cm) > +#define GIC_CLEAR_ACTIVE(irq, cm) gic_clr(s, s->irq_state[irq].active, cm) > +#define GIC_TEST_ACTIVE(irq, cm) gic_test(s, s->irq_state[irq].active, cm) > +#define GIC_SET_LEVEL(irq, cm) gic_set(s, s->irq_state[irq].level, cm) > +#define GIC_CLEAR_LEVEL(irq, cm) gic_clr(s, s->irq_state[irq].level, cm) > +#define GIC_SET_LEVEL_MASK(irq, bm) auto_or(s, s->irq_state[irq].level, bm) > +#define GIC_CLEAR_LEVEL_MASK(irq, bm) auto_andnot(s, > s->irq_state[irq].level, bm) > +#define GIC_TEST_LEVEL(irq, cm) gic_test(s, s->irq_state[irq].level, cm) > +#define GIC_TEST_LEVEL_MASK(irq, bm) auto_test(s, s->irq_state[irq].level, > bm) > +#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true > +#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false > +#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger) > +#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GICV3_INTERNAL) ? \ > + s->priority1[irq].p[cpu] : \ > + s->priority2[(irq) - GICV3_INTERNAL]) > +#define GIC_SET_TARGET(irq, cm) gic_set(s, s->irq_state[irq].target, cm) > +#define GIC_CLEAR_TARGET(irq, cm) gic_clr(s, s->irq_state[irq].target, cm) > +#define GIC_TEST_TARGET(irq, cm) gic_test(s, s->irq_state[irq].target, cm) > +#define GIC_TARGET(irq) s->irq_state[irq].target > +#define GIC_CLEAR_GROUP(irq, cm) gic_clr(s, s->irq_state[irq].group, cm) > +#define GIC_SET_GROUP(irq, cm) gic_set(s, s->irq_state[irq].group, cm) > +#define GIC_TEST_GROUP(irq, cm) gic_test(s, s->irq_state[irq].group, cm) > + > +/* The special cases for the revision property: */ > +#define REV_V3 3 > + > +static inline bool gic_test_pending(GICv3State *s, int irq, int 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 GIC_TEST_PENDING(irq, 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.h b/include/hw/intc/arm_gicv3.h > new file mode 100644 > index 0000000..a03af35 > --- /dev/null > +++ b/include/hw/intc/arm_gicv3.h > @@ -0,0 +1,44 @@ > +/* > + * 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_H > +#define HW_ARM_GICV3_H > + > +#include "arm_gicv3_common.h" > + > +#define TYPE_ARM_GICV3 "arm_gicv3" > +#define ARM_GICV3(obj) \ > + OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3) > +#define ARM_GICV3_CLASS(klass) \ > + OBJECT_CLASS_CHECK(ARMGICv3Class, (klass), TYPE_ARM_GICV3) > +#define ARM_GICV3_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(ARMGICv3Class, (obj), TYPE_ARM_GICV3) > + > +typedef struct ARMGICv3Class { > + /*< private >*/ > + ARMGICv3CommonClass parent_class; > + /*< public >*/ > + > + DeviceRealize parent_realize; > +} ARMGICv3Class; > + > +#endif > diff --git a/include/hw/intc/arm_gicv3_common.h > b/include/hw/intc/arm_gicv3_common.h > index c2fd8da..aa32229 100644 > --- a/include/hw/intc/arm_gicv3_common.h > +++ b/include/hw/intc/arm_gicv3_common.h > @@ -26,6 +26,51 @@ > #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 > +/* First 32 are private to each CPU (SGIs and PPIs). */ > +#define GICV3_INTERNAL 32 > +#define GICV3_NR_SGIS 16 > + > +#define ARM_AFF0_SHIFT 0 > +#define ARM_AFF0_MASK (0xFFULL << ARM_AFF0_SHIFT) > +#define ARM_AFF1_SHIFT 8 > +#define ARM_AFF1_MASK (0xFFULL << ARM_AFF1_SHIFT) > +#define ARM_AFF2_SHIFT 16 > +#define ARM_AFF2_MASK (0xFFULL << ARM_AFF2_SHIFT) > +#define ARM_AFF3_SHIFT 32 > +#define ARM_AFF3_MASK (0xFFULL << ARM_AFF3_SHIFT) > + > +#define MAX_NR_GROUP_PRIO 128 > + > +typedef struct gicv3_irq_state { > + /* The enable bits are only banked for per-cpu interrupts. */ > + unsigned long *enabled; > + unsigned long *pending; > + unsigned long *active; > + unsigned long *level; > + unsigned long *group; > + unsigned long *target; > + uint16_t *last_active; > + bool edge_trigger; /* true: edge-triggered, false: level-triggered */ > + int32_t num_cpu; /* For VMSTATE_BITMAP & VMSTATE_VARRAY */ > +} gicv3_irq_state; > + > +typedef struct gicv3_sgi_state { > + unsigned long *pending; > + int32_t num_cpu; /* For VMSTATE_BITMAP */ > +} gicv3_sgi_state; > + > +typedef struct gicv3_sgi_vec { > + struct gicv3_sgi_state *state; > + int32_t num_cpu; /* For VMSTATE_VARRAY */ > +} gicv3_sgi_vec; > + > +typedef struct gicv3_priority { > + uint8_t *p; > + int32_t num_cpu; /* For VMSTATE_VARRAY */ > +} gicv3_Priority; > + > typedef struct GICv3State { > /*< private >*/ > SysBusDevice parent_obj; > @@ -33,14 +78,45 @@ typedef struct GICv3State { > > qemu_irq *parent_irq; > qemu_irq *parent_fiq; > + /* 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; > + unsigned long *cpu_enabled; > + > + gicv3_irq_state irq_state[GICV3_MAXIRQ]; > + gicv3_Priority priority1[GICV3_INTERNAL]; > + uint8_t priority2[GICV3_MAXIRQ - GICV3_INTERNAL]; > + /* For each SGI on the target CPU, we store bitmap > + * 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_vec sgi[GICV3_NR_SGIS]; > + > + uint16_t *priority_mask; > + uint16_t *running_irq; > + uint16_t *running_priority; > + uint16_t *current_pending; > + uint32_t num_mp_affinity; > + uint64_t *mp_affinity; > > MemoryRegion iomem_dist; /* Distributor */ > + MemoryRegion iomem_spi; > + MemoryRegion iomem_its_cntrl; > + MemoryRegion iomem_its; > MemoryRegion iomem_redist; /* Redistributors */ > > + uint32_t cpu_mask; /* For redistributer */ > uint32_t num_cpu; > uint32_t num_irq; > uint32_t revision; > - bool security_extn; > + uint8_t security_levels; /* replace seurity extentions */ > > int dev_fd; /* kvm device fd if backed by kvm vgic support */ > } GICv3State; > -- > 1.9.1 Kind regards, Pavel Fedin Expert Engineer Samsung Electronics Research center Russia