On Monday, February 22, 2016, Peter Maydell <peter.mayd...@linaro.org>
wrote:

> From: Pavel Fedin <p.fe...@samsung.com <javascript:;>>
>
> 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.
>
> Signed-off-by: Pavel Fedin <p.fe...@samsung.com <javascript:;>>
> [PMM: significantly overhauled:
>  * Add missing qom/cpu.h include
>  * Remove legacy-only state fields (we can add them later if/when we add
>    legacy emulation)
>  * Add various missing register offset #defines
>  * Accessor macros removed entirely
>  * Fields in state structures renamed to match architectural register names
>  * Corrected the reset value for GICR_IENABLER0 since we don't support
>    legacy mode
>  * Added ARM_LINUX_BOOT_IF interface for "we are directly booting a kernel
> in
>    non-secure" so that we can fake up the firmware-mandated reconfiguration
>    only when we need it
> ]
> Signed-off-by: Peter Maydell <peter.mayd...@linaro.org <javascript:;>>
> ---
>  hw/intc/arm_gicv3_common.c         | 116 ++++++++++++++++++++++++++++-
>  hw/intc/gicv3_internal.h           | 147
> +++++++++++++++++++++++++++++++++++++
>  include/hw/intc/arm_gicv3_common.h | 106 +++++++++++++++++++++++++-
>  3 files changed, 364 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 e4f0f5a..a1ce4c1 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,7 +22,10 @@
>   */
>
>  #include "qemu/osdep.h"
> +#include "qom/cpu.h"
>  #include "hw/intc/arm_gicv3_common.h"
> +#include "gicv3_internal.h"
> +#include "hw/arm/linux-boot-if.h"
>
>  static void gicv3_pre_save(void *opaque)
>  {
> @@ -89,6 +93,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;
> +    int i;
>
>      /* revision property is actually reserved and currently used only in
> order
>       * to keep the interface compatible with GICv2 code, avoiding extra
> @@ -99,11 +105,111 @@ 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_new0(GICv3CPUState, s->num_cpu);
> +
> +    for (i = 0; i < s->num_cpu; i++) {
> +        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);
> +    int i;
> +
> +    for (i = 0; i < s->num_cpu; i++) {
> +        GICv3CPUState *c = &s->cpu[i];
> +
> +        c->gicr_waker = GICR_WAKER_ProcessorSleep |
> GICR_WAKER_ChildrenAsleep;
> +        c->gicr_ctlr = 0;
> +        c->gicr_propbaser = 0;
> +        c->gicr_pendbaser = 0;
> +        /* If we're resetting a TZ-aware GIC as if secure firmware
> +         * had set it up ready to start a kernel in non-secure, we
> +         * need to set interrupts to group 1 so the kernel can use them.
> +         * Otherwise they reset to group 0 like the hardware.
> +         */
> +        if (s->security_extn && s->irq_reset_nonsecure) {
> +            c->gicr_igroupr0 = 0xffffffff;
> +        } else {
> +            c->gicr_igroupr0 = 0;
> +        }
> +
> +        c->gicr_ienabler0 = 0;
> +        c->gicr_ipendr0 = 0;
> +        c->gicr_iactiver0 = 0;
> +        c->gicr_icfgr0 = 0xaaaaaaaa;
> +        c->gicr_icfgr1 = 0;
> +        memset(c->gicr_ipriorityr, 0, sizeof(c->gicr_ipriorityr));
> +        c->level = 0;
> +
> +        c->icc_ctlr_el1[0] = 0;
> +        c->icc_ctlr_el1[1] = 0;
> +        c->icc_igrpen0_el1 = 0;
> +        c->icc_igrpen1_el1 = 0;
> +        c->icc_pmr_el1 = 0;
> +        c->icc_bpr[0] = GIC_MIN_BPR0;
> +        c->icc_bpr[1] = GIC_MIN_BPR1;
> +        memset(c->icc_ap1r, 0, sizeof(c->icc_ap1r));
> +    }
> +
> +    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->gicd_itargetsr[i] = 1;
> +    }
> +    memset(s->gicd_irouter, 0, sizeof(s->gicd_irouter));
> +    memset(s->gicd_ipriority, 0, sizeof(s->gicd_ipriority));
> +
> +    /* 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->gicd_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->gicd_ctlr = GICD_CTLR_DS | GICD_CTLR_ARE;
> +    }
> +}
> +
> +static void arm_gic_common_linux_init(ARMLinuxBootIf *obj,
> +                                      bool secure_boot)
> +{
> +    GICState *s = ARM_GIC_COMMON(obj);
> +
> +    if (s->security_extn && !secure_boot) {
> +        /* We're directly booting a kernel into NonSecure. If this GIC
> +         * implements the security extensions then we must configure it
> +         * to have all the interrupts be NonSecure (this is a job that
> +         * is done by the Secure boot firmware in real hardware, and in
> +         * this mode QEMU is acting as a minimalist
> firmware-and-bootloader
> +         * equivalent).
> +         */
> +        s->irq_reset_nonsecure = true;
> +    }
>  }
>
>  static Property arm_gicv3_common_properties[] = {
> @@ -117,11 +223,13 @@ static Property arm_gicv3_common_properties[] = {
>  static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass);
>
>      dc->reset = arm_gicv3_common_reset;
>      dc->realize = arm_gicv3_common_realize;
>      dc->props = arm_gicv3_common_properties;
>      dc->vmsd = &vmstate_gicv3;
> +    albifc->arm_linux_init = arm_gic_common_linux_init;
>  }
>
>  static const TypeInfo arm_gicv3_common_type = {
> @@ -131,6 +239,10 @@ static const TypeInfo arm_gicv3_common_type = {
>      .class_size = sizeof(ARMGICv3CommonClass),
>      .class_init = arm_gicv3_common_class_init,
>      .abstract = true,
> +    .interfaces = (InterfaceInfo []) {
> +        { TYPE_ARM_LINUX_BOOT_IF },
> +        { },
> +    },
>  };
>
>  static void register_types(void)
> diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
> new file mode 100644
> index 0000000..9f9a45e
> --- /dev/null
> +++ b/hw/intc/gicv3_internal.h
> @@ -0,0 +1,147 @@
> +/*
> + * 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"
> +
> +/* Distributor registers, as offsets from the distributor base address */
> +#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_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_IGRPMODR        0x0D00
> +#define GICD_NASCR           0x0E00
> +#define GICD_SGIR            0x0F00
> +#define GICD_CPENDSGIR       0x0F10
> +#define GICD_SPENDSGIR       0x0F20
> +#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)
> +/* Bit 4 is ARE if the system doesn't support TrustZone, ARE_S otherwise
> */
> +#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_E1NWF             (1U << 7)
> +#define GICD_CTLR_RWP               (1U << 31)
> +
> +/*
> + * Redistributor frame offsets from RD_base
> + */
> +#define GICR_SGI_OFFSET 0x10000
> +
> +/*
> + * Redistributor registers, offsets from RD_base
> + */
> +#define GICR_CTLR             0x0000
> +#define GICR_IIDR             0x0004
> +#define GICR_TYPER            0x0008
> +#define GICR_STATUSR          0x0010
> +#define GICR_WAKER            0x0014
> +#define GICR_SETLPIR          0x0040
> +#define GICR_CLRLPIR          0x0048
> +#define GICR_PROPBASER        0x0070
> +#define GICR_PENDBASER        0x0078
> +#define GICR_INVLPIR          0x00A0
> +#define GICR_INVALLR          0x00B0
> +#define GICR_SYNCR            0x00C0
> +#define GICR_PIDR2            0xFFE8
> +
> +/* SGI and PPI Redistributor registers, offsets from SGI_base */
> +#define GICR_IGROUPR0         0x0080
> +#define GICR_ISENABLER0       0x0100
> +#define GICR_ICENABLER0       0x0180
> +#define GICR_ISPENDR0         0x0200
> +#define GICR_ICPENDR0         0x0280
> +#define GICR_ISACTIVER0       0x0300
> +#define GICR_ICACTIVER0       0x0380
> +#define GICR_IPRIORITYR0      0x0400
> +#define GICR_ICFGR0           0x0C00
> +#define GICR_ICFGR1           0x0C04
> +#define GICR_IGRPMODR0        0x0D00
> +#define GICR_NSACR            0x0E00
> +
> +#define GICR_CTLR_ENABLE_LPIS        (1U << 0)
> +#define GICR_CTLR_RWP                (1U << 3)
> +#define GICR_CTLR_DPG0               (1U << 24)
> +#define GICR_CTLR_DPG1NS             (1U << 25)
> +#define GICR_CTLR_DPG1S              (1U << 26)
> +#define GICR_CTLR_UWP                (1U << 31)
> +
> +#define GICR_TYPER_PLPIS             (1U << 0)
> +#define GICR_TYPER_VLPIS             (1U << 1)
> +#define GICR_TYPER_DIRECTLPI         (1U << 3)
> +#define GICR_TYPER_LAST              (1U << 4)
> +#define GICR_TYPER_DPGS              (1U << 5)
> +#define GICR_TYPER_PROCNUM           (0xFFFFU << 8)
> +#define GICR_TYPER_COMMONLPIAFF      (0x3 << 24)
> +#define GICR_TYPER_AFFINITYVALUE     (0xFFFFFFFFULL << 32)
> +
> +#define GICR_WAKER_ProcessorSleep    (1U << 1)
> +#define GICR_WAKER_ChildrenAsleep    (1U << 2)
> +
> +#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
> +#define GICR_PROPBASER_ADDR_MASK               (0xfffffffffULL << 12)
> +#define GICR_PROPBASER_SHAREABILITY_MASK       (3U << 10)
> +#define GICR_PROPBASER_CACHEABILITY_MASK       (7U << 7)
> +#define GICR_PROPBASER_IDBITS_MASK             (0x1f)
> +
> +#define GICR_PENDBASER_PTZ                     (1ULL << 62)
> +#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
> +#define GICR_PENDBASER_ADDR_MASK               (0xffffffffULL << 16)
> +#define GICR_PENDBASER_SHAREABILITY_MASK       (3U << 10)
> +#define GICR_PENDBASER_CACHEABILITY_MASK       (7U << 7)
> +
> +#define ICC_CTLR_EL1_CBPR           (1U << 0)
> +#define ICC_CTLR_EL1_EOIMODE        (1U << 1)
> +#define ICC_CTLR_EL1_PMHE           (1U << 6)
> +#define ICC_CTLR_EL1_SEIS           (1U << 14)
> +#define ICC_CTLR_EL1_A3V            (1U << 15)
> +
> +#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..84e9406 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,48 @@
>  #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 GICv3CPUState {
> +    uint64_t affinity_id;            /* Cached affinity ID of the CPU */
> +
> +    /* Redistributor */
> +    uint32_t level;                  /* Current IRQ level */
> +    /* RD_base page registers */
> +    uint32_t gicr_ctlr;
> +    uint32_t gicr_waker;
> +    uint64_t gicr_propbaser;
> +    uint64_t gicr_pendbaser;
> +    /* SGI_base page registers */
> +    uint32_t gicr_igroupr0;
> +    uint32_t gicr_ienabler0;
> +    uint32_t gicr_ipendr0;
> +    uint32_t gicr_iactiver0;
> +    uint32_t gicr_icfgr0;
> +    uint32_t gicr_icfgr1;
> +    uint8_t gicr_ipriorityr[GIC_INTERNAL];
> +
> +    /* CPU interface */
> +    uint64_t icc_ctlr_el1[2];
> +    uint64_t icc_pmr_el1;
> +    uint64_t icc_bpr[2];
> +    uint64_t icc_ap1r[4][2];
> +    uint64_t icc_igrpen0_el1;
> +    uint64_t icc_igrpen1_el1;
> +};
> +
> +typedef struct GICv3CPUState GICv3CPUState;
> +
> +struct GICv3State {
>      /*< private >*/
>      SysBusDevice parent_obj;
>      /*< public >*/
> @@ -41,9 +83,61 @@ typedef struct GICv3State {
>      uint32_t num_irq;
>      uint32_t revision;
>      bool security_extn;
> +    bool irq_reset_nonsecure;
>
>      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.
> +     */
> +    uint32_t 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 */
> +    uint8_t gicd_ipriority[GICV3_MAXSPI];
> +    uint8_t gicd_itargetsr[GICV3_MAXSPI];
> +    uint64_t gicd_irouter[GICV3_MAXSPI];
> +
> +    GICv3CPUState *cpu;
> +};
> +
> +typedef struct GICv3State GICv3State;
> +
> +#define GICV3_BITMAP_ACCESSORS(BMP)                                     \
> +    static inline void gicv3_gicd_##BMP##_set(GICv3State *s, int irq)   \
> +    {                                                                   \
> +        set_bit(irq - GIC_INTERNAL, s->BMP);                            \
> +    }                                                                   \
> +    static inline int gicv3_gicd_##BMP##_test(GICv3State *s, int irq)   \
> +    {                                                                   \
> +        return test_bit(irq - GIC_INTERNAL, s->BMP);                    \
> +    }                                                                   \
> +    static inline void gicv3_gicd_##BMP##_clear(GICv3State *s, int irq) \
> +    {                                                                   \
> +        clear_bit(irq - GIC_INTERNAL, s->BMP);                          \
> +    }                                                                   \
> +    static inline void gicv3_gicd_##BMP##_replace(GICv3State *s,        \
> +                                                  int irq, int value)   \
> +    {                                                                   \
> +        if (value) {                                                    \
> +            gicv3_gicd_##BMP##_set(s, irq);                             \
> +        } else {                                                        \
> +            gicv3_gicd_##BMP##_clear(s, irq);                           \
> +        }                                                               \
> +    }
> +
> +GICV3_BITMAP_ACCESSORS(group)
> +GICV3_BITMAP_ACCESSORS(enabled)
> +GICV3_BITMAP_ACCESSORS(pending)
> +GICV3_BITMAP_ACCESSORS(active)
> +GICV3_BITMAP_ACCESSORS(level)
> +GICV3_BITMAP_ACCESSORS(edge_trigger)
>
>  #define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
>  #define ARM_GICV3_COMMON(obj) \
> @@ -65,4 +159,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
> --
> 1.9.1
>
>
Hi,

I just wonder why the internal interrupts are excluded from the new
GICv3State and the new access API don't handle them?
Is it because they aren't required by KVM?
I see that they are only referenced in gicr_ipriority.

What am I missing?

Best regards,

S.P.

Reply via email to