/*
 * ARM GICv3 emulation: Distributor
 *
 * Copyright (c) 2015 Huawei.
 * Copyright (c) 2016 Linaro Limited.
 * Written by Shlomo Pongratz, Peter Maydell
 *
 * This code is licensed under the GPL, version 2 or (at your option)
 * any later version.
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "trace.h"
#include "gicv3_internal.h"

/* The GICD_NSACR registers contain a two bit field for each interrupt which
 * allows the guest to give NonSecure code access to registers controlling
 * Secure interrupts:
 *  0b00: no access (NS accesses to bits for Secure interrupts will RAZ/WI)
 *  0b01: NS r/w accesses permitted to ISPENDR, SETSPI_NSR, SGIR
 *  0b10: as 0b01, and also r/w to ICPENDR, r/o to ISACTIVER/ICACTIVER,
 *        and w/o to CLRSPI_NSR
 *  0b11: as 0b10, and also r/w to IROUTER and ITARGETSR
 *
 * Given a (multiple-of-32) interrupt number, these mask functions return
 * a mask word where each bit is 1 if the NSACR settings permit access
 * to the interrupt. The mask returned can then be ORed with the GICD_GROUP
 * word for this set of interrupts to give an overall mask.
 */

typedef uint32_t maskfn(GICv3State *s, int irq);

static uint32_t mask_nsacr_ge1(GICv3State *s, int irq)
{
    /* Return a mask where each bit is set if the NSACR field is >= 1 */
    uint64_t raw_nsacr = s->gicd_nsacr[irq / 16 + 1];

    raw_nsacr = raw_nsacr << 32 | s->gicd_nsacr[irq / 16];
    raw_nsacr = (raw_nsacr >> 1) | raw_nsacr;
    return half_unshuffle64(raw_nsacr);
}

static uint32_t mask_nsacr_ge2(GICv3State *s, int irq)
{
    /* Return a mask where each bit is set if the NSACR field is >= 2 */
    uint64_t raw_nsacr = s->gicd_nsacr[irq / 16 + 1];

    raw_nsacr = raw_nsacr << 32 | s->gicd_nsacr[irq / 16];
    raw_nsacr = raw_nsacr >> 1;
    return half_unshuffle64(raw_nsacr);
}

/* We don't need a mask_nsacr_ge3() because IROUTER<n> isn't a bitmap register,
 * but it would be implemented using:
 *  raw_nsacr = (raw_nsacr >> 1) & raw_nsacr;
 */

static uint32_t mask_group_and_nsacr(GICv3State *s, MemTxAttrs attrs,
                                     maskfn *maskfn, int irq)
{
    /* Return a 32-bit mask which should be applied for this set of 32
     * interrupts; each bit is 1 if access is permitted by the
     * combination of attrs.secure, GICD_GROUPR and GICD_NSACR.
     */
    uint32_t mask;

    if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
        /* bits for Group 0 or Secure Group 1 interrupts are RAZ/WI
         * unless the NSACR bits permit access.
         */
        mask = *gic_bmp_ptr32(s->group, irq);
        if (maskfn) {
            mask |= maskfn(s, irq);
        }
        return mask;
    }
    return 0xFFFFFFFFU;
}

static int gicd_ns_access(GICv3State *s, int irq)
{
    /* Return the 2 bit NS_access<x> field from GICD_NSACR<n> for the
     * specified interrupt.
     */
    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return 0;
    }
    return extract32(s->gicd_nsacr[irq / 16], (irq % 16) * 2, 2);
}

static void gicd_write_set_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
                                      uint32_t *bmp,
                                      maskfn *maskfn,
                                      int offset, uint32_t val)
{
    /* Helper routine to implement writing to a "set-bitmap" register
     * (GICD_ISENABLER, GICD_ISPENDR, etc).
     * Semantics implemented here:
     * RAZ/WI for SGIs, PPIs, unimplemented IRQs
     * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
     * Writing 1 means "set bit in bitmap"; writing 0 is ignored.
     * offset should be the offset in bytes of the register from the start
     * of its group.
     */
    int irq = offset * 8;

    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return;
    }
    val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
    *gic_bmp_ptr32(bmp, irq) |= val;
    gicv3_update(s, irq, 32);
}

static void gicd_write_clear_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
                                        uint32_t *bmp,
                                        maskfn *maskfn,
                                        int offset, uint32_t val)
{
    /* Helper routine to implement writing to a "clear-bitmap" register
     * (GICD_ICENABLER, GICD_ICPENDR, etc).
     * Semantics implemented here:
     * RAZ/WI for SGIs, PPIs, unimplemented IRQs
     * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
     * Writing 1 means "clear bit in bitmap"; writing 0 is ignored.
     * offset should be the offset in bytes of the register from the start
     * of its group.
     */
    int irq = offset * 8;

    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return;
    }
    val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
    *gic_bmp_ptr32(bmp, irq) &= ~val;
    gicv3_update(s, irq, 32);
}

static uint32_t gicd_read_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
                                     uint32_t *bmp,
                                     maskfn *maskfn,
                                     int offset)
{
    /* Helper routine to implement reading a "set/clear-bitmap" register
     * (GICD_ICENABLER, GICD_ISENABLER, GICD_ICPENDR, etc).
     * Semantics implemented here:
     * RAZ/WI for SGIs, PPIs, unimplemented IRQs
     * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
     * offset should be the offset in bytes of the register from the start
     * of its group.
     */
    int irq = offset * 8;
    uint32_t val;

    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return 0;
    }
    val = *gic_bmp_ptr32(bmp, irq);
    if (bmp == s->pending) {
        /* The PENDING register is a special case -- for level triggered
         * interrupts, the PENDING state is the logical OR of the state of
         * the PENDING latch with the input line level.
         */
        uint32_t edge = *gic_bmp_ptr32(s->edge_trigger, irq);
        uint32_t level = *gic_bmp_ptr32(s->level, irq);
        val |= (~edge & level);
    }
    val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
    return val;
}

static uint8_t gicd_read_ipriorityr(GICv3State *s, MemTxAttrs attrs, int irq)
{
    /* Read the value of GICD_IPRIORITYR<n> for the specified interrupt,
     * honouring security state (these are RAZ/WI for Group 0 or Secure
     * Group 1 interrupts).
     */
    uint32_t prio;

    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return 0;
    }

    prio = s->gicd_ipriority[irq];

    if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
        if (!gicv3_gicd_group_test(s, irq)) {
            /* Fields for Group 0 or Secure Group 1 interrupts are RAZ/WI */
            return 0;
        }
        /* NS view of the interrupt priority */
        prio = (prio << 1) & 0xff;
    }
    return prio;
}

static void gicd_write_ipriorityr(GICv3State *s, MemTxAttrs attrs, int irq,
                                  uint8_t value)
{
    /* Write the value of GICD_IPRIORITYR<n> for the specified interrupt,
     * honouring security state (these are RAZ/WI for Group 0 or Secure
     * Group 1 interrupts).
     */
    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return;
    }

    if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
        if (!gicv3_gicd_group_test(s, irq)) {
            /* Fields for Group 0 or Secure Group 1 interrupts are RAZ/WI */
            return;
        }
        /* NS view of the interrupt priority */
        value = 0x80 | (value >> 1);
    }
    s->gicd_ipriority[irq] = value;
}

static uint64_t gicd_read_irouter(GICv3State *s, MemTxAttrs attrs, int irq)
{
    /* Read the value of GICD_IROUTER<n> for the specified interrupt,
     * honouring security state.
     */
    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return 0;
    }

    if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
        /* RAZ/WI for NS accesses to secure interrupts */
        if (!gicv3_gicd_group_test(s, irq)) {
            if (gicd_ns_access(s, irq) != 3) {
                return 0;
            }
        }
    }

    return s->gicd_irouter[irq];
}

static void gicd_write_irouter(GICv3State *s, MemTxAttrs attrs, int irq,
                               uint64_t val)
{
    /* Write the value of GICD_IROUTER<n> for the specified interrupt,
     * honouring security state.
     */
    if (irq < GIC_INTERNAL || irq >= s->num_irq) {
        return;
    }

    if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
        /* RAZ/WI for NS accesses to secure interrupts */
        if (!gicv3_gicd_group_test(s, irq)) {
            if (gicd_ns_access(s, irq) != 3) {
                return;
            }
        }
    }

    s->gicd_irouter[irq] = val;
    gicv3_cache_target_cpustate(s, irq);
    gicv3_update(s, irq, 1);
}

/**
 * gicd_readb
 * gicd_readw
 * gicd_readl
 * gicd_readq
 * gicd_writeb
 * gicd_writew
 * gicd_writel
 * gicd_writeq
 *
 * Return %true if the operation succeeded, %false otherwise.
 */

static bool gicd_readb(GICv3State *s, hwaddr offset,
                       uint64_t *data, MemTxAttrs attrs)
{
    /* Most GICv3 distributor registers do not support byte accesses. */
    switch (offset) {
    case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
    case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
    case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
        /* This GIC implementation always has affinity routing enabled,
         * so these registers are all RAZ/WI.
         */
        return true;
    case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
        *data = gicd_read_ipriorityr(s, attrs, offset - GICD_IPRIORITYR);
        return true;
    default:
        return false;
    }
}

static bool gicd_writeb(GICv3State *s, hwaddr offset,
                        uint64_t value, MemTxAttrs attrs)
{
    /* Most GICv3 distributor registers do not support byte accesses. */
    switch (offset) {
    case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
    case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
    case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
        /* This GIC implementation always has affinity routing enabled,
         * so these registers are all RAZ/WI.
         */
        return true;
    case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
    {
        int irq = offset - GICD_IPRIORITYR;

        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            return true;
        }
        gicd_write_ipriorityr(s, attrs, irq, value);
        gicv3_update(s, irq, 1);
        return true;
    }
    default:
        return false;
    }
}

static bool gicd_readw(GICv3State *s, hwaddr offset,
                       uint64_t *data, MemTxAttrs attrs)
{
    /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR
     * support 16 bit accesses, and those registers are all part of the
     * optional message-based SPI feature which this GIC does not currently
     * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are
     * reserved.
     */
    return false;
}

static bool gicd_writew(GICv3State *s, hwaddr offset,
                        uint64_t value, MemTxAttrs attrs)
{
    /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR
     * support 16 bit accesses, and those registers are all part of the
     * optional message-based SPI feature which this GIC does not currently
     * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are
     * reserved.
     */
    return false;
}

static bool gicd_readl(GICv3State *s, hwaddr offset,
                       uint64_t *data, MemTxAttrs attrs)
{
    /* Almost all GICv3 distributor registers are 32-bit.
     * Note that WO registers must return an UNKNOWN value on reads,
     * not an abort.
     */

    switch (offset) {
    case GICD_CTLR:
        if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
            /* The NS view of the GICD_CTLR sees only certain bits:
             * + bit [31] (RWP) is an alias of the Secure bit [31]
             * + bit [4] (ARE_NS) is an alias of Secure bit [5]
             * + bit [1] (EnableGrp1A) is an alias of Secure bit [1] if
             *   NS affinity routing is enabled, otherwise RES0
             * + bit [0] (EnableGrp1) is an alias of Secure bit [1] if
             *   NS affinity routing is not enabled, otherwise RES0
             * Since for QEMU affinity routing is always enabled
             * for both S and NS this means that bits [4] and [5] are
             * both always 1, and we can simply make the NS view
             * be bits 31, 4 and 1 of the S view.
             */
            *data = s->gicd_ctlr & (GICD_CTLR_ARE_S |
                                    GICD_CTLR_EN_GRP1NS |
                                    GICD_CTLR_RWP);
        } else {
            *data = s->gicd_ctlr;
        }
        return true;
    case GICD_TYPER:
    {
        /* For this implementation:
         * No1N == 1 (1-of-N SPI interrupts not supported)
         * A3V == 1 (non-zero values of Affinity level 3 supported)
         * IDbits == 0xf (we support 16-bit interrupt identifiers)
         * DVIS == 0 (Direct virtual LPI injection not supported)
         * LPIS == 1 (LPIs are supported if affinity routing is enabled)
         * num_LPIs == 0b00000 (bits [15:11],Number of LPIs as indicated
         *                      by GICD_TYPER.IDbits)
         * MBIS == 0 (message-based SPIs not supported)
         * SecurityExtn == 1 if security extns supported
         * CPUNumber == 0 since for us ARE is always 1
         * ITLinesNumber == (num external irqs / 32) - 1
         */
        int itlinesnumber = ((s->num_irq - GIC_INTERNAL) / 32) - 1;
        /*
         * SecurityExtn must be RAZ if GICD_CTLR.DS == 1, and
         * "security extensions not supported" always implies DS == 1,
         * so we only need to check the DS bit.
         */
        bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);

        *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
            (s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
            (0xf << 19) | itlinesnumber;
        return true;
    }
    case GICD_IIDR:
        /* We claim to be an ARM r0p0 with a zero ProductID.
         * This is the same as an r0p0 GIC-500.
         */
        *data = gicv3_iidr();
        return true;
    case GICD_STATUSR:
        /* RAZ/WI for us (this is an optional register and our implementation
         * does not track RO/WO/reserved violations to report them to the guest)
         */
        *data = 0;
        return true;
    case GICD_IGROUPR ... GICD_IGROUPR + 0x7f:
    {
        int irq;

        if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
            *data = 0;
            return true;
        }
        /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
        irq = (offset - GICD_IGROUPR) * 8;
        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            *data = 0;
            return true;
        }
        *data = *gic_bmp_ptr32(s->group, irq);
        return true;
    }
    case GICD_ISENABLER ... GICD_ISENABLER + 0x7f:
        *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL,
                                     offset - GICD_ISENABLER);
        return true;
    case GICD_ICENABLER ... GICD_ICENABLER + 0x7f:
        *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL,
                                     offset - GICD_ICENABLER);
        return true;
    case GICD_ISPENDR ... GICD_ISPENDR + 0x7f:
        *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1,
                                     offset - GICD_ISPENDR);
        return true;
    case GICD_ICPENDR ... GICD_ICPENDR + 0x7f:
        *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2,
                                     offset - GICD_ICPENDR);
        return true;
    case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f:
        *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2,
                                     offset - GICD_ISACTIVER);
        return true;
    case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f:
        *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2,
                                     offset - GICD_ICACTIVER);
        return true;
    case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
    {
        int i, irq = offset - GICD_IPRIORITYR;
        uint32_t value = 0;

        for (i = irq + 3; i >= irq; i--) {
            value <<= 8;
            value |= gicd_read_ipriorityr(s, attrs, i);
        }
        *data = value;
        return true;
    }
    case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
        /* RAZ/WI since affinity routing is always enabled */
        *data = 0;
        return true;
    case GICD_ICFGR ... GICD_ICFGR + 0xff:
    {
        /* Here only the even bits are used; odd bits are RES0 */
        int irq = (offset - GICD_ICFGR) * 4;
        uint32_t value = 0;

        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            *data = 0;
            return true;
        }

        /* Since our edge_trigger bitmap is one bit per irq, we only need
         * half of the 32-bit word, which we can then spread out
         * into the odd bits.
         */
        value = *gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f);
        value &= mask_group_and_nsacr(s, attrs, NULL, irq & ~0x1f);
        value = extract32(value, (irq & 0x1f) ? 16 : 0, 16);
        value = half_shuffle32(value) << 1;
        *data = value;
        return true;
    }
    case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff:
    {
        int irq;

        if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
            /* RAZ/WI if security disabled, or if
             * security enabled and this is an NS access
             */
            *data = 0;
            return true;
        }
        /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
        irq = (offset - GICD_IGRPMODR) * 8;
        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            *data = 0;
            return true;
        }
        *data = *gic_bmp_ptr32(s->grpmod, irq);
        return true;
    }
    case GICD_NSACR ... GICD_NSACR + 0xff:
    {
        /* Two bits per interrupt */
        int irq = (offset - GICD_NSACR) * 4;

        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            *data = 0;
            return true;
        }

        if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
            /* RAZ/WI if security disabled, or if
             * security enabled and this is an NS access
             */
            *data = 0;
            return true;
        }

        *data = s->gicd_nsacr[irq / 16];
        return true;
    }
    case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
    case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
        /* RAZ/WI since affinity routing is always enabled */
        *data = 0;
        return true;
    case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
    {
        uint64_t r;
        int irq = (offset - GICD_IROUTER) / 8;

        r = gicd_read_irouter(s, attrs, irq);
        if (offset & 7) {
            *data = r >> 32;
        } else {
            *data = (uint32_t)r;
        }
        return true;
    }
    case GICD_IDREGS ... GICD_IDREGS + 0x2f:
        /* ID registers */
        *data = gicv3_idreg(offset - GICD_IDREGS);
        return true;
    case GICD_SGIR:
        /* WO registers, return unknown value */
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: invalid guest read from WO register at offset "
                      TARGET_FMT_plx "\n", __func__, offset);
        *data = 0;
        return true;
    default:
        return false;
    }
}

static bool gicd_writel(GICv3State *s, hwaddr offset,
                        uint64_t value, MemTxAttrs attrs)
{
    /* Almost all GICv3 distributor registers are 32-bit. Note that
     * RO registers must ignore writes, not abort.
     */

    switch (offset) {
    case GICD_CTLR:
    {
        uint32_t mask;
        /* GICv3 5.3.20 */
        if (s->gicd_ctlr & GICD_CTLR_DS) {
            /* With only one security state, E1NWF is RAZ/WI, DS is RAO/WI,
             * ARE is RAO/WI (affinity routing always on), and only
             * bits 0 and 1 (group enables) are writable.
             */
            mask = GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1NS;
        } else {
            if (attrs.secure) {
                /* for secure access:
                 * ARE_NS and ARE_S are RAO/WI (affinity routing always on)
                 * E1NWF is RAZ/WI (we don't support enable-1-of-n-wakeup)
                 *
                 * We can only modify bits[2:0] (the group enables).
                 */
                mask = GICD_CTLR_DS | GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1_ALL;
            } else {
                /* For non secure access ARE_NS is RAO/WI and EnableGrp1
                 * is RES0. The only writable bit is [1] (EnableGrp1A), which
                 * is an alias of the Secure bit [1].
                 */
                mask = GICD_CTLR_EN_GRP1NS;
            }
        }
        s->gicd_ctlr = (s->gicd_ctlr & ~mask) | (value & mask);
        if (value & mask & GICD_CTLR_DS) {
            /* We just set DS, so the ARE_NS and EnG1S bits are now RES0.
             * Note that this is a one-way transition because if DS is set
             * then it's not writeable, so it can only go back to 0 with a
             * hardware reset.
             */
            s->gicd_ctlr &= ~(GICD_CTLR_EN_GRP1S | GICD_CTLR_ARE_NS);
        }
        gicv3_full_update(s);
        return true;
    }
    case GICD_STATUSR:
        /* RAZ/WI for our implementation */
        return true;
    case GICD_IGROUPR ... GICD_IGROUPR + 0x7f:
    {
        int irq;

        if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
            return true;
        }
        /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
        irq = (offset - GICD_IGROUPR) * 8;
        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            return true;
        }
        *gic_bmp_ptr32(s->group, irq) = value;
        gicv3_update(s, irq, 32);
        return true;
    }
    case GICD_ISENABLER ... GICD_ISENABLER + 0x7f:
        gicd_write_set_bitmap_reg(s, attrs, s->enabled, NULL,
                                  offset - GICD_ISENABLER, value);
        return true;
    case GICD_ICENABLER ... GICD_ICENABLER + 0x7f:
        gicd_write_clear_bitmap_reg(s, attrs, s->enabled, NULL,
                                    offset - GICD_ICENABLER, value);
        return true;
    case GICD_ISPENDR ... GICD_ISPENDR + 0x7f:
        gicd_write_set_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1,
                                  offset - GICD_ISPENDR, value);
        return true;
    case GICD_ICPENDR ... GICD_ICPENDR + 0x7f:
        gicd_write_clear_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2,
                                    offset - GICD_ICPENDR, value);
        return true;
    case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f:
        gicd_write_set_bitmap_reg(s, attrs, s->active, NULL,
                                  offset - GICD_ISACTIVER, value);
        return true;
    case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f:
        gicd_write_clear_bitmap_reg(s, attrs, s->active, NULL,
                                    offset - GICD_ICACTIVER, value);
        return true;
    case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
    {
        int i, irq = offset - GICD_IPRIORITYR;

        if (irq < GIC_INTERNAL || irq + 3 >= s->num_irq) {
            return true;
        }

        for (i = irq; i < irq + 4; i++, value >>= 8) {
            gicd_write_ipriorityr(s, attrs, i, value);
        }
        gicv3_update(s, irq, 4);
        return true;
    }
    case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
        /* RAZ/WI since affinity routing is always enabled */
        return true;
    case GICD_ICFGR ... GICD_ICFGR + 0xff:
    {
        /* Here only the odd bits are used; even bits are RES0 */
        int irq = (offset - GICD_ICFGR) * 4;
        uint32_t mask, oldval;

        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            return true;
        }

        /* Since our edge_trigger bitmap is one bit per irq, our input
         * 32-bits will compress down into 16 bits which we need
         * to write into the bitmap.
         */
        value = half_unshuffle32(value >> 1);
        mask = mask_group_and_nsacr(s, attrs, NULL, irq & ~0x1f);
        if (irq & 0x1f) {
            value <<= 16;
            mask &= 0xffff0000U;
        } else {
            mask &= 0xffff;
        }
        oldval = *gic_bmp_ptr32(s->edge_trigger, (irq & ~0x1f));
        value = (oldval & ~mask) | (value & mask);
        *gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f) = value;
        return true;
    }
    case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff:
    {
        int irq;

        if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
            /* RAZ/WI if security disabled, or if
             * security enabled and this is an NS access
             */
            return true;
        }
        /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
        irq = (offset - GICD_IGRPMODR) * 8;
        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            return true;
        }
        *gic_bmp_ptr32(s->grpmod, irq) = value;
        gicv3_update(s, irq, 32);
        return true;
    }
    case GICD_NSACR ... GICD_NSACR + 0xff:
    {
        /* Two bits per interrupt */
        int irq = (offset - GICD_NSACR) * 4;

        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            return true;
        }

        if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
            /* RAZ/WI if security disabled, or if
             * security enabled and this is an NS access
             */
            return true;
        }

        s->gicd_nsacr[irq / 16] = value;
        /* No update required as this only affects access permission checks */
        return true;
    }
    case GICD_SGIR:
        /* RES0 if affinity routing is enabled */
        return true;
    case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
    case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
        /* RAZ/WI since affinity routing is always enabled */
        return true;
    case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
    {
        uint64_t r;
        int irq = (offset - GICD_IROUTER) / 8;

        if (irq < GIC_INTERNAL || irq >= s->num_irq) {
            return true;
        }

        /* Write half of the 64-bit register */
        r = gicd_read_irouter(s, attrs, irq);
        r = deposit64(r, (offset & 7) ? 32 : 0, 32, value);
        gicd_write_irouter(s, attrs, irq, r);
        return true;
    }
    case GICD_IDREGS ... GICD_IDREGS + 0x2f:
    case GICD_TYPER:
    case GICD_IIDR:
        /* RO registers, ignore the write */
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: invalid guest write to RO register at offset "
                      TARGET_FMT_plx "\n", __func__, offset);
        return true;
    default:
        return false;
    }
}

static bool gicd_writeq(GICv3State *s, hwaddr offset,
                        uint64_t value, MemTxAttrs attrs)
{
    /* Our only 64-bit registers are GICD_IROUTER<n> */
    int irq;

    switch (offset) {
    case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
        irq = (offset - GICD_IROUTER) / 8;
        gicd_write_irouter(s, attrs, irq, value);
        return true;
    default:
        return false;
    }
}

static bool gicd_readq(GICv3State *s, hwaddr offset,
                       uint64_t *data, MemTxAttrs attrs)
{
    /* Our only 64-bit registers are GICD_IROUTER<n> */
    int irq;

    switch (offset) {
    case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
        irq = (offset - GICD_IROUTER) / 8;
        *data = gicd_read_irouter(s, attrs, irq);
        return true;
    default:
        return false;
    }
}

MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
                            unsigned size, MemTxAttrs attrs)
{
    GICv3State *s = (GICv3State *)opaque;
    bool r;

    switch (size) {
    case 1:
        r = gicd_readb(s, offset, data, attrs);
        break;
    case 2:
        r = gicd_readw(s, offset, data, attrs);
        break;
    case 4:
        r = gicd_readl(s, offset, data, attrs);
        break;
    case 8:
        r = gicd_readq(s, offset, data, attrs);
        break;
    default:
        r = false;
        break;
    }

    if (!r) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: invalid guest read at offset " TARGET_FMT_plx
                      " size %u\n", __func__, offset, size);
        trace_gicv3_dist_badread(offset, size, attrs.secure);
        /* The spec requires that reserved registers are RAZ/WI;
         * so use MEMTX_ERROR returns from leaf functions as a way to
         * trigger the guest-error logging but don't return it to
         * the caller, or we'll cause a spurious guest data abort.
         */
        *data = 0;
    } else {
        trace_gicv3_dist_read(offset, *data, size, attrs.secure);
    }
    return MEMTX_OK;
}

MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
                             unsigned size, MemTxAttrs attrs)
{
    GICv3State *s = (GICv3State *)opaque;
    bool r;

    switch (size) {
    case 1:
        r = gicd_writeb(s, offset, data, attrs);
        break;
    case 2:
        r = gicd_writew(s, offset, data, attrs);
        break;
    case 4:
        r = gicd_writel(s, offset, data, attrs);
        break;
    case 8:
        r = gicd_writeq(s, offset, data, attrs);
        break;
    default:
        r = false;
        break;
    }

    if (!r) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: invalid guest write at offset " TARGET_FMT_plx
                      " size %u\n", __func__, offset, size);
        trace_gicv3_dist_badwrite(offset, data, size, attrs.secure);
        /* The spec requires that reserved registers are RAZ/WI;
         * so use MEMTX_ERROR returns from leaf functions as a way to
         * trigger the guest-error logging but don't return it to
         * the caller, or we'll cause a spurious guest data abort.
         */
    } else {
        trace_gicv3_dist_write(offset, data, size, attrs.secure);
    }
    return MEMTX_OK;
}

void gicv3_dist_set_irq(GICv3State *s, int irq, int level)
{
    /* Update distributor state for a change in an external SPI input line */
    if (level == gicv3_gicd_level_test(s, irq)) {
        return;
    }

    trace_gicv3_dist_set_irq(irq, level);

    gicv3_gicd_level_replace(s, irq, level);

    if (level) {
        /* 0->1 edges latch the pending bit for edge-triggered interrupts */
        if (gicv3_gicd_edge_trigger_test(s, irq)) {
            gicv3_gicd_pending_set(s, irq);
        }
    }

    gicv3_update(s, irq, 1);
}
