113531Sjairo.balart@metempsy.com/*
214167Sgiacomo.travaglini@arm.com * Copyright (c) 2019 ARM Limited
314167Sgiacomo.travaglini@arm.com * All rights reserved
414167Sgiacomo.travaglini@arm.com *
514167Sgiacomo.travaglini@arm.com * The license below extends only to copyright in the software and shall
614167Sgiacomo.travaglini@arm.com * not be construed as granting a license to any other intellectual
714167Sgiacomo.travaglini@arm.com * property including but not limited to intellectual property relating
814167Sgiacomo.travaglini@arm.com * to a hardware implementation of the functionality of the software
914167Sgiacomo.travaglini@arm.com * licensed hereunder.  You may use the software subject to the license
1014167Sgiacomo.travaglini@arm.com * terms below provided that you ensure that this notice is replicated
1114167Sgiacomo.travaglini@arm.com * unmodified and in its entirety in all distributions of the software,
1214167Sgiacomo.travaglini@arm.com * modified or unmodified, in source code or in binary form.
1314167Sgiacomo.travaglini@arm.com *
1413531Sjairo.balart@metempsy.com * Copyright (c) 2018 Metempsy Technology Consulting
1513531Sjairo.balart@metempsy.com * All rights reserved.
1613531Sjairo.balart@metempsy.com *
1713531Sjairo.balart@metempsy.com * Redistribution and use in source and binary forms, with or without
1813531Sjairo.balart@metempsy.com * modification, are permitted provided that the following conditions are
1913531Sjairo.balart@metempsy.com * met: redistributions of source code must retain the above copyright
2013531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer;
2113531Sjairo.balart@metempsy.com * redistributions in binary form must reproduce the above copyright
2213531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer in the
2313531Sjairo.balart@metempsy.com * documentation and/or other materials provided with the distribution;
2413531Sjairo.balart@metempsy.com * neither the name of the copyright holders nor the names of its
2513531Sjairo.balart@metempsy.com * contributors may be used to endorse or promote products derived from
2613531Sjairo.balart@metempsy.com * this software without specific prior written permission.
2713531Sjairo.balart@metempsy.com *
2813531Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2913531Sjairo.balart@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3013531Sjairo.balart@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3113531Sjairo.balart@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3213531Sjairo.balart@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3313531Sjairo.balart@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3413531Sjairo.balart@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3513531Sjairo.balart@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3613531Sjairo.balart@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3713531Sjairo.balart@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3813531Sjairo.balart@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3913531Sjairo.balart@metempsy.com *
4013531Sjairo.balart@metempsy.com * Authors: Jairo Balart
4113531Sjairo.balart@metempsy.com */
4213756Sjairo.balart@metempsy.com
4313531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_distributor.hh"
4413531Sjairo.balart@metempsy.com
4513531Sjairo.balart@metempsy.com#include <algorithm>
4613531Sjairo.balart@metempsy.com
4714257Sgiacomo.travaglini@arm.com#include "base/intmath.hh"
4813531Sjairo.balart@metempsy.com#include "debug/GIC.hh"
4913531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3.hh"
5013531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_cpu_interface.hh"
5113531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_redistributor.hh"
5213531Sjairo.balart@metempsy.com
5313756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IGROUPR   (0x0080, 0x00ff);
5413756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f);
5513756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff);
5613756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ISPENDR   (0x0200, 0x027f);
5713756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICPENDR   (0x0280, 0x02ff);
5813756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f);
5913756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff);
6013531Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
6113756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff);
6213756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICFGR     (0x0c00, 0x0cff);
6313756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IGRPMODR  (0x0d00, 0x0d7f);
6413756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_NSACR     (0x0e00, 0x0eff);
6513756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f);
6613756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f);
6713756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IROUTER   (0x6000, 0x7fe0);
6813531Sjairo.balart@metempsy.com
6913531Sjairo.balart@metempsy.comGicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines)
7013531Sjairo.balart@metempsy.com    : gic(gic),
7113531Sjairo.balart@metempsy.com      itLines(it_lines),
7214258Sgiacomo.travaglini@arm.com      ARE(true),
7314258Sgiacomo.travaglini@arm.com      EnableGrp1S(0),
7414258Sgiacomo.travaglini@arm.com      EnableGrp1NS(0),
7514258Sgiacomo.travaglini@arm.com      EnableGrp0(0),
7614258Sgiacomo.travaglini@arm.com      irqGroup(it_lines, 0),
7714258Sgiacomo.travaglini@arm.com      irqEnabled(it_lines, false),
7814258Sgiacomo.travaglini@arm.com      irqPending(it_lines, false),
7914258Sgiacomo.travaglini@arm.com      irqActive(it_lines, false),
8014258Sgiacomo.travaglini@arm.com      irqPriority(it_lines, 0xAA),
8114258Sgiacomo.travaglini@arm.com      irqConfig(it_lines, Gicv3::INT_LEVEL_SENSITIVE),
8214258Sgiacomo.travaglini@arm.com      irqGrpmod(it_lines, 0),
8314258Sgiacomo.travaglini@arm.com      irqNsacr(it_lines, 0),
8414258Sgiacomo.travaglini@arm.com      irqAffinityRouting(it_lines, 0),
8514257Sgiacomo.travaglini@arm.com      gicdTyper(0),
8614167Sgiacomo.travaglini@arm.com      gicdPidr0(0x92),
8714167Sgiacomo.travaglini@arm.com      gicdPidr1(0xb4),
8814167Sgiacomo.travaglini@arm.com      gicdPidr2(0x3b),
8914167Sgiacomo.travaglini@arm.com      gicdPidr3(0),
9014167Sgiacomo.travaglini@arm.com      gicdPidr4(0x44)
9113531Sjairo.balart@metempsy.com{
9213531Sjairo.balart@metempsy.com    panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
9314257Sgiacomo.travaglini@arm.com    /*
9414257Sgiacomo.travaglini@arm.com     * RSS           [26]    == 1
9514257Sgiacomo.travaglini@arm.com     * (The implementation does supports targeted SGIs with affinity
9614257Sgiacomo.travaglini@arm.com     * level 0 values of 0 - 255)
9714257Sgiacomo.travaglini@arm.com     * No1N          [25]    == 1
9814257Sgiacomo.travaglini@arm.com     * (1 of N SPI interrupts are not supported)
9914257Sgiacomo.travaglini@arm.com     * A3V           [24]    == 1
10014257Sgiacomo.travaglini@arm.com     * (Supports nonzero values of Affinity level 3)
10114257Sgiacomo.travaglini@arm.com     * IDbits        [23:19] == 0xf
10214257Sgiacomo.travaglini@arm.com     * (The number of interrupt identifier bits supported, minus one)
10314257Sgiacomo.travaglini@arm.com     * DVIS          [18]    == 0
10414257Sgiacomo.travaglini@arm.com     * (The implementation does not support Direct Virtual LPI
10514257Sgiacomo.travaglini@arm.com     * injection)
10614257Sgiacomo.travaglini@arm.com     * LPIS          [17]    == 1
10714257Sgiacomo.travaglini@arm.com     * (The implementation does not support LPIs)
10814257Sgiacomo.travaglini@arm.com     * MBIS          [16]    == 1
10914257Sgiacomo.travaglini@arm.com     * (The implementation supports message-based interrupts
11014257Sgiacomo.travaglini@arm.com     * by writing to Distributor registers)
11114257Sgiacomo.travaglini@arm.com     * SecurityExtn  [10]    == X
11214257Sgiacomo.travaglini@arm.com     * (The GIC implementation supports two Security states)
11314257Sgiacomo.travaglini@arm.com     * CPUNumber     [7:5]   == 0
11414257Sgiacomo.travaglini@arm.com     * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
11514257Sgiacomo.travaglini@arm.com     * ITLinesNumber [4:0]   == N
11614257Sgiacomo.travaglini@arm.com     * (MaxSPIIntId = 32 (N + 1) - 1)
11714257Sgiacomo.travaglini@arm.com     */
11814257Sgiacomo.travaglini@arm.com    int max_spi_int_id = itLines - 1;
11914257Sgiacomo.travaglini@arm.com    int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1;
12014257Sgiacomo.travaglini@arm.com    gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) |
12114257Sgiacomo.travaglini@arm.com        (1 << 17) | (1 << 16) |
12214257Sgiacomo.travaglini@arm.com        ((gic->getSystem()->haveSecurity() ? 1 : 0) << 10) |
12314257Sgiacomo.travaglini@arm.com        (it_lines_number << 0);
12413531Sjairo.balart@metempsy.com
12513531Sjairo.balart@metempsy.com    if (gic->getSystem()->haveSecurity()) {
12613531Sjairo.balart@metempsy.com        DS = false;
12713531Sjairo.balart@metempsy.com    } else {
12813531Sjairo.balart@metempsy.com        DS = true;
12913531Sjairo.balart@metempsy.com    }
13014258Sgiacomo.travaglini@arm.com}
13113531Sjairo.balart@metempsy.com
13214258Sgiacomo.travaglini@arm.comvoid
13314258Sgiacomo.travaglini@arm.comGicv3Distributor::init()
13414258Sgiacomo.travaglini@arm.com{
13513531Sjairo.balart@metempsy.com}
13613531Sjairo.balart@metempsy.com
13713531Sjairo.balart@metempsy.comuint64_t
13813531Sjairo.balart@metempsy.comGicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
13913531Sjairo.balart@metempsy.com{
14013531Sjairo.balart@metempsy.com    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
14113531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
14213531Sjairo.balart@metempsy.com
14313531Sjairo.balart@metempsy.com        if (!DS && !is_secure_access) {
14413531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
14513531Sjairo.balart@metempsy.com            return 0;
14613531Sjairo.balart@metempsy.com        }
14713531Sjairo.balart@metempsy.com
14813531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
14913531Sjairo.balart@metempsy.com
15013531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
15113531Sjairo.balart@metempsy.com            return 0;
15213531Sjairo.balart@metempsy.com        }
15313531Sjairo.balart@metempsy.com
15413531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
15513756Sjairo.balart@metempsy.com             i++, int_id++) {
15613531Sjairo.balart@metempsy.com            val |= irqGroup[int_id] << i;
15713531Sjairo.balart@metempsy.com        }
15813531Sjairo.balart@metempsy.com
15913531Sjairo.balart@metempsy.com        return val;
16013756Sjairo.balart@metempsy.com    } else if (GICD_ISENABLER.contains(addr)) {
16113531Sjairo.balart@metempsy.com        // Interrupt Set-Enable Registers
16213531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
16313531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
16413531Sjairo.balart@metempsy.com
16513531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
16613531Sjairo.balart@metempsy.com            return 0;
16713531Sjairo.balart@metempsy.com        }
16813531Sjairo.balart@metempsy.com
16913531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
17013756Sjairo.balart@metempsy.com             i++, int_id++) {
17113756Sjairo.balart@metempsy.com
17213531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
17313531Sjairo.balart@metempsy.com            {
17413531Sjairo.balart@metempsy.com                continue;
17513531Sjairo.balart@metempsy.com            }
17613531Sjairo.balart@metempsy.com
17713531Sjairo.balart@metempsy.com            val |= irqEnabled[int_id] << i;
17813531Sjairo.balart@metempsy.com        }
17913531Sjairo.balart@metempsy.com
18013531Sjairo.balart@metempsy.com        return val;
18113531Sjairo.balart@metempsy.com    } else if (GICD_ICENABLER.contains(addr)) {
18213531Sjairo.balart@metempsy.com        // Interrupt Clear-Enable Registers
18313531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
18413531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
18513531Sjairo.balart@metempsy.com
18613531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
18713531Sjairo.balart@metempsy.com            return 0;
18813531Sjairo.balart@metempsy.com        }
18913531Sjairo.balart@metempsy.com
19013531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
19113756Sjairo.balart@metempsy.com             i++, int_id++) {
19213756Sjairo.balart@metempsy.com
19313531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
19413531Sjairo.balart@metempsy.com            {
19513531Sjairo.balart@metempsy.com                continue;
19613531Sjairo.balart@metempsy.com            }
19713531Sjairo.balart@metempsy.com
19813531Sjairo.balart@metempsy.com            val |= (irqEnabled[int_id] << i);
19913531Sjairo.balart@metempsy.com        }
20013531Sjairo.balart@metempsy.com
20113531Sjairo.balart@metempsy.com        return val;
20213531Sjairo.balart@metempsy.com    } else if (GICD_ISPENDR.contains(addr)) {
20313756Sjairo.balart@metempsy.com        // Interrupt Set-Pending Registers
20413531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
20513531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
20613531Sjairo.balart@metempsy.com
20713531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
20813531Sjairo.balart@metempsy.com            return 0;
20913531Sjairo.balart@metempsy.com        }
21013531Sjairo.balart@metempsy.com
21113531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
21213756Sjairo.balart@metempsy.com             i++, int_id++) {
21313756Sjairo.balart@metempsy.com
21413531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
21513531Sjairo.balart@metempsy.com            {
21613531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] == 0) {
21713531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
21813531Sjairo.balart@metempsy.com                    continue;
21913531Sjairo.balart@metempsy.com                }
22013531Sjairo.balart@metempsy.com            }
22113531Sjairo.balart@metempsy.com
22213531Sjairo.balart@metempsy.com            val |= (irqPending[int_id] << i);
22313531Sjairo.balart@metempsy.com        }
22413531Sjairo.balart@metempsy.com
22513531Sjairo.balart@metempsy.com        return val;
22613531Sjairo.balart@metempsy.com    } else if (GICD_ICPENDR.contains(addr)) {
22713756Sjairo.balart@metempsy.com        // Interrupt Clear-Pending Registers
22813531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
22913531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
23013531Sjairo.balart@metempsy.com
23113531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
23213531Sjairo.balart@metempsy.com            return 0;
23313531Sjairo.balart@metempsy.com        }
23413531Sjairo.balart@metempsy.com
23513531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
23613756Sjairo.balart@metempsy.com             i++, int_id++) {
23713756Sjairo.balart@metempsy.com
23813531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
23913531Sjairo.balart@metempsy.com            {
24013531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
24113531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
24213531Sjairo.balart@metempsy.com                    continue;
24313531Sjairo.balart@metempsy.com                }
24413531Sjairo.balart@metempsy.com            }
24513531Sjairo.balart@metempsy.com
24613531Sjairo.balart@metempsy.com            val |= (irqPending[int_id] << i);
24713531Sjairo.balart@metempsy.com        }
24813531Sjairo.balart@metempsy.com
24913531Sjairo.balart@metempsy.com        return val;
25013756Sjairo.balart@metempsy.com    } else if (GICD_ISACTIVER.contains(addr)) {
25113531Sjairo.balart@metempsy.com        // Interrupt Set-Active Registers
25213531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
25313531Sjairo.balart@metempsy.com
25413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
25513531Sjairo.balart@metempsy.com            return 0;
25613531Sjairo.balart@metempsy.com        }
25713531Sjairo.balart@metempsy.com
25813531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
25913531Sjairo.balart@metempsy.com
26013531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
26113756Sjairo.balart@metempsy.com             i++, int_id++) {
26213756Sjairo.balart@metempsy.com
26313531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
26413531Sjairo.balart@metempsy.com            {
26513531Sjairo.balart@metempsy.com                // Group 0 or Secure Group 1 interrupts are RAZ/WI
26613531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
26713531Sjairo.balart@metempsy.com                    continue;
26813531Sjairo.balart@metempsy.com                }
26913531Sjairo.balart@metempsy.com            }
27013531Sjairo.balart@metempsy.com
27113531Sjairo.balart@metempsy.com            val |= (irqActive[int_id] << i);
27213531Sjairo.balart@metempsy.com        }
27313531Sjairo.balart@metempsy.com
27413531Sjairo.balart@metempsy.com        return val;
27513756Sjairo.balart@metempsy.com    } else if (GICD_ICACTIVER.contains(addr)) {
27613531Sjairo.balart@metempsy.com        // Interrupt Clear-Active Registers
27713531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
27813531Sjairo.balart@metempsy.com
27913531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
28013531Sjairo.balart@metempsy.com            return 0;
28113531Sjairo.balart@metempsy.com        }
28213531Sjairo.balart@metempsy.com
28313531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
28413531Sjairo.balart@metempsy.com
28513531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
28613756Sjairo.balart@metempsy.com             i++, int_id++) {
28713756Sjairo.balart@metempsy.com
28813531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
28913531Sjairo.balart@metempsy.com            {
29013531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
29113531Sjairo.balart@metempsy.com                    continue;
29213531Sjairo.balart@metempsy.com                }
29313531Sjairo.balart@metempsy.com            }
29413531Sjairo.balart@metempsy.com
29513531Sjairo.balart@metempsy.com            val |= (irqActive[int_id] << i);
29613531Sjairo.balart@metempsy.com        }
29713531Sjairo.balart@metempsy.com
29813531Sjairo.balart@metempsy.com        return val;
29913756Sjairo.balart@metempsy.com    } else if (GICD_IPRIORITYR.contains(addr)) {
30013531Sjairo.balart@metempsy.com        // Interrupt Priority Registers
30113531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
30213531Sjairo.balart@metempsy.com        int first_intid = addr - GICD_IPRIORITYR.start();
30313531Sjairo.balart@metempsy.com
30413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
30513531Sjairo.balart@metempsy.com            return 0;
30613531Sjairo.balart@metempsy.com        }
30713531Sjairo.balart@metempsy.com
30813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
30913756Sjairo.balart@metempsy.com             i++, int_id++) {
31013756Sjairo.balart@metempsy.com
31113531Sjairo.balart@metempsy.com            uint8_t prio = irqPriority[int_id];
31213531Sjairo.balart@metempsy.com
31313531Sjairo.balart@metempsy.com            if (!DS && !is_secure_access) {
31413531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
31513531Sjairo.balart@metempsy.com                    // RAZ/WI for non-secure accesses for secure interrupts
31613531Sjairo.balart@metempsy.com                    continue;
31713531Sjairo.balart@metempsy.com                } else {
31813531Sjairo.balart@metempsy.com                    // NS view
31913531Sjairo.balart@metempsy.com                    prio = (prio << 1) & 0xff;
32013531Sjairo.balart@metempsy.com                }
32113531Sjairo.balart@metempsy.com            }
32213531Sjairo.balart@metempsy.com
32313531Sjairo.balart@metempsy.com            val |= prio << (i * 8);
32413531Sjairo.balart@metempsy.com        }
32513531Sjairo.balart@metempsy.com
32613531Sjairo.balart@metempsy.com        return val;
32713531Sjairo.balart@metempsy.com    } else if (GICD_ITARGETSR.contains(addr)) {
32813531Sjairo.balart@metempsy.com        // Interrupt Processor Targets Registers
32913531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
33013531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::read(): "
33113531Sjairo.balart@metempsy.com             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
33213531Sjairo.balart@metempsy.com        return 0;
33313756Sjairo.balart@metempsy.com    } else if (GICD_ICFGR.contains(addr)) {
33413531Sjairo.balart@metempsy.com        // Interrupt Configuration Registers
33513531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICFGR.start()) * 4;
33613531Sjairo.balart@metempsy.com
33713531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
33813531Sjairo.balart@metempsy.com            return 0;
33913531Sjairo.balart@metempsy.com        }
34013531Sjairo.balart@metempsy.com
34113531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
34213531Sjairo.balart@metempsy.com
34313531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
34413756Sjairo.balart@metempsy.com             i = i + 2, int_id++) {
34513756Sjairo.balart@metempsy.com
34613531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
34713531Sjairo.balart@metempsy.com            {
34813531Sjairo.balart@metempsy.com                continue;
34913531Sjairo.balart@metempsy.com            }
35013531Sjairo.balart@metempsy.com
35113531Sjairo.balart@metempsy.com            if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
35213531Sjairo.balart@metempsy.com                val |= (0x2 << i);
35313531Sjairo.balart@metempsy.com            }
35413531Sjairo.balart@metempsy.com        }
35513531Sjairo.balart@metempsy.com
35613531Sjairo.balart@metempsy.com        return val;
35713531Sjairo.balart@metempsy.com    } else if (GICD_IGRPMODR.contains(addr)) {
35813531Sjairo.balart@metempsy.com        // Interrupt Group Modifier Registers
35913531Sjairo.balart@metempsy.com        if (DS) {
36013531Sjairo.balart@metempsy.com            // RAZ/WI if security disabled
36113531Sjairo.balart@metempsy.com            return 0;
36213531Sjairo.balart@metempsy.com        } else {
36313531Sjairo.balart@metempsy.com            if (!is_secure_access) {
36413531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses
36513531Sjairo.balart@metempsy.com                return 0;
36613531Sjairo.balart@metempsy.com            } else {
36713531Sjairo.balart@metempsy.com                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
36813531Sjairo.balart@metempsy.com
36913531Sjairo.balart@metempsy.com                if (isNotSPI(first_intid)) {
37013531Sjairo.balart@metempsy.com                    return 0;
37113531Sjairo.balart@metempsy.com                }
37213531Sjairo.balart@metempsy.com
37313531Sjairo.balart@metempsy.com                uint64_t val = 0x0;
37413531Sjairo.balart@metempsy.com
37513531Sjairo.balart@metempsy.com                for (int i = 0, int_id = first_intid;
37613756Sjairo.balart@metempsy.com                     i < 8 * size && int_id < itLines; i++, int_id++) {
37713531Sjairo.balart@metempsy.com                    val |= irqGrpmod[int_id] << i;
37813531Sjairo.balart@metempsy.com                }
37913531Sjairo.balart@metempsy.com
38013531Sjairo.balart@metempsy.com                return val;
38113531Sjairo.balart@metempsy.com            }
38213531Sjairo.balart@metempsy.com        }
38313756Sjairo.balart@metempsy.com    } else if (GICD_NSACR.contains(addr)) {
38413531Sjairo.balart@metempsy.com        // Non-secure Access Control Registers
38513531Sjairo.balart@metempsy.com        // 2 bits per interrupt
38613531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_NSACR.start()) * 4;
38713531Sjairo.balart@metempsy.com
38813531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
38913531Sjairo.balart@metempsy.com            return 0;
39013531Sjairo.balart@metempsy.com        }
39113531Sjairo.balart@metempsy.com
39213531Sjairo.balart@metempsy.com        if (DS || (!DS && !is_secure_access)) {
39313531Sjairo.balart@metempsy.com            return 0;
39413531Sjairo.balart@metempsy.com        }
39513531Sjairo.balart@metempsy.com
39613531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
39713531Sjairo.balart@metempsy.com
39813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid;
39913756Sjairo.balart@metempsy.com             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
40013531Sjairo.balart@metempsy.com            val |= irqNsacr[int_id] << i;
40113531Sjairo.balart@metempsy.com        }
40213531Sjairo.balart@metempsy.com
40313531Sjairo.balart@metempsy.com        return val;
40413531Sjairo.balart@metempsy.com    } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
40513531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
40613531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::read(): "
40713531Sjairo.balart@metempsy.com             "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
40813531Sjairo.balart@metempsy.com        return 0x0;
40913531Sjairo.balart@metempsy.com    } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
41013531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
41113531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::read(): "
41213531Sjairo.balart@metempsy.com             "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
41313531Sjairo.balart@metempsy.com        return 0x0;
41413531Sjairo.balart@metempsy.com    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
41513531Sjairo.balart@metempsy.com        // 64 bit registers. 2 or 1 access.
41613531Sjairo.balart@metempsy.com        int int_id = (addr - GICD_IROUTER.start()) / 8;
41713531Sjairo.balart@metempsy.com
41813531Sjairo.balart@metempsy.com        if (isNotSPI(int_id)) {
41913531Sjairo.balart@metempsy.com            return 0;
42013531Sjairo.balart@metempsy.com        }
42113531Sjairo.balart@metempsy.com
42213531Sjairo.balart@metempsy.com        if (nsAccessToSecInt(int_id, is_secure_access))
42313531Sjairo.balart@metempsy.com        {
42413531Sjairo.balart@metempsy.com            if (irqNsacr[int_id] < 3) {
42513531Sjairo.balart@metempsy.com                return 0;
42613531Sjairo.balart@metempsy.com            }
42713531Sjairo.balart@metempsy.com        }
42813531Sjairo.balart@metempsy.com
42913531Sjairo.balart@metempsy.com        if (size == 4) {
43013531Sjairo.balart@metempsy.com            if (addr & 7) { // high half of 64 bit register
43113531Sjairo.balart@metempsy.com                return irqAffinityRouting[int_id] >> 32;
43213531Sjairo.balart@metempsy.com            } else { // high low of 64 bit register
43313531Sjairo.balart@metempsy.com                return irqAffinityRouting[int_id] & 0xFFFFFFFF;
43413531Sjairo.balart@metempsy.com            }
43513531Sjairo.balart@metempsy.com        } else {
43613531Sjairo.balart@metempsy.com            return irqAffinityRouting[int_id];
43713531Sjairo.balart@metempsy.com        }
43813531Sjairo.balart@metempsy.com    }
43913531Sjairo.balart@metempsy.com
44013531Sjairo.balart@metempsy.com    switch (addr) {
44113531Sjairo.balart@metempsy.com      case GICD_CTLR: // Control Register
44213531Sjairo.balart@metempsy.com        if (!DS) {
44313531Sjairo.balart@metempsy.com            if (is_secure_access) {
44413531Sjairo.balart@metempsy.com                // E1NWF [7] RAZ/WI
44513531Sjairo.balart@metempsy.com                // DS [6] - Disable Security
44613531Sjairo.balart@metempsy.com                // ARE_NS [5] RAO/WI
44713531Sjairo.balart@metempsy.com                // ARE_S [4] RAO/WI
44813531Sjairo.balart@metempsy.com                // EnableGrp1S [2]
44913531Sjairo.balart@metempsy.com                // EnableGrp1NS [1]
45013531Sjairo.balart@metempsy.com                // EnableGrp0 [0]
45113531Sjairo.balart@metempsy.com                return (EnableGrp0 << 0) |
45213531Sjairo.balart@metempsy.com                    (EnableGrp1NS << 1) |
45313531Sjairo.balart@metempsy.com                    (EnableGrp1S << 2) |
45413531Sjairo.balart@metempsy.com                    (1 << 4) |
45513531Sjairo.balart@metempsy.com                    (1 << 5) |
45613531Sjairo.balart@metempsy.com                    (DS << 6);
45713531Sjairo.balart@metempsy.com            } else {
45813531Sjairo.balart@metempsy.com                // ARE_NS [4] RAO/WI;
45913531Sjairo.balart@metempsy.com                // EnableGrp1A [1] is a read-write alias of the Secure
46013531Sjairo.balart@metempsy.com                // GICD_CTLR.EnableGrp1NS
46113531Sjairo.balart@metempsy.com                // EnableGrp1 [0] RES0
46213531Sjairo.balart@metempsy.com                return (1 << 4) | (EnableGrp1NS << 1);
46313531Sjairo.balart@metempsy.com            }
46413531Sjairo.balart@metempsy.com        } else {
46513531Sjairo.balart@metempsy.com            return (DS << 6) | (ARE << 4) |
46613531Sjairo.balart@metempsy.com                (EnableGrp1NS << 1) | (EnableGrp0 << 0);
46713531Sjairo.balart@metempsy.com        }
46813531Sjairo.balart@metempsy.com
46913531Sjairo.balart@metempsy.com      case GICD_TYPER: // Interrupt Controller Type Register
47014257Sgiacomo.travaglini@arm.com        return gicdTyper;
47113531Sjairo.balart@metempsy.com
47213531Sjairo.balart@metempsy.com      case GICD_IIDR: // Implementer Identification Register
47313531Sjairo.balart@metempsy.com        //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
47413531Sjairo.balart@metempsy.com        return 0;
47513531Sjairo.balart@metempsy.com
47613531Sjairo.balart@metempsy.com      case GICD_STATUSR: // Error Reporting Status Register
47713531Sjairo.balart@metempsy.com        // Optional register, RAZ/WI
47813531Sjairo.balart@metempsy.com        return 0x0;
47913531Sjairo.balart@metempsy.com
48013756Sjairo.balart@metempsy.com      case GICD_PIDR0: // Peripheral ID0 Register
48114167Sgiacomo.travaglini@arm.com        return gicdPidr0;
48213531Sjairo.balart@metempsy.com
48314167Sgiacomo.travaglini@arm.com      case GICD_PIDR1: // Peripheral ID1 Register
48414167Sgiacomo.travaglini@arm.com        return gicdPidr1;
48513531Sjairo.balart@metempsy.com
48614167Sgiacomo.travaglini@arm.com      case GICD_PIDR2: // Peripheral ID2 Register
48714167Sgiacomo.travaglini@arm.com        return gicdPidr2;
48813531Sjairo.balart@metempsy.com
48913531Sjairo.balart@metempsy.com      case GICD_PIDR3: // Peripheral ID3 Register
49014167Sgiacomo.travaglini@arm.com        return gicdPidr3;
49113531Sjairo.balart@metempsy.com
49214167Sgiacomo.travaglini@arm.com      case GICD_PIDR4: // Peripheral ID4 Register
49314167Sgiacomo.travaglini@arm.com        return gicdPidr4;
49413531Sjairo.balart@metempsy.com
49513531Sjairo.balart@metempsy.com      case GICD_PIDR5: // Peripheral ID5 Register
49613531Sjairo.balart@metempsy.com      case GICD_PIDR6: // Peripheral ID6 Register
49713531Sjairo.balart@metempsy.com      case GICD_PIDR7: // Peripheral ID7 Register
49813531Sjairo.balart@metempsy.com        return 0; // RES0
49913531Sjairo.balart@metempsy.com
50013531Sjairo.balart@metempsy.com      default:
50113531Sjairo.balart@metempsy.com        panic("Gicv3Distributor::read(): invalid offset %#x\n", addr);
50213531Sjairo.balart@metempsy.com        break;
50313531Sjairo.balart@metempsy.com    }
50413531Sjairo.balart@metempsy.com}
50513531Sjairo.balart@metempsy.com
50613531Sjairo.balart@metempsy.comvoid
50713531Sjairo.balart@metempsy.comGicv3Distributor::write(Addr addr, uint64_t data, size_t size,
50813531Sjairo.balart@metempsy.com                        bool is_secure_access)
50913531Sjairo.balart@metempsy.com{
51013531Sjairo.balart@metempsy.com    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
51113531Sjairo.balart@metempsy.com        if (!DS && !is_secure_access) {
51213531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
51313531Sjairo.balart@metempsy.com            return;
51413531Sjairo.balart@metempsy.com        }
51513531Sjairo.balart@metempsy.com
51613531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
51713531Sjairo.balart@metempsy.com
51813531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
51913531Sjairo.balart@metempsy.com            return;
52013531Sjairo.balart@metempsy.com        }
52113531Sjairo.balart@metempsy.com
52213531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
52313756Sjairo.balart@metempsy.com             i++, int_id++) {
52413531Sjairo.balart@metempsy.com            irqGroup[int_id] = data & (1 << i) ? 1 : 0;
52513531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
52613531Sjairo.balart@metempsy.com                    int_id, irqGroup[int_id]);
52713531Sjairo.balart@metempsy.com        }
52813531Sjairo.balart@metempsy.com
52913531Sjairo.balart@metempsy.com        return;
53013756Sjairo.balart@metempsy.com    } else if (GICD_ISENABLER.contains(addr)) {
53113531Sjairo.balart@metempsy.com        // Interrupt Set-Enable Registers
53213531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
53313531Sjairo.balart@metempsy.com
53413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
53513531Sjairo.balart@metempsy.com            return;
53613531Sjairo.balart@metempsy.com        }
53713531Sjairo.balart@metempsy.com
53813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
53913756Sjairo.balart@metempsy.com             i++, int_id++) {
54013756Sjairo.balart@metempsy.com
54113531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
54213531Sjairo.balart@metempsy.com            {
54313531Sjairo.balart@metempsy.com                continue;
54413531Sjairo.balart@metempsy.com            }
54513531Sjairo.balart@metempsy.com
54613531Sjairo.balart@metempsy.com            bool enable = data & (1 << i) ? 1 : 0;
54713531Sjairo.balart@metempsy.com
54813531Sjairo.balart@metempsy.com            if (enable) {
54913531Sjairo.balart@metempsy.com                if (!irqEnabled[int_id]) {
55013531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
55113531Sjairo.balart@metempsy.com                            "int_id %d enabled\n", int_id);
55213531Sjairo.balart@metempsy.com                }
55313531Sjairo.balart@metempsy.com
55413531Sjairo.balart@metempsy.com                irqEnabled[int_id] = true;
55513531Sjairo.balart@metempsy.com            }
55613531Sjairo.balart@metempsy.com        }
55713531Sjairo.balart@metempsy.com
55813531Sjairo.balart@metempsy.com        return;
55913531Sjairo.balart@metempsy.com    } else if (GICD_ICENABLER.contains(addr)) {
56013531Sjairo.balart@metempsy.com        // Interrupt Clear-Enable Registers
56113531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
56213531Sjairo.balart@metempsy.com
56313812Sgiacomo.travaglini@arm.com        if (isNotSPI(first_intid)) {
56413812Sgiacomo.travaglini@arm.com            return;
56513812Sgiacomo.travaglini@arm.com        }
56613812Sgiacomo.travaglini@arm.com
56713531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
56813756Sjairo.balart@metempsy.com             i++, int_id++) {
56913756Sjairo.balart@metempsy.com
57013531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
57113531Sjairo.balart@metempsy.com            {
57213531Sjairo.balart@metempsy.com                continue;
57313531Sjairo.balart@metempsy.com            }
57413531Sjairo.balart@metempsy.com
57513531Sjairo.balart@metempsy.com            bool disable = data & (1 << i) ? 1 : 0;
57613531Sjairo.balart@metempsy.com
57713531Sjairo.balart@metempsy.com            if (disable) {
57813531Sjairo.balart@metempsy.com                if (irqEnabled[int_id]) {
57913531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
58013531Sjairo.balart@metempsy.com                            "int_id %d disabled\n", int_id);
58113531Sjairo.balart@metempsy.com                }
58213531Sjairo.balart@metempsy.com
58313531Sjairo.balart@metempsy.com                irqEnabled[int_id] = false;
58413531Sjairo.balart@metempsy.com            }
58513531Sjairo.balart@metempsy.com        }
58613531Sjairo.balart@metempsy.com
58713531Sjairo.balart@metempsy.com        return;
58813531Sjairo.balart@metempsy.com    } else if (GICD_ISPENDR.contains(addr)) {
58913756Sjairo.balart@metempsy.com        // Interrupt Set-Pending Registers
59013531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
59113531Sjairo.balart@metempsy.com
59213531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
59313531Sjairo.balart@metempsy.com            return;
59413531Sjairo.balart@metempsy.com        }
59513531Sjairo.balart@metempsy.com
59613531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
59713756Sjairo.balart@metempsy.com             i++, int_id++) {
59813756Sjairo.balart@metempsy.com
59913531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
60013531Sjairo.balart@metempsy.com            {
60113531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] == 0) {
60213531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
60313531Sjairo.balart@metempsy.com                    continue;
60413531Sjairo.balart@metempsy.com                }
60513531Sjairo.balart@metempsy.com            }
60613531Sjairo.balart@metempsy.com
60713531Sjairo.balart@metempsy.com            bool pending = data & (1 << i) ? 1 : 0;
60813531Sjairo.balart@metempsy.com
60913531Sjairo.balart@metempsy.com            if (pending) {
61013531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
61113531Sjairo.balart@metempsy.com                        "int_id %d (SPI) pending bit set\n", int_id);
61213531Sjairo.balart@metempsy.com                irqPending[int_id] = true;
61313531Sjairo.balart@metempsy.com            }
61413531Sjairo.balart@metempsy.com        }
61513531Sjairo.balart@metempsy.com
61614231Sgiacomo.travaglini@arm.com        update();
61713531Sjairo.balart@metempsy.com        return;
61813531Sjairo.balart@metempsy.com    } else if (GICD_ICPENDR.contains(addr)) {
61913756Sjairo.balart@metempsy.com        // Interrupt Clear-Pending Registers
62013531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
62113531Sjairo.balart@metempsy.com
62213531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
62313531Sjairo.balart@metempsy.com            return;
62413531Sjairo.balart@metempsy.com        }
62513531Sjairo.balart@metempsy.com
62613531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
62713756Sjairo.balart@metempsy.com             i++, int_id++) {
62813756Sjairo.balart@metempsy.com
62913531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
63013531Sjairo.balart@metempsy.com            {
63113531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
63213531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
63313531Sjairo.balart@metempsy.com                    continue;
63413531Sjairo.balart@metempsy.com                }
63513531Sjairo.balart@metempsy.com            }
63613531Sjairo.balart@metempsy.com
63713531Sjairo.balart@metempsy.com            bool clear = data & (1 << i) ? 1 : 0;
63813531Sjairo.balart@metempsy.com
63913531Sjairo.balart@metempsy.com            if (clear) {
64013531Sjairo.balart@metempsy.com                irqPending[int_id] = false;
64114231Sgiacomo.travaglini@arm.com                clearIrqCpuInterface(int_id);
64213531Sjairo.balart@metempsy.com            }
64313531Sjairo.balart@metempsy.com        }
64413531Sjairo.balart@metempsy.com
64514231Sgiacomo.travaglini@arm.com        update();
64613531Sjairo.balart@metempsy.com        return;
64713756Sjairo.balart@metempsy.com    } else if (GICD_ISACTIVER.contains(addr)) {
64813531Sjairo.balart@metempsy.com        // Interrupt Set-Active Registers
64913531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
65013531Sjairo.balart@metempsy.com
65113531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
65213531Sjairo.balart@metempsy.com            return;
65313531Sjairo.balart@metempsy.com        }
65413531Sjairo.balart@metempsy.com
65513531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
65613756Sjairo.balart@metempsy.com             i++, int_id++) {
65713756Sjairo.balart@metempsy.com
65813531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
65913531Sjairo.balart@metempsy.com            {
66013531Sjairo.balart@metempsy.com                continue;
66113531Sjairo.balart@metempsy.com            }
66213531Sjairo.balart@metempsy.com
66313531Sjairo.balart@metempsy.com            bool active = data & (1 << i) ? 1 : 0;
66413531Sjairo.balart@metempsy.com
66513531Sjairo.balart@metempsy.com            if (active) {
66613531Sjairo.balart@metempsy.com                irqActive[int_id] = 1;
66713531Sjairo.balart@metempsy.com            }
66813531Sjairo.balart@metempsy.com        }
66913531Sjairo.balart@metempsy.com
67013531Sjairo.balart@metempsy.com        return;
67113531Sjairo.balart@metempsy.com    } else if (GICD_ICACTIVER.contains(addr)) {
67213531Sjairo.balart@metempsy.com        // Interrupt Clear-Active Registers
67313531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
67413531Sjairo.balart@metempsy.com
67513531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
67613531Sjairo.balart@metempsy.com            return;
67713531Sjairo.balart@metempsy.com        }
67813531Sjairo.balart@metempsy.com
67913531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
68013756Sjairo.balart@metempsy.com             i++, int_id++) {
68113756Sjairo.balart@metempsy.com
68213531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
68313531Sjairo.balart@metempsy.com            {
68413531Sjairo.balart@metempsy.com                continue;
68513531Sjairo.balart@metempsy.com            }
68613531Sjairo.balart@metempsy.com
68713531Sjairo.balart@metempsy.com            bool clear = data & (1 << i) ? 1 : 0;
68813531Sjairo.balart@metempsy.com
68913531Sjairo.balart@metempsy.com            if (clear) {
69013531Sjairo.balart@metempsy.com                if (irqActive[int_id]) {
69113531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
69213531Sjairo.balart@metempsy.com                            "int_id %d active cleared\n", int_id);
69313531Sjairo.balart@metempsy.com                }
69413531Sjairo.balart@metempsy.com
69513531Sjairo.balart@metempsy.com                irqActive[int_id] = false;
69613531Sjairo.balart@metempsy.com            }
69713531Sjairo.balart@metempsy.com        }
69813531Sjairo.balart@metempsy.com
69913531Sjairo.balart@metempsy.com        return;
70013756Sjairo.balart@metempsy.com    } else if (GICD_IPRIORITYR.contains(addr)) {
70113531Sjairo.balart@metempsy.com        // Interrupt Priority Registers
70213531Sjairo.balart@metempsy.com        int first_intid = addr - GICD_IPRIORITYR.start();
70313531Sjairo.balart@metempsy.com
70413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
70513531Sjairo.balart@metempsy.com            return;
70613531Sjairo.balart@metempsy.com        }
70713531Sjairo.balart@metempsy.com
70813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
70913531Sjairo.balart@metempsy.com                i++, int_id++) {
71013531Sjairo.balart@metempsy.com            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
71113531Sjairo.balart@metempsy.com
71213531Sjairo.balart@metempsy.com            if (!DS && !is_secure_access) {
71313531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
71413531Sjairo.balart@metempsy.com                    // RAZ/WI for non-secure accesses to secure interrupts
71513531Sjairo.balart@metempsy.com                    continue;
71613531Sjairo.balart@metempsy.com                } else {
71713531Sjairo.balart@metempsy.com                    prio = 0x80 | (prio >> 1);
71813531Sjairo.balart@metempsy.com                }
71913531Sjairo.balart@metempsy.com            }
72013531Sjairo.balart@metempsy.com
72113531Sjairo.balart@metempsy.com            irqPriority[int_id] = prio;
72213531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
72313531Sjairo.balart@metempsy.com                    int_id, irqPriority[int_id]);
72413531Sjairo.balart@metempsy.com        }
72513531Sjairo.balart@metempsy.com
72613531Sjairo.balart@metempsy.com        return;
72713531Sjairo.balart@metempsy.com    } else if (GICD_ITARGETSR.contains(addr)) {
72813531Sjairo.balart@metempsy.com        // Interrupt Processor Targets Registers
72913531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
73013531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::write(): "
73113531Sjairo.balart@metempsy.com             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
73213531Sjairo.balart@metempsy.com        return;
73313756Sjairo.balart@metempsy.com    } else if (GICD_ICFGR.contains(addr)) {
73413531Sjairo.balart@metempsy.com        // Interrupt Configuration Registers
73513756Sjairo.balart@metempsy.com        // for x = 0 to 15:
73613756Sjairo.balart@metempsy.com        //   GICD_ICFGR[2x] = RES0
73713756Sjairo.balart@metempsy.com        //   GICD_ICFGR[2x + 1] =
73813756Sjairo.balart@metempsy.com        //     0 level-sensitive
73913756Sjairo.balart@metempsy.com        //     1 edge-triggered
74013531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICFGR.start()) * 4;
74113531Sjairo.balart@metempsy.com
74213531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
74313531Sjairo.balart@metempsy.com            return;
74413531Sjairo.balart@metempsy.com        }
74513531Sjairo.balart@metempsy.com
74613531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
74713756Sjairo.balart@metempsy.com             i = i + 2, int_id++) {
74813531Sjairo.balart@metempsy.com            irqConfig[int_id] = data & (0x2 << i) ?
74913531Sjairo.balart@metempsy.com                                Gicv3::INT_EDGE_TRIGGERED :
75013531Sjairo.balart@metempsy.com                                Gicv3::INT_LEVEL_SENSITIVE;
75113531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
75213531Sjairo.balart@metempsy.com                    int_id, irqConfig[int_id]);
75313531Sjairo.balart@metempsy.com        }
75413531Sjairo.balart@metempsy.com
75513531Sjairo.balart@metempsy.com        return;
75613531Sjairo.balart@metempsy.com    } else if (GICD_IGRPMODR.contains(addr)) {
75713531Sjairo.balart@metempsy.com        // Interrupt Group Modifier Registers
75813531Sjairo.balart@metempsy.com        if (DS) {
75913531Sjairo.balart@metempsy.com            return;
76013531Sjairo.balart@metempsy.com        } else {
76113531Sjairo.balart@metempsy.com            if (!is_secure_access) {
76213531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses
76313531Sjairo.balart@metempsy.com                return;
76413531Sjairo.balart@metempsy.com            } else {
76513531Sjairo.balart@metempsy.com                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
76613531Sjairo.balart@metempsy.com
76713531Sjairo.balart@metempsy.com                if (isNotSPI(first_intid)) {
76813531Sjairo.balart@metempsy.com                    return;
76913531Sjairo.balart@metempsy.com                }
77013531Sjairo.balart@metempsy.com
77113531Sjairo.balart@metempsy.com                for (int i = 0, int_id = first_intid;
77213756Sjairo.balart@metempsy.com                     i < 8 * size && int_id < itLines; i++, int_id++) {
77314230Sgiacomo.travaglini@arm.com                    irqGrpmod[int_id] = bits(data, i);
77413531Sjairo.balart@metempsy.com                }
77513531Sjairo.balart@metempsy.com
77613531Sjairo.balart@metempsy.com                return ;
77713531Sjairo.balart@metempsy.com            }
77813531Sjairo.balart@metempsy.com        }
77913531Sjairo.balart@metempsy.com
78013756Sjairo.balart@metempsy.com    } else if (GICD_NSACR.contains(addr)) {
78113531Sjairo.balart@metempsy.com        // Non-secure Access Control Registers
78213531Sjairo.balart@metempsy.com        // 2 bits per interrupt
78313531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_NSACR.start()) * 4;
78413531Sjairo.balart@metempsy.com
78513531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
78613531Sjairo.balart@metempsy.com            return;
78713531Sjairo.balart@metempsy.com        }
78813531Sjairo.balart@metempsy.com
78913531Sjairo.balart@metempsy.com        if (DS || (!DS && !is_secure_access)) {
79013531Sjairo.balart@metempsy.com            return;
79113531Sjairo.balart@metempsy.com        }
79213531Sjairo.balart@metempsy.com
79313531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid;
79413756Sjairo.balart@metempsy.com             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
79513531Sjairo.balart@metempsy.com            irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
79613531Sjairo.balart@metempsy.com        }
79713531Sjairo.balart@metempsy.com
79813531Sjairo.balart@metempsy.com        return;
79913531Sjairo.balart@metempsy.com    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
80013531Sjairo.balart@metempsy.com        // 64 bit registers. 2 accesses.
80113531Sjairo.balart@metempsy.com        int int_id = (addr - GICD_IROUTER.start()) / 8;
80213531Sjairo.balart@metempsy.com
80313531Sjairo.balart@metempsy.com        if (isNotSPI(int_id)) {
80413531Sjairo.balart@metempsy.com            return;
80513531Sjairo.balart@metempsy.com        }
80613531Sjairo.balart@metempsy.com
80713531Sjairo.balart@metempsy.com        if (nsAccessToSecInt(int_id, is_secure_access))
80813531Sjairo.balart@metempsy.com        {
80913531Sjairo.balart@metempsy.com            if (irqNsacr[int_id] < 3) {
81013531Sjairo.balart@metempsy.com                // Group 0 or Secure Group 1 interrupts are RAZ/WI
81113531Sjairo.balart@metempsy.com                return;
81213531Sjairo.balart@metempsy.com            }
81313531Sjairo.balart@metempsy.com        }
81413531Sjairo.balart@metempsy.com
81513531Sjairo.balart@metempsy.com        if (size == 4) {
81613531Sjairo.balart@metempsy.com            if (addr & 7) { // high half of 64 bit register
81713531Sjairo.balart@metempsy.com                irqAffinityRouting[int_id] =
81813531Sjairo.balart@metempsy.com                    (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
81913531Sjairo.balart@metempsy.com            } else { // low half of 64 bit register
82013531Sjairo.balart@metempsy.com                irqAffinityRouting[int_id] =
82113531Sjairo.balart@metempsy.com                    (irqAffinityRouting[int_id] & 0xffffffff00000000) |
82213531Sjairo.balart@metempsy.com                    (data & 0xffffffff);
82313531Sjairo.balart@metempsy.com            }
82413531Sjairo.balart@metempsy.com        } else {
82513531Sjairo.balart@metempsy.com            irqAffinityRouting[int_id] = data;
82613531Sjairo.balart@metempsy.com        }
82713531Sjairo.balart@metempsy.com
82813531Sjairo.balart@metempsy.com        DPRINTF(GIC, "Gicv3Distributor::write(): "
82913531Sjairo.balart@metempsy.com                "int_id %d GICD_IROUTER %#llx\n",
83013531Sjairo.balart@metempsy.com                int_id, irqAffinityRouting[int_id]);
83113531Sjairo.balart@metempsy.com        return;
83213531Sjairo.balart@metempsy.com    }
83313531Sjairo.balart@metempsy.com
83413531Sjairo.balart@metempsy.com    switch (addr) {
83513531Sjairo.balart@metempsy.com      case GICD_CTLR: // Control Register
83613531Sjairo.balart@metempsy.com        if (DS) {
83713531Sjairo.balart@metempsy.com            /*
83813531Sjairo.balart@metempsy.com             * E1NWF [7]
83913531Sjairo.balart@metempsy.com             * 1 of N wakeup functionality not supported, RAZ/WI
84013531Sjairo.balart@metempsy.com             * DS [6] - RAO/WI
84113531Sjairo.balart@metempsy.com             * ARE [4]
84213531Sjairo.balart@metempsy.com             * affinity routing always on, no GICv2 legacy, RAO/WI
84313531Sjairo.balart@metempsy.com             * EnableGrp1 [1]
84413531Sjairo.balart@metempsy.com             * EnableGrp0 [0]
84513531Sjairo.balart@metempsy.com             */
84613531Sjairo.balart@metempsy.com            if ((data & (1 << 4)) == 0) {
84713531Sjairo.balart@metempsy.com                warn("Gicv3Distributor::write(): "
84813531Sjairo.balart@metempsy.com                        "setting ARE to 0 is not supported!\n");
84913531Sjairo.balart@metempsy.com            }
85013531Sjairo.balart@metempsy.com
85113531Sjairo.balart@metempsy.com            EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
85213531Sjairo.balart@metempsy.com            EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
85313531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
85413531Sjairo.balart@metempsy.com                    "EnableGrp1NS %d EnableGrp0 %d\n",
85513531Sjairo.balart@metempsy.com                    EnableGrp1NS, EnableGrp0);
85613531Sjairo.balart@metempsy.com        } else {
85713531Sjairo.balart@metempsy.com            if (is_secure_access) {
85813531Sjairo.balart@metempsy.com                /*
85913531Sjairo.balart@metempsy.com                 * E1NWF [7]
86013531Sjairo.balart@metempsy.com                 * 1 of N wakeup functionality not supported, RAZ/WI
86113531Sjairo.balart@metempsy.com                 * DS [6]
86213531Sjairo.balart@metempsy.com                 * ARE_NS [5]
86313531Sjairo.balart@metempsy.com                 * affinity routing always on, no GICv2 legacy, RAO/WI
86413531Sjairo.balart@metempsy.com                 * ARE_S [4]
86513531Sjairo.balart@metempsy.com                 * affinity routing always on, no GICv2 legacy, RAO/WI
86613531Sjairo.balart@metempsy.com                 * EnableGrp1S [2]
86713531Sjairo.balart@metempsy.com                 * EnableGrp1NS [1]
86813531Sjairo.balart@metempsy.com                 * EnableGrp0 [0]
86913531Sjairo.balart@metempsy.com                 */
87013531Sjairo.balart@metempsy.com                if ((data & (1 << 5)) == 0) {
87113531Sjairo.balart@metempsy.com                    warn("Gicv3Distributor::write(): "
87213531Sjairo.balart@metempsy.com                            "setting ARE_NS to 0 is not supported!\n");
87313531Sjairo.balart@metempsy.com                }
87413531Sjairo.balart@metempsy.com
87513531Sjairo.balart@metempsy.com                if ((data & (1 << 4)) == 0) {
87613531Sjairo.balart@metempsy.com                    warn("Gicv3Distributor::write(): "
87713531Sjairo.balart@metempsy.com                            "setting ARE_S to 0 is not supported!\n");
87813531Sjairo.balart@metempsy.com                }
87913531Sjairo.balart@metempsy.com
88013531Sjairo.balart@metempsy.com                DS = data & GICD_CTLR_DS;
88113531Sjairo.balart@metempsy.com                EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S;
88213531Sjairo.balart@metempsy.com                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
88313531Sjairo.balart@metempsy.com                EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
88413531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
88513531Sjairo.balart@metempsy.com                        "DS %d "
88613531Sjairo.balart@metempsy.com                        "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
88713531Sjairo.balart@metempsy.com                        DS, EnableGrp1S, EnableGrp1NS, EnableGrp0);
88813531Sjairo.balart@metempsy.com
88913531Sjairo.balart@metempsy.com                if (data & GICD_CTLR_DS) {
89013531Sjairo.balart@metempsy.com                    EnableGrp1S = 0;
89113531Sjairo.balart@metempsy.com                }
89213531Sjairo.balart@metempsy.com            } else {
89313531Sjairo.balart@metempsy.com                /*
89413531Sjairo.balart@metempsy.com                 * ARE_NS [4] RAO/WI;
89513531Sjairo.balart@metempsy.com                 * EnableGrp1A [1] is a read-write alias of the Secure
89613531Sjairo.balart@metempsy.com                 * GICD_CTLR.EnableGrp1NS
89713531Sjairo.balart@metempsy.com                 * EnableGrp1 [0] RES0
89813531Sjairo.balart@metempsy.com                 */
89913531Sjairo.balart@metempsy.com                if ((data & (1 << 4)) == 0) {
90013531Sjairo.balart@metempsy.com                    warn("Gicv3Distributor::write(): "
90113531Sjairo.balart@metempsy.com                            "setting ARE_NS to 0 is not supported!\n");
90213531Sjairo.balart@metempsy.com                }
90313531Sjairo.balart@metempsy.com
90413531Sjairo.balart@metempsy.com                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A;
90513531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
90613531Sjairo.balart@metempsy.com                        "EnableGrp1NS %d\n", EnableGrp1NS);
90713531Sjairo.balart@metempsy.com            }
90813531Sjairo.balart@metempsy.com        }
90913531Sjairo.balart@metempsy.com
91014232Sgiacomo.travaglini@arm.com        update();
91114232Sgiacomo.travaglini@arm.com
91213531Sjairo.balart@metempsy.com        break;
91313531Sjairo.balart@metempsy.com
91414251Sgiacomo.travaglini@arm.com      case GICD_SGIR: // Error Reporting Status Register
91514251Sgiacomo.travaglini@arm.com        // Only if affinity routing is disabled, RES0
91614251Sgiacomo.travaglini@arm.com        break;
91714251Sgiacomo.travaglini@arm.com
91814253Sgiacomo.travaglini@arm.com      case GICD_SETSPI_NSR: {
91914253Sgiacomo.travaglini@arm.com        // Writes to this register have no effect if:
92014253Sgiacomo.travaglini@arm.com        // * The value written specifies an invalid SPI.
92114253Sgiacomo.travaglini@arm.com        // * The SPI is already pending.
92214253Sgiacomo.travaglini@arm.com        // * The value written specifies a Secure SPI, the value is
92314253Sgiacomo.travaglini@arm.com        // written by a Non-secure access, and the value of the
92414253Sgiacomo.travaglini@arm.com        // corresponding GICD_NSACR<n> register is 0.
92514253Sgiacomo.travaglini@arm.com        const uint32_t intid = bits(data, 9, 0);
92614253Sgiacomo.travaglini@arm.com        if (isNotSPI(intid) || irqPending[intid] ||
92714253Sgiacomo.travaglini@arm.com            (nsAccessToSecInt(intid, is_secure_access) &&
92814253Sgiacomo.travaglini@arm.com             irqNsacr[intid] == 0)) {
92914253Sgiacomo.travaglini@arm.com            return;
93014253Sgiacomo.travaglini@arm.com        } else {
93114253Sgiacomo.travaglini@arm.com            // Valid SPI, set interrupt pending
93214253Sgiacomo.travaglini@arm.com            sendInt(intid);
93314253Sgiacomo.travaglini@arm.com        }
93414253Sgiacomo.travaglini@arm.com        break;
93514253Sgiacomo.travaglini@arm.com      }
93614253Sgiacomo.travaglini@arm.com
93714253Sgiacomo.travaglini@arm.com      case GICD_CLRSPI_NSR: {
93814253Sgiacomo.travaglini@arm.com        // Writes to this register have no effect if:
93914253Sgiacomo.travaglini@arm.com        // * The value written specifies an invalid SPI.
94014253Sgiacomo.travaglini@arm.com        // * The SPI is not pending.
94114253Sgiacomo.travaglini@arm.com        // * The value written specifies a Secure SPI, the value is
94214253Sgiacomo.travaglini@arm.com        // written by a Non-secure access, and the value of the
94314253Sgiacomo.travaglini@arm.com        // corresponding GICD_NSACR<n> register is less than 0b10.
94414253Sgiacomo.travaglini@arm.com        const uint32_t intid = bits(data, 9, 0);
94514253Sgiacomo.travaglini@arm.com        if (isNotSPI(intid) || !irqPending[intid] ||
94614253Sgiacomo.travaglini@arm.com            (nsAccessToSecInt(intid, is_secure_access) &&
94714253Sgiacomo.travaglini@arm.com             irqNsacr[intid] < 2)) {
94814253Sgiacomo.travaglini@arm.com            return;
94914253Sgiacomo.travaglini@arm.com        } else {
95014253Sgiacomo.travaglini@arm.com            // Valid SPI, clear interrupt pending
95114253Sgiacomo.travaglini@arm.com            deassertSPI(intid);
95214253Sgiacomo.travaglini@arm.com        }
95314253Sgiacomo.travaglini@arm.com        break;
95414253Sgiacomo.travaglini@arm.com      }
95514253Sgiacomo.travaglini@arm.com
95614253Sgiacomo.travaglini@arm.com      case GICD_SETSPI_SR: {
95714253Sgiacomo.travaglini@arm.com        // Writes to this register have no effect if:
95814253Sgiacomo.travaglini@arm.com        // * GICD_CTLR.DS = 1 (WI)
95914253Sgiacomo.travaglini@arm.com        // * The value written specifies an invalid SPI.
96014253Sgiacomo.travaglini@arm.com        // * The SPI is already pending.
96114253Sgiacomo.travaglini@arm.com        // * The value is written by a Non-secure access.
96214253Sgiacomo.travaglini@arm.com        const uint32_t intid = bits(data, 9, 0);
96314253Sgiacomo.travaglini@arm.com        if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) {
96414253Sgiacomo.travaglini@arm.com            return;
96514253Sgiacomo.travaglini@arm.com        } else {
96614253Sgiacomo.travaglini@arm.com            // Valid SPI, set interrupt pending
96714253Sgiacomo.travaglini@arm.com            sendInt(intid);
96814253Sgiacomo.travaglini@arm.com        }
96914253Sgiacomo.travaglini@arm.com        break;
97014253Sgiacomo.travaglini@arm.com      }
97114253Sgiacomo.travaglini@arm.com
97214253Sgiacomo.travaglini@arm.com      case GICD_CLRSPI_SR: {
97314253Sgiacomo.travaglini@arm.com        // Writes to this register have no effect if:
97414253Sgiacomo.travaglini@arm.com        // * GICD_CTLR.DS = 1 (WI)
97514253Sgiacomo.travaglini@arm.com        // * The value written specifies an invalid SPI.
97614253Sgiacomo.travaglini@arm.com        // * The SPI is not pending.
97714253Sgiacomo.travaglini@arm.com        // * The value is written by a Non-secure access.
97814253Sgiacomo.travaglini@arm.com        const uint32_t intid = bits(data, 9, 0);
97914253Sgiacomo.travaglini@arm.com        if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) {
98014253Sgiacomo.travaglini@arm.com            return;
98114253Sgiacomo.travaglini@arm.com        } else {
98214253Sgiacomo.travaglini@arm.com            // Valid SPI, clear interrupt pending
98314253Sgiacomo.travaglini@arm.com            deassertSPI(intid);
98414253Sgiacomo.travaglini@arm.com        }
98514253Sgiacomo.travaglini@arm.com        break;
98614253Sgiacomo.travaglini@arm.com      }
98714253Sgiacomo.travaglini@arm.com
98813531Sjairo.balart@metempsy.com      default:
98913531Sjairo.balart@metempsy.com        panic("Gicv3Distributor::write(): invalid offset %#x\n", addr);
99013531Sjairo.balart@metempsy.com        break;
99113531Sjairo.balart@metempsy.com    }
99213531Sjairo.balart@metempsy.com}
99313531Sjairo.balart@metempsy.com
99413531Sjairo.balart@metempsy.comvoid
99513531Sjairo.balart@metempsy.comGicv3Distributor::sendInt(uint32_t int_id)
99613531Sjairo.balart@metempsy.com{
99713531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
99813531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
99913531Sjairo.balart@metempsy.com    irqPending[int_id] = true;
100013531Sjairo.balart@metempsy.com    DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
100113531Sjairo.balart@metempsy.com            "int_id %d (SPI) pending bit set\n", int_id);
100214231Sgiacomo.travaglini@arm.com    update();
100313531Sjairo.balart@metempsy.com}
100413531Sjairo.balart@metempsy.com
100513531Sjairo.balart@metempsy.comvoid
100613756Sjairo.balart@metempsy.comGicv3Distributor::deassertSPI(uint32_t int_id)
100713531Sjairo.balart@metempsy.com{
100813531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
100913531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
101013531Sjairo.balart@metempsy.com    irqPending[int_id] = false;
101114231Sgiacomo.travaglini@arm.com    clearIrqCpuInterface(int_id);
101214231Sgiacomo.travaglini@arm.com
101314231Sgiacomo.travaglini@arm.com    update();
101413531Sjairo.balart@metempsy.com}
101513531Sjairo.balart@metempsy.com
101614231Sgiacomo.travaglini@arm.comGicv3CPUInterface*
101714231Sgiacomo.travaglini@arm.comGicv3Distributor::route(uint32_t int_id)
101813531Sjairo.balart@metempsy.com{
101914231Sgiacomo.travaglini@arm.com    IROUTER affinity_routing = irqAffinityRouting[int_id];
102014231Sgiacomo.travaglini@arm.com    Gicv3Redistributor * target_redistributor = nullptr;
102113531Sjairo.balart@metempsy.com
102214231Sgiacomo.travaglini@arm.com    const Gicv3::GroupId int_group = getIntGroup(int_id);
102314231Sgiacomo.travaglini@arm.com
102414231Sgiacomo.travaglini@arm.com    if (affinity_routing.IRM) {
102514231Sgiacomo.travaglini@arm.com        // Interrupts routed to any PE defined as a participating node
102614231Sgiacomo.travaglini@arm.com        for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
102714231Sgiacomo.travaglini@arm.com            Gicv3Redistributor * redistributor_i =
102814231Sgiacomo.travaglini@arm.com                gic->getRedistributor(i);
102914231Sgiacomo.travaglini@arm.com
103014231Sgiacomo.travaglini@arm.com            if (redistributor_i->
103114231Sgiacomo.travaglini@arm.com                    canBeSelectedFor1toNInterrupt(int_group)) {
103214231Sgiacomo.travaglini@arm.com                target_redistributor = redistributor_i;
103314231Sgiacomo.travaglini@arm.com                break;
103414231Sgiacomo.travaglini@arm.com            }
103514231Sgiacomo.travaglini@arm.com        }
103614231Sgiacomo.travaglini@arm.com    } else {
103714231Sgiacomo.travaglini@arm.com        uint32_t affinity = (affinity_routing.Aff3 << 24) |
103814231Sgiacomo.travaglini@arm.com                            (affinity_routing.Aff2 << 16) |
103914231Sgiacomo.travaglini@arm.com                            (affinity_routing.Aff1 << 8) |
104014231Sgiacomo.travaglini@arm.com                            (affinity_routing.Aff0 << 0);
104114231Sgiacomo.travaglini@arm.com        target_redistributor =
104214231Sgiacomo.travaglini@arm.com            gic->getRedistributorByAffinity(affinity);
104314231Sgiacomo.travaglini@arm.com    }
104414231Sgiacomo.travaglini@arm.com
104514231Sgiacomo.travaglini@arm.com    if (!target_redistributor) {
104614231Sgiacomo.travaglini@arm.com        // Interrrupts targeting not present cpus must remain pending
104714231Sgiacomo.travaglini@arm.com        return nullptr;
104814231Sgiacomo.travaglini@arm.com    } else {
104914231Sgiacomo.travaglini@arm.com        return target_redistributor->getCPUInterface();
105013531Sjairo.balart@metempsy.com    }
105113531Sjairo.balart@metempsy.com}
105213531Sjairo.balart@metempsy.com
105313531Sjairo.balart@metempsy.comvoid
105414231Sgiacomo.travaglini@arm.comGicv3Distributor::clearIrqCpuInterface(uint32_t int_id)
105513531Sjairo.balart@metempsy.com{
105614231Sgiacomo.travaglini@arm.com    auto cpu_interface = route(int_id);
105714231Sgiacomo.travaglini@arm.com    if (cpu_interface)
105814259Sgiacomo.travaglini@arm.com        cpu_interface->resetHppi(int_id);
105913531Sjairo.balart@metempsy.com}
106013531Sjairo.balart@metempsy.com
106113531Sjairo.balart@metempsy.comvoid
106213531Sjairo.balart@metempsy.comGicv3Distributor::update()
106313531Sjairo.balart@metempsy.com{
106413531Sjairo.balart@metempsy.com    // Find the highest priority pending SPI
106513531Sjairo.balart@metempsy.com    for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
106613756Sjairo.balart@metempsy.com         int_id++) {
106713531Sjairo.balart@metempsy.com        Gicv3::GroupId int_group = getIntGroup(int_id);
106813531Sjairo.balart@metempsy.com        bool group_enabled = groupEnabled(int_group);
106913531Sjairo.balart@metempsy.com
107013531Sjairo.balart@metempsy.com        if (irqPending[int_id] && irqEnabled[int_id] &&
107113756Sjairo.balart@metempsy.com            !irqActive[int_id] && group_enabled) {
107213531Sjairo.balart@metempsy.com
107314231Sgiacomo.travaglini@arm.com            // Find the cpu interface where to route the interrupt
107414231Sgiacomo.travaglini@arm.com            Gicv3CPUInterface *target_cpu_interface = route(int_id);
107513531Sjairo.balart@metempsy.com
107614231Sgiacomo.travaglini@arm.com            // Invalid routing
107714231Sgiacomo.travaglini@arm.com            if (!target_cpu_interface) continue;
107813531Sjairo.balart@metempsy.com
107913531Sjairo.balart@metempsy.com            if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
108013756Sjairo.balart@metempsy.com                (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
108113756Sjairo.balart@metempsy.com                int_id < target_cpu_interface->hppi.intid)) {
108214231Sgiacomo.travaglini@arm.com
108313531Sjairo.balart@metempsy.com                target_cpu_interface->hppi.intid = int_id;
108413531Sjairo.balart@metempsy.com                target_cpu_interface->hppi.prio = irqPriority[int_id];
108513531Sjairo.balart@metempsy.com                target_cpu_interface->hppi.group = int_group;
108613531Sjairo.balart@metempsy.com            }
108713531Sjairo.balart@metempsy.com        }
108813531Sjairo.balart@metempsy.com    }
108913531Sjairo.balart@metempsy.com
109014231Sgiacomo.travaglini@arm.com    // Update all redistributors
109113531Sjairo.balart@metempsy.com    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
109214231Sgiacomo.travaglini@arm.com        gic->getRedistributor(i)->update();
109313531Sjairo.balart@metempsy.com    }
109413531Sjairo.balart@metempsy.com}
109513531Sjairo.balart@metempsy.com
109613531Sjairo.balart@metempsy.comGicv3::IntStatus
109713756Sjairo.balart@metempsy.comGicv3Distributor::intStatus(uint32_t int_id) const
109813531Sjairo.balart@metempsy.com{
109913531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
110013531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
110113531Sjairo.balart@metempsy.com
110213531Sjairo.balart@metempsy.com    if (irqPending[int_id]) {
110313531Sjairo.balart@metempsy.com        if (irqActive[int_id]) {
110413531Sjairo.balart@metempsy.com            return Gicv3::INT_ACTIVE_PENDING;
110513531Sjairo.balart@metempsy.com        }
110613531Sjairo.balart@metempsy.com
110713531Sjairo.balart@metempsy.com        return Gicv3::INT_PENDING;
110813531Sjairo.balart@metempsy.com    } else if (irqActive[int_id]) {
110913531Sjairo.balart@metempsy.com        return Gicv3::INT_ACTIVE;
111013531Sjairo.balart@metempsy.com    } else {
111113531Sjairo.balart@metempsy.com        return Gicv3::INT_INACTIVE;
111213531Sjairo.balart@metempsy.com    }
111313531Sjairo.balart@metempsy.com}
111413531Sjairo.balart@metempsy.com
111513531Sjairo.balart@metempsy.comGicv3::GroupId
111613756Sjairo.balart@metempsy.comGicv3Distributor::getIntGroup(int int_id) const
111713531Sjairo.balart@metempsy.com{
111813531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
111913531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
112013531Sjairo.balart@metempsy.com
112113531Sjairo.balart@metempsy.com    if (DS) {
112213531Sjairo.balart@metempsy.com        if (irqGroup[int_id] == 1) {
112313531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
112413531Sjairo.balart@metempsy.com        } else {
112513531Sjairo.balart@metempsy.com            return Gicv3::G0S;
112613531Sjairo.balart@metempsy.com        }
112713531Sjairo.balart@metempsy.com    } else {
112813531Sjairo.balart@metempsy.com        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
112913531Sjairo.balart@metempsy.com            return Gicv3::G0S;
113013531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
113113531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
113213531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
113313531Sjairo.balart@metempsy.com            return Gicv3::G1S;
113413531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
113513531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
113613531Sjairo.balart@metempsy.com        }
113713531Sjairo.balart@metempsy.com    }
113813531Sjairo.balart@metempsy.com
113913531Sjairo.balart@metempsy.com    M5_UNREACHABLE;
114013531Sjairo.balart@metempsy.com}
114113531Sjairo.balart@metempsy.com
114213531Sjairo.balart@metempsy.comvoid
114313531Sjairo.balart@metempsy.comGicv3Distributor::activateIRQ(uint32_t int_id)
114413531Sjairo.balart@metempsy.com{
114513531Sjairo.balart@metempsy.com    irqPending[int_id] = false;
114613531Sjairo.balart@metempsy.com    irqActive[int_id] = true;
114713531Sjairo.balart@metempsy.com}
114813531Sjairo.balart@metempsy.com
114913531Sjairo.balart@metempsy.comvoid
115013531Sjairo.balart@metempsy.comGicv3Distributor::deactivateIRQ(uint32_t int_id)
115113531Sjairo.balart@metempsy.com{
115213531Sjairo.balart@metempsy.com    irqActive[int_id] = false;
115313531Sjairo.balart@metempsy.com}
115413531Sjairo.balart@metempsy.com
115513531Sjairo.balart@metempsy.comvoid
115613531Sjairo.balart@metempsy.comGicv3Distributor::serialize(CheckpointOut & cp) const
115713531Sjairo.balart@metempsy.com{
115813531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(ARE);
115913531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(DS);
116013531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableGrp1S);
116113531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableGrp1NS);
116213531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableGrp0);
116313531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqGroup);
116413531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqEnabled);
116513531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqPending);
116613531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqActive);
116713531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqPriority);
116813531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqConfig);
116913531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqGrpmod);
117013531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqNsacr);
117113531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqAffinityRouting);
117213531Sjairo.balart@metempsy.com}
117313531Sjairo.balart@metempsy.com
117413531Sjairo.balart@metempsy.comvoid
117513531Sjairo.balart@metempsy.comGicv3Distributor::unserialize(CheckpointIn & cp)
117613531Sjairo.balart@metempsy.com{
117713531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(ARE);
117813531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(DS);
117913531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableGrp1S);
118013531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableGrp1NS);
118113531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableGrp0);
118213531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqGroup);
118313531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqEnabled);
118413531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqPending);
118513531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqActive);
118613531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqPriority);
118713531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqConfig);
118813531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqGrpmod);
118913531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqNsacr);
119013531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqAffinityRouting);
119113531Sjairo.balart@metempsy.com}
1192