Comment on the "workaround" see inline. On Friday, October 23, 2015, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 22 October 2015 at 15:02, Pavel Fedin <p.fe...@samsung.com > <javascript:;>> wrote: > > Add state information to GICv3 object structure and implement > > arm_gicv3_common_reset(). Also, add some functions for registers which > are > > not stored directly but simulated. > > > > State information includes not only pure GICv3 data, but also some legacy > > registers. This will be useful for implementing software emulation of > GICv3 > > with v2 backwards compatilibity mode. > > So we're going to (potentially) emulate: > * non-system-register config > * non-affinity-routing config > > ? OK, but are we really sure we want to do that? Legacy config > is deprecated and it's really going to complicate the model... > > (Are we starting out with the non-legacy config that forces > system-regs and affinity-routing to always-on?) > > > Signed-off-by: Pavel Fedin <p.fe...@samsung.com <javascript:;>> > > --- > > hw/intc/arm_gicv3_common.c | 127 +++++++++++++++++- > > hw/intc/gicv3_internal.h | 265 > +++++++++++++++++++++++++++++++++++++ > > include/hw/intc/arm_gicv3_common.h | 93 ++++++++++++- > > 3 files changed, 480 insertions(+), 5 deletions(-) > > create mode 100644 hw/intc/gicv3_internal.h > > > > diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c > > index 032ece2..2082d05 100644 > > --- a/hw/intc/arm_gicv3_common.c > > +++ b/hw/intc/arm_gicv3_common.c > > @@ -3,8 +3,9 @@ > > * > > * Copyright (c) 2012 Linaro Limited > > * Copyright (c) 2015 Huawei. > > + * Copyright (c) 2015 Samsung Electronics Co., Ltd. > > * Written by Peter Maydell > > - * Extended to 64 cores by Shlomo Pongratz > > + * Reworked for GICv3 by Shlomo Pongratz and Pavel Fedin > > * > > * 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 > > @@ -21,6 +22,7 @@ > > */ > > > > #include "hw/intc/arm_gicv3_common.h" > > +#include "gicv3_internal.h" > > > > static void gicv3_pre_save(void *opaque) > > { > > @@ -88,6 +90,8 @@ 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); > > + Object *cpu; > > + unsigned int i, j; > > > > /* revision property is actually reserved and currently used only > in order > > * to keep the interface compatible with GICv2 code, avoiding extra > > @@ -98,11 +102,130 @@ static void arm_gicv3_common_realize(DeviceState > *dev, Error **errp) > > error_setg(errp, "unsupported GIC revision %d", s->revision); > > return; > > } > > + > > + if (s->num_irq > GICV3_MAXIRQ) { > > + error_setg(errp, > > + "requested %u interrupt lines exceeds GIC maximum > %d", > > + s->num_irq, GICV3_MAXIRQ); > > + return; > > + } > > + > > + s->cpu = g_malloc(s->num_cpu * sizeof(GICv3CPUState)); > > g_new0(GICv3CPUState, s->num_cpu); > > > + > > + for (i = 0; i < s->num_cpu; i++) { > > + for (j = 0; j < GIC_NR_SGIS; j++) { > > + s->cpu[i].sgi[j].pending = > g_malloc(BITS_TO_LONGS(s->num_cpu)); > > + s->cpu[i].sgi[j].size = s->num_cpu; > > + } > > + > > + cpu = OBJECT(qemu_get_cpu(i)); > > + s->cpu[i].affinity_id = object_property_get_int(cpu, > "mp-affinity", > > + NULL); > > + } > > } > > > > static void arm_gicv3_common_reset(DeviceState *dev) > > { > > - /* TODO */ > > + GICv3State *s = ARM_GICV3_COMMON(dev); > > + unsigned int i, j; > > + > > + for (i = 0; i < s->num_cpu; i++) { > > + GICv3CPUState *c = &s->cpu[i]; > > + > > + c->cpu_enabled = false; > > + c->redist_ctlr = 0; > > + c->propbaser = > GICR_PROPBASER_InnerShareable|GICR_PROPBASER_WaWb; > > + c->pendbaser = > GICR_PENDBASER_InnerShareable|GICR_PENDBASER_WaWb; > > + /* 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. > > + * The same for SPIs below > > + */ > > Is this a bug in Linux, or is it just expecting that firmware configures > all interrupts into group 1 for it? (ie do we need some variation on > commit 8ff41f3995ad2d for gicv3 ?) > I think it is a bug in Linux as I explain in the comment, as far as I know the kernel should not assume anything, that is if it wants ti use group one it should initialize it, but since I don't have a board with a GICv3 (GIC500) I can't be sure. My purpose is to make the "virt" virtual machine work. Maybe this initialization should go there. > > > + c->group = 0xffffffff; > > + /* GIC-500 comment 'j' SGI are always enabled */ > > + c->enabled = 0x0000ffff; > > + c->pending = 0; > > + c->active = 0; > > + c->level = 0; > > + c->edge_trigger = 0x0000ffff; > > + memset(c->priority, 0, sizeof(c->priority)); > > + for (j = 0; j < GIC_NR_SGIS; j++) { > > + bitmap_zero(c->sgi[j].pending, s->num_cpu); > > + } > > + > > + c->ctlr[0] = 0; > > + c->ctlr[1] = 0; > > + c->legacy_ctlr = 0; > > + c->priority_mask = 0; > > + c->bpr[0] = GIC_MIN_BPR0; > > + c->bpr[1] = GIC_MIN_BPR1; > > + memset(c->apr, 0, sizeof(c->apr)); > > + > > + c->current_pending = 1023; > > + c->running_irq = 1023; > > + c->running_priority = 0x100; > > + memset(c->last_active, 0, sizeof(c->last_active)); > > + } > > + > > + memset(s->group, 0, sizeof(s->group)); > > + memset(s->enabled, 0, sizeof(s->enabled)); > > + memset(s->pending, 0, sizeof(s->pending)); > > + memset(s->active, 0, sizeof(s->active)); > > + memset(s->level, 0, sizeof(s->level)); > > + memset(s->edge_trigger, 0, sizeof(s->edge_trigger)); > > + > > + /* Workaround! (the same as c->group above) */ > > + for (i = GIC_INTERNAL; i < s->num_irq; i++) { > > + set_bit(i - GIC_INTERNAL, s->group); > > + } > > + > > + /* By default all interrupts always target CPU #0 */ > > + for (i = 0; i < GICV3_MAXSPI; i++) { > > + s->irq_target[i] = 1; > > + } > > + memset(s->irq_route, 0, sizeof(s->irq_route)); > > + memset(s->priority, 0, sizeof(s->priority)); > > + > > + /* With all configuration we don't support GICv2 backwards > computability */ > > + if (s->security_extn) { > > + /* 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; > > + } > > +} > > + > > +uint32_t gicv3_get_igrpen0(GICv3State *s, int cpuindex) > > +{ > > + GICv3CPUState *c = &s->cpu[cpuindex]; > > + > > + return extract32(c->legacy_ctlr, GICC_CTLR_EN_GRP0_SHIFT, 1); > > +} > > My gut feeling is that if we alias legacy and system register > state, then we should do it by having the 'master' copy be > the system register format. > > > + > > +void gicv3_set_igrpen0(GICv3State *s, int cpuindex, uint32_t val) > > +{ > > + GICv3CPUState *c = &s->cpu[cpuindex]; > > + > > + c->legacy_ctlr = deposit32(c->legacy_ctlr, GICC_CTLR_EN_GRP0_SHIFT, > 1, val); > > +} > > + > > +uint32_t gicv3_get_igrpen1(GICv3State *s, int cpuindex) > > +{ > > + GICv3CPUState *c = &s->cpu[cpuindex]; > > + > > + return extract32(c->legacy_ctlr, GICC_CTLR_EN_GRP1_SHIFT, 1); > > +} > > + > > +void gicv3_set_igrpen1(GICv3State *s, int cpuindex, uint32_t val) > > +{ > > + GICv3CPUState *c = &s->cpu[cpuindex]; > > + > > + c->legacy_ctlr = deposit32(c->legacy_ctlr, GICC_CTLR_EN_GRP1_SHIFT, > 1, val); > > } > > > > static Property arm_gicv3_common_properties[] = { > > diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h > > new file mode 100644 > > index 0000000..f1694b3 > > --- /dev/null > > +++ b/hw/intc/gicv3_internal.h > > @@ -0,0 +1,265 @@ > > +/* > > + * ARM GICv3 support - internal interfaces > > + * > > + * Copyright (c) 2012 Linaro Limited > > + * Copyright (c) 2015 Huawei. > > + * Copyright (c) 2015 Samsung Electronics Co., Ltd. > > + * Written by Peter Maydell > > + * Reworked for GICv3 by Shlomo Pongratz and Pavel Fedin > > + * > > + * 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" > > + > > +/* > > + * Field manipulations > > + */ > > +#define GIC_CLEAR_BIT(irq, ncpu, field) \ > > + do { \ > > + if ((irq) < GIC_INTERNAL) { \ > > + s->cpu[(ncpu)].field &= ~(1 << (irq)); \ > > + } else { \ > > + clear_bit((irq) - GIC_INTERNAL, s->field); \ > > + } \ > > + } while (0) > > +#define GIC_SET_BIT(irq, ncpu, field) \ > > + do { \ > > + if ((irq) < GIC_INTERNAL) { \ > > + s->cpu[(ncpu)].field |= 1 << (irq); \ > > + } else { \ > > + set_bit((irq) - GIC_INTERNAL, s->field); \ > > + } \ > > + } while (0) > > Special-casing irq numbers less than GIC_INTERNAL like this looks a bit > odd. Since in general the difference is that the state for the > < GIC_INTERNAL irqs is in the distributor, whereas state for the others > is in the redistributor, I wouldn't expect code to generally want to > update the state without caring whether it's in the distributor or the > redistributor. Where we do need to do something different for these > cases I think it will be clearer to have the "internal irqs are different" > check in the calling code, not hidden in the accessors. > > (This will also allow you to use proper functions rather than > macros, generally.) > > > +#define GIC_REPLACE_BIT(irq, ncpu, field, val) \ > > + do { \ > > + if (val) { \ > > + GIC_SET_BIT(irq, ncpu, field); \ > > + } else { \ > > + GIC_CLEAR_BIT(irq, ncpu, field); \ > > + } \ > > + } while (0) > > +#define GIC_TEST_BIT(irq, ncpu, field) \ > > + (((irq) < GIC_INTERNAL) ? (s->cpu[(ncpu)].field >> (irq)) & 1 : \ > > + test_bit((irq) - GIC_INTERNAL, s->field)) > > + > > +#define GIC_SET_PRIORITY(irq, ncpu, pri) \ > > + do { \ > > + if ((irq) < GIC_INTERNAL) { \ > > + s->cpu[(ncpu)].priority[(irq)] = (pri); \ > > + } else { \ > > + s->priority[(irq) - GIC_INTERNAL] = (pri); \ > > + } \ > > + } while (0) > > +#define GIC_GET_PRIORITY(irq, ncpu) \ > > + (((irq) < GIC_INTERNAL) ? s->cpu[(ncpu)].priority[irq] : \ > > + s->priority[(irq) - GIC_INTERNAL]) > > + > > +#define GIC_GET_TARGET(irq, ncpu) \ > > + (((irq) < GIC_INTERNAL) ? (1 << (ncpu)) : \ > > + s->irq_target[(irq) - GIC_INTERNAL]) > > +#define GIC_SET_TARGET(irq, cm) \ > > + do { \ > > + if ((irq) >= GIC_INTERNAL) { \ > > + s->irq_target[(irq - GIC_INTERNAL)] = (cm); \ > > + } \ > > + } while (0) > > + > > +#define GIC_SET_GROUP(irq, cpu) GIC_SET_BIT(irq, cpu, group) > > +#define GIC_CLEAR_GROUP(irq, cpu) GIC_CLEAR_BIT(irq, cpu, group) > > +#define GIC_REPLACE_GROUP(irq, cpu, val) GIC_REPLACE_BIT(irq, cpu, > group, val) > > +#define GIC_TEST_GROUP(irq, cpu) GIC_TEST_BIT(irq, cpu, group) > > +#define GIC_SET_ENABLED(irq, cpu) GIC_SET_BIT(irq, cpu, enabled) > > +#define GIC_CLEAR_ENABLED(irq, cpu) GIC_CLEAR_BIT(irq, cpu, > enabled) > > +#define GIC_REPLACE_ENABLED(irq, cpu, val) \ > > + GIC_REPLACE_BIT(irq, cpu, > enabled, val) > > +#define GIC_TEST_ENABLED(irq, cpu) GIC_TEST_BIT(irq, cpu, enabled) > > +#define GIC_SET_PENDING(irq, cpu) GIC_SET_BIT(irq, cpu, pending) > > +#define GIC_CLEAR_PENDING(irq, cpu) GIC_CLEAR_BIT(irq, cpu, > pending) > > +#define GIC_REPLACE_PENDING(irq, cpu, val) \ > > + GIC_REPLACE_BIT(irq, cpu, > pending, val) > > +#define GIC_TEST_PENDING(irq, cpu) GIC_TEST_BIT(irq, cpu, pending) > > +#define GIC_SET_ACTIVE(irq, cpu) GIC_SET_BIT(irq, cpu, active) > > +#define GIC_CLEAR_ACTIVE(irq, cpu) GIC_CLEAR_BIT(irq, cpu, active) > > +#define GIC_REPLACE_ACTIVE(irq, cpu, val) GIC_REPLACE_BIT(irq, cpu, > active, val) > > +#define GIC_TEST_ACTIVE(irq, cpu) GIC_TEST_BIT(irq, cpu, active) > > +#define GIC_SET_LEVEL(irq, cpu) GIC_SET_BIT(irq, cpu, level) > > +#define GIC_CLEAR_LEVEL(irq, cpu) GIC_CLEAR_BIT(irq, cpu, level) > > +#define GIC_REPLACE_LEVEL(irq, cpu, val) GIC_REPLACE_BIT(irq, cpu, > level, val) > > +#define GIC_TEST_LEVEL(irq, cpu) GIC_TEST_BIT(irq, cpu, level) > > +#define GIC_SET_EDGE_TRIGGER(irq, cpu) GIC_SET_BIT(irq, cpu, > edge_trigger) > > +#define GIC_CLEAR_EDGE_TRIGGER(irq, cpu) GIC_CLEAR_BIT(irq, cpu, > edge_trigger) > > +#define GIC_REPLACE_EDGE_TRIGGER(irq, cpu, val) \ > > + GIC_REPLACE_BIT(irq, cpu, > edge_trigger, val) > > +#define GIC_TEST_EDGE_TRIGGER(irq, cpu) GIC_TEST_BIT(irq, cpu, > edge_trigger) > > + > > +static inline bool gic_test_pending(GICv3State *s, int irq, int cpu) > > +{ > > + /* 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, cpu) || > > + (!GIC_TEST_EDGE_TRIGGER(irq, cpu) && GIC_TEST_LEVEL(irq, > cpu)); > > +} > > + > > + > > +#define GICD_CTLR 0x0000 > > This block of GICD_ constants is missing a header comment. > > > +#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_IGROUPR 0x0080 > > +#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_ITARGETSR 0x0800 > > +#define GICD_ICFGR 0x0C00 > > +#define GICD_CPENDSGIR 0x0F10 > > +#define GICD_SPENDSGIR 0x0F20 > > +#define GICD_IROUTER 0x6000 > > +#define GICD_PIDR2 0xFFE8 > > Missing GICD_IGRPMODR, GICD_NASCR, GICD_SGIR ? > > > > > + > > +/* 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) > > Comment about why we're defining two bits with the same value? > > > +#define GICD_CTLR_ARE_NS (1U << 5) > > +#define GICD_CTLR_DS (1U << 6) > > +#define GICD_CTLR_RWP (1U << 31) > > Might as well add GICD_CTLR_E1NWF while we're here. > > > + > > +/* > > + * Redistributor frame offsets from RD_base > > + */ > > +#define GICR_SGI_OFFSET 0x10000 > > + > > +/* > > + * Re-Distributor registers, offsets from RD_base > > + */ > > +#define GICR_CTLR GICD_CTLR > > The redistributor register layout has nothing to do with the > distributor register layout, so it doesn't make sense to define > the GICR_ constants in terms of the GICD_ ones. > > > +#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 > > My copy of the GICv3 spec defines 0x100 and 0x110 as IMPDEF. > > > +#define GICR_PIDR2 GICD_PIDR2 > > + > > +#define GICR_CTLR_DPG1S (1U << 26) > > +#define GICR_CTLR_DPG1NS (1U << 25) > > +#define GICR_CTLR_DPG0 (1U << 24) > > +#define GICR_CTLR_ENABLE_LPIS (1U << 0) > > Missing UWP and RWP. > > Why is this set of constants defined from the highest bit > working down, when the GICD_CTLR constants were defined from > the lowest bit working up? > > > + > > +#define GICR_TYPER_PLPIS (1U << 0) > > +#define GICR_TYPER_VLPIS (1U << 1) > > +#define GICR_TYPER_LAST (1U << 4) > > Also missing various bits. > > > + > > +#define GICR_WAKER_ProcessorSleep (1U << 1) > > +#define GICR_WAKER_ChildrenAsleep (1U << 2) > > + > > +#define GICR_PROPBASER_OUTER_AsInner (0ULL << 56) > > +#define GICR_PROPBASER_OUTER_nC (1ULL << 56) > > +#define GICR_PROPBASER_OUTER_RaWt (2ULL << 56) > > +#define GICR_PROPBASER_OUTER_RaWb (3ULL << 56) > > +#define GICR_PROPBASER_OUTER_WaWt (4ULL << 56) > > +#define GICR_PROPBASER_OUTER_WaWb (5ULL << 56) > > +#define GICR_PROPBASER_OUTER_RaWaWt (6ULL << 56) > > +#define GICR_PROPBASER_OUTER_RaWaWb (7ULL << 56) > > +#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK (7ULL << 56) > > +#define GICR_PROPBASER_ADDR_MASK (0xfffffffffULL << 12) > > +#define GICR_PROPBASER_NonShareable (0U << 10) > > +#define GICR_PROPBASER_InnerShareable (1U << 10) > > +#define GICR_PROPBASER_OuterShareable (2U << 10) > > +#define GICR_PROPBASER_SHAREABILITY_MASK (3U << 10) > > +#define GICR_PROPBASER_nCnB (0U << 7) > > +#define GICR_PROPBASER_nC (1U << 7) > > +#define GICR_PROPBASER_RaWt (2U << 7) > > +#define GICR_PROPBASER_RaWb (3U << 7) > > +#define GICR_PROPBASER_WaWt (4U << 7) > > +#define GICR_PROPBASER_WaWb (5U << 7) > > +#define GICR_PROPBASER_RaWaWt (6U << 7) > > +#define GICR_PROPBASER_RaWaWb (7U << 7) > > +#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7) > > +#define GICR_PROPBASER_IDBITS_MASK (0x1f) > > Do we really need all the defines for different values in the > InnerCache/OuterCache/Shareability fields, given that QEMU > doesn't model any of these memory attributes at all and so our > GICv3 emulation will just ignore whatever the guest writes here? > (If we do want them it seems better to define constants for the > various field values 0 through 7, plus a constant for the location > of the field, since the fields here and in PENDBASER are all > basically the same encoding.) > > > + > > +#define GICR_PENDBASER_PTZ (1ULL << 62) > > +#define GICR_PENDBASER_OUTER_AsInner (0ULL << 56) > > +#define GICR_PENDBASER_OUTER_nC (1ULL << 56) > > +#define GICR_PENDBASER_OUTER_RaWt (2ULL << 56) > > +#define GICR_PENDBASER_OUTER_RaWb (3ULL << 56) > > +#define GICR_PENDBASER_OUTER_WaWt (4ULL << 56) > > +#define GICR_PENDBASER_OUTER_WaWb (5ULL << 56) > > +#define GICR_PENDBASER_OUTER_RaWaWt (6ULL << 56) > > +#define GICR_PENDBASER_OUTER_RaWaWb (7ULL << 56) > > +#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK (7ULL << 56) > > +#define GICR_PENDBASER_ADDR_MASK (0xffffffffULL << 16) > > +#define GICR_PENDBASER_NonShareable (0U << 10) > > +#define GICR_PENDBASER_InnerShareable (1U << 10) > > +#define GICR_PENDBASER_OuterShareable (2U << 10) > > +#define GICR_PENDBASER_SHAREABILITY_MASK (3U << 10) > > +#define GICR_PENDBASER_nCnB (0U << 7) > > +#define GICR_PENDBASER_nC (1U << 7) > > +#define GICR_PENDBASER_RaWt (2U << 7) > > +#define GICR_PENDBASER_RaWb (3U << 7) > > +#define GICR_PENDBASER_WaWt (4U << 7) > > +#define GICR_PENDBASER_WaWb (5U << 7) > > +#define GICR_PENDBASER_RaWaWt (6U << 7) > > +#define GICR_PENDBASER_RaWaWb (7U << 7) > > +#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7) > > + > > +/* > > + * Simulated system registers > > + */ > > Not sure what "simulated system registers" means here. > > > +#define GICC_CTLR_EN_GRP0_SHIFT 0 > > +#define GICC_CTLR_EN_GRP0 (1U << GICC_CTLR_EN_GRP0_SHIFT) > > +#define GICC_CTLR_EN_GRP1_SHIFT 1 > > +#define GICC_CTLR_EN_GRP1 (1U << GICC_CTLR_EN_GRP1_SHIFT) > > +#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) > > We haven't defined a GICC_CTLR register offset, so why define > the bit fields for it? > > > + > > +#define ICC_CTLR_CBPR (1U << 0) > > +#define ICC_CTLR_EOIMODE (1U << 1) > > +#define ICC_CTLR_PMHE (1U << 6) > > Missing a few fields. > > > + > > +#define ICC_PMR_PRIORITY_MASK 0xff > > +#define ICC_BPR_BINARYPOINT_MASK 0x07 > > +#define ICC_IGRPEN_ENABLE 0x01 > > + > > +#endif /* !QEMU_ARM_GIC_INTERNAL_H */ > > diff --git a/include/hw/intc/arm_gicv3_common.h > b/include/hw/intc/arm_gicv3_common.h > > index c2fd8da..c128622 100644 > > --- a/include/hw/intc/arm_gicv3_common.h > > +++ b/include/hw/intc/arm_gicv3_common.h > > @@ -3,8 +3,9 @@ > > * > > * Copyright (c) 2012 Linaro Limited > > * Copyright (c) 2015 Huawei. > > + * Copyright (c) 2015 Samsung Electronics Co., Ltd. > > * Written by Peter Maydell > > - * Extended to 64 cores by Shlomo Pongratz > > + * Reworked for GICv3 by Shlomo Pongratz and Pavel Fedin > > * > > * 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 > > @@ -26,7 +27,66 @@ > > #include "hw/sysbus.h" > > #include "hw/intc/arm_gic_common.h" > > > > -typedef struct GICv3State { > > +/* > > + * Maximum number of possible interrupts, determined by the GIC > architecture. > > + * Note that this does not include LPIs. When implemented, these should > be > > + * dealt with separately. > > + */ > > +#define GICV3_MAXIRQ 1020 > > +#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL) > > + > > +#define GIC_MIN_BPR0 0 > > +#define GIC_MIN_BPR1 (GIC_MIN_BPR0 + 1) > > + > > +struct GICv3SGISource { > > + /* For each SGI on the target CPU, we store bit mask > > + * 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. > > + */ > > + unsigned long *pending; > > + int32_t size; /* Bitmap size for migration */ > > +}; > > This doesn't look right. There is one GICD_SPENDSGIR* register set > for each CPU, but each CPU has only 8 pending bits per SGI. > (That's because this is only relevant for legacy operation > with affinity-routing disabled, and the limitations on > legacy operation apply.) So you don't need a huge bitmap here. > I would default to modelling this as uint32_t spendsgir[4] > unless there's a good reason to do something else. > > > + > > +typedef struct GICv3SGISource GICv3SGISource; > > + > > +struct GICv3CPUState { > > + uint64_t affinity_id; /* Cached affinity ID of the CPU */ > > + > > + /* Redistributor */ > > + bool cpu_enabled; /* !GICR_WAKER_ProcessorSleep */ > > Why not just have a field for GICR_WAKER, and read the relevant bit > as needed? (I'm assuming we won't in practice implement all the > GICv3 power-down signalling logic anyway.) > > > + uint32_t redist_ctlr; /* GICR_CTLR */ > > If you named all these fields with their architectural names you > wouldn't have to have all these comments... > > > + uint32_t group; /* GICR_IGROUPR0 */ > > + uint32_t enabled; /* GICR_ISENABLER0 */ > > + uint32_t pending; /* GICR_ISPENDR0 */ > > + uint32_t active; /* GICR_ISACTIVER0 */ > > + uint32_t level; /* Current IRQ level */ > > + uint32_t edge_trigger; /* GICR_ICFGR */ > > GICR_ICFGR0 and GICR_ICFGR1 are both 32-bit registers, but we seem > to only have 32 bits of state here. > > > + uint8_t priority[GIC_INTERNAL]; /* GICR_IPRIORITYR */ > > + uint64_t propbaser; > > + uint64_t pendbaser; > > + > > + /* CPU interface */ > > + uint32_t ctlr[2]; /* ICC_CTLR_EL1, banked */ > > + uint32_t priority_mask; /* ICC_PMR_EL1 */ > > + uint32_t bpr[2]; > > + uint32_t apr[4][2]; > > + > > + /* Legacy CPU interface */ > > + uint32_t legacy_ctlr; /* GICC_CTLR */ > > + GICv3SGISource sgi[GIC_NR_SGIS]; /* GIC_SPENDSGIR */ > > + > > + /* Internal state */ > > There should in general be no internal state, unless it is purely > a cached representation of some architecturally visible state > (ie an optimisation for speed). > > > + uint16_t current_pending; > > + uint16_t running_irq; > > + uint16_t running_priority; > > + uint16_t last_active[GICV3_MAXIRQ]; > > This last_active array is definitely wrong, as is running_irq. I > fixed the GICv2 not to try to handle priorities in this way in a > set of commits in September; the GICv3 implementation should work > similarly to how GICv2 does it now. > > running_priority is not internal state, it is ICC_RPR_EL1. > current_pending is not internal state, it is ICC_HPPIR0_EL1 and > ICC_HPPIR1_EL1. > > > +}; > > + > > +typedef struct GICv3CPUState GICv3CPUState; > > + > > +struct GICv3State { > > /*< private >*/ > > SysBusDevice parent_obj; > > /*< public >*/ > > @@ -43,7 +103,28 @@ typedef struct GICv3State { > > bool security_extn; > > > > int dev_fd; /* kvm device fd if backed by kvm vgic support */ > > -} GICv3State; > > + Error *migration_blocker; > > + > > + /* Distributor */ > > + > > + /* 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. > > + */ > > This comment needs updating, because in GICv3 the NS banked version has > more than just one bit (though they are all still aliases of various bits > in the S version). > > > + uint32_t ctlr; /* GICD_CTLR */ > > + DECLARE_BITMAP(group, GICV3_MAXSPI); /* GICD_IGROUPR */ > > + DECLARE_BITMAP(enabled, GICV3_MAXSPI); /* GICD_ISENABLER */ > > + DECLARE_BITMAP(pending, GICV3_MAXSPI); /* GICD_ISPENDR */ > > + DECLARE_BITMAP(active, GICV3_MAXSPI); /* GICD_ISACTIVER */ > > + DECLARE_BITMAP(level, GICV3_MAXSPI); /* Current level */ > > + DECLARE_BITMAP(edge_trigger, GICV3_MAXSPI); /* GICD_ICFGR */ > > GICD_ICFGR has two bits of state per interrupt, not one. > > > + uint8_t priority[GICV3_MAXSPI]; /* GICD_IPRIORITYR */ > > + uint8_t irq_target[GICV3_MAXSPI]; /* GICD_ITARGETSR */ > > + uint64_t irq_route[GICV3_MAXSPI]; /* GICD_IROUTER */ > > + > > + GICv3CPUState *cpu; > > +}; > > + > > +typedef struct GICv3State GICv3State; > > > > #define TYPE_ARM_GICV3_COMMON "arm-gicv3-common" > > #define ARM_GICV3_COMMON(obj) \ > > @@ -65,4 +146,10 @@ typedef struct ARMGICv3CommonClass { > > void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, > > const MemoryRegionOps *ops); > > > > +/* Accessors for simulated system registers */ > > +uint32_t gicv3_get_igrpen0(GICv3State *s, int cpuindex); > > +void gicv3_set_igrpen0(GICv3State *s, int cpuindex, uint32_t val); > > +uint32_t gicv3_get_igrpen1(GICv3State *s, int cpuindex); > > +void gicv3_set_igrpen1(GICv3State *s, int cpuindex, uint32_t val); > > + > > #endif > > -- > > 2.4.4 > > thanks > -- PMM >