* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
       [not found] <1445396964-21189-1-git-send-email-shlomopongratz@gmail.com>
@ 2015-10-21  6:48 ` Pavel Fedin
       [not found]   ` <CAHzK-V0YsPx8E66fNpJ7C6T=tE-CM-pg2o5vQNpYn1SQ4BeLxg@mail.gmail.com>
  0 siblings, 1 reply; 8+ messages in thread
From: Pavel Fedin @ 2015-10-21  6:48 UTC (permalink / raw)
  To: 'Shlomo Pongratz', qemu-devel
  Cc: peter.maydell, eric.auger, 'Shlomo Pongratz',
	shannon.zhao, ashoks, imammedo
 Hello!
> -----Original Message-----
> From: Shlomo Pongratz [mailto:shlomopongratz@gmail.com]
> Sent: Wednesday, October 21, 2015 6:09 AM
> To: qemu-devel@nongnu.org
> Cc: p.fedin@samsung.com; peter.maydell@linaro.org; eric.auger@linaro.org;
> shannon.zhao@linaro.org; imammedo@redhat.com; ashoks@broadcom.com; Shlomo Pongratz
> Subject: [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
> 
> From: Shlomo Pongratz <shlomo.pongratz@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.pongratz@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
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
       [not found]   ` <CAHzK-V0YsPx8E66fNpJ7C6T=tE-CM-pg2o5vQNpYn1SQ4BeLxg@mail.gmail.com>
@ 2015-10-21 10:48     ` Pavel Fedin
  2015-10-21 11:38       ` Shlomo Pongratz
  0 siblings, 1 reply; 8+ messages in thread
From: Pavel Fedin @ 2015-10-21 10:48 UTC (permalink / raw)
  To: 'Shlomo Pongratz'
  Cc: peter.maydell, eric.auger, 'Shlomo Pongratz', qemu-devel,
	shannon.zhao, ashoks, imammedo
 Hello!
> I can't find the patch that handles the for example modification of "uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU]" to fixed-size bitmaps. as
> GIC_NCPU is not a constant and uint8_t need to have the size of nubmer of CPUs which is no longer bounded.
 This is the only thing which i excluded, because my vGIC implementation didn't need these flags. I know that you cannot actually omit them in software emulation, because they are needed in order to handle a situation where more than one CPU sends the same SGI number.
 I think you can place it in distributor, in "internal state" section, if you look at my patch.
> Are you sure that the semantics is the same? In section 4.1.4 of GICv3 I see that the security level is a combination of two registers GRPMOD > and GROUP and I wanted to be prepared for it.
 Looks like you have some private NDA version of the manual, because my one (downloaded from infocenter) doesn't have a paragraph numbered 4.1.4. Anyway, after reading my one, i think that GRPMOD simply overrides what is specified in GROUP. I cannot find such thing as "group 2" anywhere, and all the text starts with "In a GIC which supports two security states". So, there's only non-secure and secure state, nothing else.
 Again, nothing changes since ARM32.
> I assume you want to distinguish between Secure EL1 and Secure EL3 (in the future).
 As far as i understand, EL3 is what was called "monitor" in ARM32, and i would still prefer to call it this way, because it is more meaningful than those stupid (IMHO) numbers. The only special thing about this mode is that it allows you to freely switch between secure and non-secure states. So, again, there's nothing special about "secure EL3".
 Peter, please correct me if i'm wrong.
> I don't have access to the internal CPU's data structures in the GIC's core, its an opaque structure to the GIC.
> Including the CPU include files doesn't seems to work.
 See this: http://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg02349.html. This is also a part of my live migration RFC.
 I remember that Peter told long time ago that "it should really be a property", when i integrated full affinity support. But, he currently refused to accept this small standalone patch because there are no users for now. My GICv3 live migration is waiting for kernel API to be ready. And kernel API is waiting for kernel 4.5 development cycle to begin.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
  2015-10-21 10:48     ` Pavel Fedin
@ 2015-10-21 11:38       ` Shlomo Pongratz
  2015-10-21 12:32         ` Pavel Fedin
  0 siblings, 1 reply; 8+ messages in thread
From: Shlomo Pongratz @ 2015-10-21 11:38 UTC (permalink / raw)
  To: Pavel Fedin
  Cc: peter.maydell@linaro.org, eric.auger@linaro.org, Shlomo Pongratz,
	qemu-devel@nongnu.org, shannon.zhao@linaro.org,
	ashoks@broadcom.com, imammedo@redhat.com
[-- Attachment #1: Type: text/plain, Size: 2986 bytes --]
See inline.
On Wednesday, October 21, 2015, Pavel Fedin <p.fedin@samsung.com> wrote:
>  Hello!
>
> > I can't find the patch that handles the for example modification of
> "uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU]" to fixed-size bitmaps. as
> > GIC_NCPU is not a constant and uint8_t need to have the size of nubmer
> of CPUs which is no longer bounded.
>
>  This is the only thing which i excluded, because my vGIC implementation
> didn't need these flags. I know that you cannot actually omit them in
> software emulation, because they are needed in order to handle a situation
> where more than one CPU sends the same SGI number.
>  I think you can place it in distributor, in "internal state" section, if
> you look at my patch.
>
> I'll modify the reset along your suggestion.
> > Are you sure that the semantics is the same? In section 4.1.4 of GICv3 I
> see that the security level is a combination of two registers GRPMOD > and
> GROUP and I wanted to be prepared for it.
>
>  Looks like you have some private NDA version of the manual, because my
> one (downloaded from infocenter) doesn't have a paragraph numbered 4.1.4.
> Anyway, after reading my one, i think that GRPMOD simply overrides what is
> specified in GROUP. I cannot find such thing as "group 2" anywhere, and all
> the text starts with "In a GIC which supports two security states". So,
> there's only non-secure and secure state, nothing else.
>  Again, nothing changes since ARM32.
>
>
I'll re-examine the document and see if this is relevant.
> I assume you want to distinguish between Secure EL1 and Secure EL3 (in
> the future).
>
>  As far as i understand, EL3 is what was called "monitor" in ARM32, and i
> would still prefer to call it this way, because it is more meaningful than
> those stupid (IMHO) numbers. The only special thing about this mode is that
> it allows you to freely switch between secure and non-secure states. So,
> again, there's nothing special about "secure EL3".
>
>  Peter, please correct me if i'm wrong.
>
> > I don't have access to the internal CPU's data structures in the GIC's
> core, its an opaque structure to the GIC.
> > Including the CPU include files doesn't seems to work.
>
>  See this:
> http://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg02349.html.
> This is also a part of my live migration RFC.
>  I remember that Peter told long time ago that "it should really be a
> property", when i integrated full affinity support. But, he currently
> refused to accept this small standalone patch because there are no users
> for now. My GICv3 live migration is waiting for kernel API to be ready. And
> kernel API is waiting for kernel 4.5 development cycle to begin.
>
> So please resubmit it and mention me as a client.
But I wonder if accessing the property in real time (not in only in
initialization) from the GIC code will have impact on performance.
Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
>
>
>
[-- Attachment #2: Type: text/html, Size: 3896 bytes --]
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
  2015-10-21 11:38       ` Shlomo Pongratz
@ 2015-10-21 12:32         ` Pavel Fedin
  2015-10-21 13:12           ` Shlomo Pongratz
  0 siblings, 1 reply; 8+ messages in thread
From: Pavel Fedin @ 2015-10-21 12:32 UTC (permalink / raw)
  To: 'Shlomo Pongratz'
  Cc: peter.maydell, eric.auger, 'Shlomo Pongratz', qemu-devel,
	shannon.zhao, ashoks, imammedo
 Hello!
>> See this: http://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg02349.html. This is also a part of my live migration RFC.
>> I remember that Peter told long time ago that "it should really be a property", when i integrated full affinity support. But, he currently
>> refused to accept this small standalone patch because there are no users for now. My GICv3 live migration is waiting for kernel API to be
>> ready. And kernel API is waiting for kernel 4.5 development cycle to begin.
> So please resubmit it and mention me as a client.
 Ok, i'll PING, but you can also include it into your patchset. BTW, why is it still RFC?
> But I wonder if accessing the property in real time (not in only in initialization) from the GIC code will have impact on performance.
 It can, but you can cache them during realize. For example, if you accept my data layout, then you can just add "uint64_t mp_affinity" to GICv3CPUState.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
  2015-10-21 12:32         ` Pavel Fedin
@ 2015-10-21 13:12           ` Shlomo Pongratz
  2015-10-21 13:39             ` Pavel Fedin
  0 siblings, 1 reply; 8+ messages in thread
From: Shlomo Pongratz @ 2015-10-21 13:12 UTC (permalink / raw)
  To: Pavel Fedin
  Cc: peter.maydell@linaro.org, eric.auger@linaro.org, Shlomo Pongratz,
	qemu-devel@nongnu.org, shannon.zhao@linaro.org,
	ashoks@broadcom.com, imammedo@redhat.com
[-- Attachment #1: Type: text/plain, Size: 1460 bytes --]
See inline
On Wednesday, October 21, 2015, Pavel Fedin <p.fedin@samsung.com> wrote:
>  Hello!
>
> >> See this:
> http://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg02349.html.
> This is also a part of my live migration RFC.
> >> I remember that Peter told long time ago that "it should really be a
> property", when i integrated full affinity support. But, he currently
> >> refused to accept this small standalone patch because there are no
> users for now. My GICv3 live migration is waiting for kernel API to be
> >> ready. And kernel API is waiting for kernel 4.5 development cycle to
> begin.
> > So please resubmit it and mention me as a client.
>
>  Ok, i'll PING, but you can also include it into your patchset. BTW, why
> is it still RFC?
>
It is still in RFC because there are still many comments as you can see :-)
>
> > But I wonder if accessing the property in real time (not in only in
> initialization) from the GIC code will have impact on performance.
>
>  It can, but you can cache them during realize. For example, if you accept
> my data layout, then you can just add "uint64_t mp_affinity" to
> GICv3CPUState.
>
>
Do you mean that in virt.c::create_gic I'll take the cpu's affinity from
the cpu's property and not directly from
ARM_CPU(qemu_get_cpu(i))->mp_affinity
I can do that but that depends on acceptance of your patch.
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
>
>
>
[-- Attachment #2: Type: text/html, Size: 2146 bytes --]
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
  2015-10-21 13:12           ` Shlomo Pongratz
@ 2015-10-21 13:39             ` Pavel Fedin
  2015-10-21 13:58               ` Shlomo Pongratz
  0 siblings, 1 reply; 8+ messages in thread
From: Pavel Fedin @ 2015-10-21 13:39 UTC (permalink / raw)
  To: 'Shlomo Pongratz'
  Cc: peter.maydell, eric.auger, 'Shlomo Pongratz', qemu-devel,
	shannon.zhao, ashoks, imammedo
 Hello!
> Do you mean that in virt.c::create_gic I'll take the cpu's affinity from the cpu's property and not directly from
> ARM_CPU(qemu_get_cpu(i))->mp_affinity
 I mean that you can do it in your GIC's realize function. And, even better, in arm_gicv3_common_realize(), because KVM GICv3 live migration code will also need it:
--- cut ---
for (i = 0; i < s->num_cpu; i++) {
    Object *cpu = OBJECT(qemu_get_cpu(i));
    s->cpu[i].mp_affinity = object_property_get_int(cpu, "mp-affinity", NULL);
}
--- cut ---
> I can do that but that depends on acceptance of your patch.
 Peter ACKed it, just he doesn't like having unused code: http://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg03105.html
 Just include it into your next respin and forget. :) Actually, i made my RFC so that you could just take 0001 and 0002 from it and use for your purpose. With additions, of course, if necessary.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
  2015-10-21 13:39             ` Pavel Fedin
@ 2015-10-21 13:58               ` Shlomo Pongratz
  0 siblings, 0 replies; 8+ messages in thread
From: Shlomo Pongratz @ 2015-10-21 13:58 UTC (permalink / raw)
  To: Pavel Fedin
  Cc: peter.maydell@linaro.org, eric.auger@linaro.org, Shlomo Pongratz,
	qemu-devel@nongnu.org, shannon.zhao@linaro.org,
	ashoks@broadcom.com, imammedo@redhat.com
[-- Attachment #1: Type: text/plain, Size: 1126 bytes --]
O.K.
On Wednesday, October 21, 2015, Pavel Fedin <p.fedin@samsung.com> wrote:
>  Hello!
>
> > Do you mean that in virt.c::create_gic I'll take the cpu's affinity from
> the cpu's property and not directly from
> > ARM_CPU(qemu_get_cpu(i))->mp_affinity
>
>  I mean that you can do it in your GIC's realize function. And, even
> better, in arm_gicv3_common_realize(), because KVM GICv3 live migration
> code will also need it:
> --- cut ---
> for (i = 0; i < s->num_cpu; i++) {
>     Object *cpu = OBJECT(qemu_get_cpu(i));
>     s->cpu[i].mp_affinity = object_property_get_int(cpu, "mp-affinity",
> NULL);
> }
> --- cut ---
>
> > I can do that but that depends on acceptance of your patch.
>
>  Peter ACKed it, just he doesn't like having unused code:
> http://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg03105.html
>  Just include it into your next respin and forget. :) Actually, i made my
> RFC so that you could just take 0001 and 0002 from it and use for your
> purpose. With additions, of course, if necessary.
>
> Kind regards,
> Pavel Fedin
> Expert Engineer
> Samsung Electronics Research center Russia
>
>
>
[-- Attachment #2: Type: text/html, Size: 1520 bytes --]
^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
       [not found] ` <1445361732-16257-2-git-send-email-shlomopongratz@gmail.com>
@ 2015-10-22 11:53   ` Pavel Fedin
  0 siblings, 0 replies; 8+ messages in thread
From: Pavel Fedin @ 2015-10-22 11:53 UTC (permalink / raw)
  To: 'Shlomo Pongratz', qemu-devel
  Cc: peter.maydell, eric.auger, 'Shlomo Pongratz',
	shannon.zhao, ashoks, imammedo
 Hello!
 Some more notes after more careful reviewing. Actually, i am working on v3 of live migration RFC, i will include some macros which
will help you to integrate better.
> -----Original Message-----
> From: Shlomo Pongratz [mailto:shlomopongratz@gmail.com]
> Sent: Tuesday, October 20, 2015 8:22 PM
> To: qemu-devel@nongnu.org
> Cc: p.fedin@samsung.com; peter.maydell@linaro.org; eric.auger@linaro.org;
> shannon.zhao@linaro.org; imammedo@redhat.com; ashoks@broadcom.com; Shlomo Pongratz
> Subject: [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files
> 
> From: Shlomo Pongratz <shlomo.pongratz@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.pongratz@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()
> +    }
>  };
> 
>  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;
>      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),
> +    DEFINE_PROP_ARRAY("mp-affinity", GICv3State, num_mp_affinity, mp_affinity,
> +                      qdev_prop_uint64, uint64_t),
>      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)
 Does it really worth that? IMHO it only pollutes the code and makes it less readable. If you ever want to compare this with GICv2
code, you should just know that there's no GICV3_BASE_IRQ. Actually, IIRC, it's not even GIC, but NVIC artifact.
> +
> +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)
 I know that GICv2 implements them this way. Not sure that it's correct, though. GICR_ICFGR description in the doc says:
--- cut ---
Configurations
A copy of this register is provided for each Redistributor.
--- cut ---
 So, i assume that these are per-CPU too, despite it really doesn't make sense to have different configs on different CPUs.
 My RFC implements per-CPU registers for SGI/PPIs.
> +#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
 Does this make any sense? Value 3 is self-sufficient here, because it's just 3. This reads like "#define NUM_3 3". Isn't it
ridiculous?
> +
> +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
 These three are not used anywhere.
> +
> +/*
> + * 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)
 Actually, these are defined in target-arm/cpu-qom.h. Looks like it was my fault and they have to be moved to something like
include/hw/cpu/cpu_arm.h. I'll post some patches to move them, but not sure that Peter accepts them, just because "there are no
users for this yet".
> +
> +#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
^ permalink raw reply	[flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-10-22 11:53 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1445396964-21189-1-git-send-email-shlomopongratz@gmail.com>
2015-10-21  6:48 ` [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files Pavel Fedin
     [not found]   ` <CAHzK-V0YsPx8E66fNpJ7C6T=tE-CM-pg2o5vQNpYn1SQ4BeLxg@mail.gmail.com>
2015-10-21 10:48     ` Pavel Fedin
2015-10-21 11:38       ` Shlomo Pongratz
2015-10-21 12:32         ` Pavel Fedin
2015-10-21 13:12           ` Shlomo Pongratz
2015-10-21 13:39             ` Pavel Fedin
2015-10-21 13:58               ` Shlomo Pongratz
2015-10-20 17:22 [Qemu-devel] [PATCH RFC V5 0/9] Implement GIC-500 from GICv3 family for arm64 Shlomo Pongratz
     [not found] ` <1445361732-16257-2-git-send-email-shlomopongratz@gmail.com>
2015-10-22 11:53   ` [Qemu-devel] [PATCH RFC V5 1/9] hw/intc: Implement GIC-500 support files Pavel Fedin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).