gic_v3_distributor.cc revision 14232
12810SN/A/*
212724Snikos.nikoleris@arm.com * Copyright (c) 2019 ARM Limited
38856Sandreas.hansson@arm.com * All rights reserved
48856Sandreas.hansson@arm.com *
58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98856Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138856Sandreas.hansson@arm.com *
142810SN/A * Copyright (c) 2018 Metempsy Technology Consulting
152810SN/A * All rights reserved.
162810SN/A *
172810SN/A * Redistribution and use in source and binary forms, with or without
182810SN/A * modification, are permitted provided that the following conditions are
192810SN/A * met: redistributions of source code must retain the above copyright
202810SN/A * notice, this list of conditions and the following disclaimer;
212810SN/A * redistributions in binary form must reproduce the above copyright
222810SN/A * notice, this list of conditions and the following disclaimer in the
232810SN/A * documentation and/or other materials provided with the distribution;
242810SN/A * neither the name of the copyright holders nor the names of its
252810SN/A * contributors may be used to endorse or promote products derived from
262810SN/A * this software without specific prior written permission.
272810SN/A *
282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392810SN/A *
402810SN/A * Authors: Jairo Balart
4112724Snikos.nikoleris@arm.com */
422810SN/A
432810SN/A#include "dev/arm/gic_v3_distributor.hh"
442810SN/A
452810SN/A#include <algorithm>
462810SN/A
472810SN/A#include "debug/GIC.hh"
482810SN/A#include "dev/arm/gic_v3.hh"
4911486Snikos.nikoleris@arm.com#include "dev/arm/gic_v3_cpu_interface.hh"
5011486Snikos.nikoleris@arm.com#include "dev/arm/gic_v3_redistributor.hh"
5112724Snikos.nikoleris@arm.com
5212724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_IGROUPR   (0x0080, 0x00ff);
538232Snate@binkert.orgconst AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f);
5412724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff);
5513222Sodanrc@yahoo.com.brconst AddrRange Gicv3Distributor::GICD_ISPENDR   (0x0200, 0x027f);
5612724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICPENDR   (0x0280, 0x02ff);
5711486Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f);
5812724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff);
5912724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
6012724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff);
6113352Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICFGR     (0x0c00, 0x0cff);
6212724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_IGRPMODR  (0x0d00, 0x0d7f);
6312724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_NSACR     (0x0e00, 0x0eff);
6412724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f);
6512724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f);
662810SN/Aconst AddrRange Gicv3Distributor::GICD_IROUTER   (0x6000, 0x7fe0);
672810SN/A
682810SN/AGicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines)
698856Sandreas.hansson@arm.com    : gic(gic),
708856Sandreas.hansson@arm.com      itLines(it_lines),
718856Sandreas.hansson@arm.com      irqGroup(it_lines),
728922Swilliam.wang@arm.com      irqEnabled(it_lines),
7312084Sspwilson2@wisc.edu      irqPending(it_lines),
7412084Sspwilson2@wisc.edu      irqActive(it_lines),
758856Sandreas.hansson@arm.com      irqPriority(it_lines),
768856Sandreas.hansson@arm.com      irqConfig(it_lines),
774475SN/A      irqGrpmod(it_lines),
7811053Sandreas.hansson@arm.com      irqNsacr(it_lines),
795034SN/A      irqAffinityRouting(it_lines),
8012724Snikos.nikoleris@arm.com      gicdPidr0(0x92),
8112724Snikos.nikoleris@arm.com      gicdPidr1(0xb4),
8211377Sandreas.hansson@arm.com      gicdPidr2(0x3b),
8311377Sandreas.hansson@arm.com      gicdPidr3(0),
8412724Snikos.nikoleris@arm.com      gicdPidr4(0x44)
8512724Snikos.nikoleris@arm.com{
8613352Snikos.nikoleris@arm.com    panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
8712724Snikos.nikoleris@arm.com}
8812724Snikos.nikoleris@arm.com
8912724Snikos.nikoleris@arm.comvoid
9012724Snikos.nikoleris@arm.comGicv3Distributor::init()
9112724Snikos.nikoleris@arm.com{
9211053Sandreas.hansson@arm.com}
9311722Ssophiane.senni@gmail.com
9411722Ssophiane.senni@gmail.comvoid
9511722Ssophiane.senni@gmail.comGicv3Distributor::initState()
9611722Ssophiane.senni@gmail.com{
979263Smrinmoy.ghosh@arm.com    reset();
9813418Sodanrc@yahoo.com.br}
995034SN/A
10011331Sandreas.hansson@arm.comvoid
10112724Snikos.nikoleris@arm.comGicv3Distributor::reset()
10210884Sandreas.hansson@arm.com{
1034626SN/A    std::fill(irqGroup.begin(), irqGroup.end(), 0);
10410360Sandreas.hansson@arm.com    // Imp. defined reset value
10511484Snikos.nikoleris@arm.com    std::fill(irqEnabled.begin(), irqEnabled.end(), false);
1065034SN/A    std::fill(irqPending.begin(), irqPending.end(), false);
1078883SAli.Saidi@ARM.com    std::fill(irqActive.begin(), irqActive.end(), false);
1088833Sdam.sunwoo@arm.com    // Imp. defined reset value
1094458SN/A    std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA);
11011377Sandreas.hansson@arm.com    std::fill(irqConfig.begin(), irqConfig.end(),
11111377Sandreas.hansson@arm.com              Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value
11211377Sandreas.hansson@arm.com    std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
11311377Sandreas.hansson@arm.com    std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
11411377Sandreas.hansson@arm.com    /*
11511377Sandreas.hansson@arm.com     * For our implementation affinity routing is always enabled,
11611331Sandreas.hansson@arm.com     * no GICv2 legacy
11711331Sandreas.hansson@arm.com     */
11812724Snikos.nikoleris@arm.com    ARE = true;
11912843Srmk35@cl.cam.ac.uk
12012724Snikos.nikoleris@arm.com    if (gic->getSystem()->haveSecurity()) {
12113419Sodanrc@yahoo.com.br        DS = false;
12212724Snikos.nikoleris@arm.com    } else {
12312724Snikos.nikoleris@arm.com        DS = true;
12412724Snikos.nikoleris@arm.com    }
12512724Snikos.nikoleris@arm.com
12612724Snikos.nikoleris@arm.com    EnableGrp0 = 0;
12712724Snikos.nikoleris@arm.com    EnableGrp1NS = 0;
12812724Snikos.nikoleris@arm.com    EnableGrp1S = 0;
1292810SN/A}
1302810SN/A
1313013SN/Auint64_t
1328856Sandreas.hansson@arm.comGicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
1332810SN/A{
1343013SN/A    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
13510714Sandreas.hansson@arm.com        uint64_t val = 0x0;
1362810SN/A
1379614Srene.dejong@arm.com        if (!DS && !is_secure_access) {
1389614Srene.dejong@arm.com            // RAZ/WI for non-secure accesses
1399614Srene.dejong@arm.com            return 0;
14010345SCurtis.Dunham@arm.com        }
14110714Sandreas.hansson@arm.com
14210345SCurtis.Dunham@arm.com        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
1439614Srene.dejong@arm.com
1442810SN/A        if (isNotSPI(first_intid)) {
1452810SN/A            return 0;
1462810SN/A        }
1478856Sandreas.hansson@arm.com
1482810SN/A        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
1493013SN/A             i++, int_id++) {
15010714Sandreas.hansson@arm.com            val |= irqGroup[int_id] << i;
1513013SN/A        }
1528856Sandreas.hansson@arm.com
15310714Sandreas.hansson@arm.com        return val;
1548922Swilliam.wang@arm.com    } else if (GICD_ISENABLER.contains(addr)) {
1552897SN/A        // Interrupt Set-Enable Registers
1562810SN/A        uint64_t val = 0x0;
1572810SN/A        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
15810344Sandreas.hansson@arm.com
15910344Sandreas.hansson@arm.com        if (isNotSPI(first_intid)) {
16010344Sandreas.hansson@arm.com            return 0;
16110714Sandreas.hansson@arm.com        }
16210344Sandreas.hansson@arm.com
16310344Sandreas.hansson@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
16410344Sandreas.hansson@arm.com             i++, int_id++) {
16510713Sandreas.hansson@arm.com
16610344Sandreas.hansson@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
1672844SN/A            {
16812730Sodanrc@yahoo.com.br                continue;
16912730Sodanrc@yahoo.com.br            }
17012730Sodanrc@yahoo.com.br
17112730Sodanrc@yahoo.com.br            val |= irqEnabled[int_id] << i;
17212730Sodanrc@yahoo.com.br        }
17312730Sodanrc@yahoo.com.br
17412730Sodanrc@yahoo.com.br        return val;
17512730Sodanrc@yahoo.com.br    } else if (GICD_ICENABLER.contains(addr)) {
17612730Sodanrc@yahoo.com.br        // Interrupt Clear-Enable Registers
17712730Sodanrc@yahoo.com.br        uint64_t val = 0x0;
1782810SN/A        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
1792858SN/A
1802858SN/A        if (isNotSPI(first_intid)) {
18112724Snikos.nikoleris@arm.com            return 0;
1828922Swilliam.wang@arm.com        }
18312724Snikos.nikoleris@arm.com
18412724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
1852858SN/A             i++, int_id++) {
1862858SN/A
1879294Sandreas.hansson@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
1889294Sandreas.hansson@arm.com            {
1898922Swilliam.wang@arm.com                continue;
1908922Swilliam.wang@arm.com            }
19112724Snikos.nikoleris@arm.com
1928922Swilliam.wang@arm.com            val |= (irqEnabled[int_id] << i);
1938922Swilliam.wang@arm.com        }
1948922Swilliam.wang@arm.com
1958922Swilliam.wang@arm.com        return val;
1968922Swilliam.wang@arm.com    } else if (GICD_ISPENDR.contains(addr)) {
1979294Sandreas.hansson@arm.com        // Interrupt Set-Pending Registers
1989294Sandreas.hansson@arm.com        uint64_t val = 0x0;
1998922Swilliam.wang@arm.com        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
2008922Swilliam.wang@arm.com
20112724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
2028922Swilliam.wang@arm.com            return 0;
2038922Swilliam.wang@arm.com        }
2048922Swilliam.wang@arm.com
2058922Swilliam.wang@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
2064628SN/A             i++, int_id++) {
20710821Sandreas.hansson@arm.com
20810821Sandreas.hansson@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
20910821Sandreas.hansson@arm.com            {
21010821Sandreas.hansson@arm.com                if (irqNsacr[int_id] == 0) {
21110821Sandreas.hansson@arm.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
21210821Sandreas.hansson@arm.com                    continue;
21310821Sandreas.hansson@arm.com                }
21410821Sandreas.hansson@arm.com            }
21510821Sandreas.hansson@arm.com
21610821Sandreas.hansson@arm.com            val |= (irqPending[int_id] << i);
21710821Sandreas.hansson@arm.com        }
2182858SN/A
21912724Snikos.nikoleris@arm.com        return val;
22012724Snikos.nikoleris@arm.com    } else if (GICD_ICPENDR.contains(addr)) {
22112724Snikos.nikoleris@arm.com        // Interrupt Clear-Pending Registers
22212724Snikos.nikoleris@arm.com        uint64_t val = 0x0;
22312724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
22412724Snikos.nikoleris@arm.com
22512724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
22612724Snikos.nikoleris@arm.com            return 0;
22712724Snikos.nikoleris@arm.com        }
22812724Snikos.nikoleris@arm.com
22913418Sodanrc@yahoo.com.br        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
23013418Sodanrc@yahoo.com.br             i++, int_id++) {
23112724Snikos.nikoleris@arm.com
23212724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
23312724Snikos.nikoleris@arm.com            {
23412724Snikos.nikoleris@arm.com                if (irqNsacr[int_id] < 2) {
23512724Snikos.nikoleris@arm.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
23612724Snikos.nikoleris@arm.com                    continue;
23712724Snikos.nikoleris@arm.com                }
23812724Snikos.nikoleris@arm.com            }
23912724Snikos.nikoleris@arm.com
24012724Snikos.nikoleris@arm.com            val |= (irqPending[int_id] << i);
24112724Snikos.nikoleris@arm.com        }
24212724Snikos.nikoleris@arm.com
24312724Snikos.nikoleris@arm.com        return val;
24412724Snikos.nikoleris@arm.com    } else if (GICD_ISACTIVER.contains(addr)) {
24512724Snikos.nikoleris@arm.com        // Interrupt Set-Active Registers
24612724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
24712724Snikos.nikoleris@arm.com
24813352Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
24913352Snikos.nikoleris@arm.com            return 0;
25013352Snikos.nikoleris@arm.com        }
25113352Snikos.nikoleris@arm.com
25213352Snikos.nikoleris@arm.com        uint64_t val = 0x0;
25313352Snikos.nikoleris@arm.com
25412724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
25512724Snikos.nikoleris@arm.com             i++, int_id++) {
25612724Snikos.nikoleris@arm.com
25712724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
25812724Snikos.nikoleris@arm.com            {
25912724Snikos.nikoleris@arm.com                // Group 0 or Secure Group 1 interrupts are RAZ/WI
26012724Snikos.nikoleris@arm.com                if (irqNsacr[int_id] < 2) {
26112724Snikos.nikoleris@arm.com                    continue;
26212724Snikos.nikoleris@arm.com                }
26312724Snikos.nikoleris@arm.com            }
26412724Snikos.nikoleris@arm.com
26512724Snikos.nikoleris@arm.com            val |= (irqActive[int_id] << i);
26612724Snikos.nikoleris@arm.com        }
26712724Snikos.nikoleris@arm.com
26812724Snikos.nikoleris@arm.com        return val;
26912724Snikos.nikoleris@arm.com    } else if (GICD_ICACTIVER.contains(addr)) {
27012724Snikos.nikoleris@arm.com        // Interrupt Clear-Active Registers
27112724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
27212724Snikos.nikoleris@arm.com
27312724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
27412724Snikos.nikoleris@arm.com            return 0;
27512724Snikos.nikoleris@arm.com        }
27612724Snikos.nikoleris@arm.com
27712724Snikos.nikoleris@arm.com        uint64_t val = 0x0;
27812724Snikos.nikoleris@arm.com
27912724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
28012724Snikos.nikoleris@arm.com             i++, int_id++) {
28112724Snikos.nikoleris@arm.com
28212724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
28312724Snikos.nikoleris@arm.com            {
28412724Snikos.nikoleris@arm.com                if (irqNsacr[int_id] < 2) {
28512724Snikos.nikoleris@arm.com                    continue;
28612724Snikos.nikoleris@arm.com                }
28712724Snikos.nikoleris@arm.com            }
28812724Snikos.nikoleris@arm.com
28912724Snikos.nikoleris@arm.com            val |= (irqActive[int_id] << i);
29012724Snikos.nikoleris@arm.com        }
29112724Snikos.nikoleris@arm.com
29212724Snikos.nikoleris@arm.com        return val;
29312724Snikos.nikoleris@arm.com    } else if (GICD_IPRIORITYR.contains(addr)) {
29412724Snikos.nikoleris@arm.com        // Interrupt Priority Registers
29512724Snikos.nikoleris@arm.com        uint64_t val = 0x0;
29612724Snikos.nikoleris@arm.com        int first_intid = addr - GICD_IPRIORITYR.start();
29712724Snikos.nikoleris@arm.com
29812724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
29912724Snikos.nikoleris@arm.com            return 0;
30012724Snikos.nikoleris@arm.com        }
30112724Snikos.nikoleris@arm.com
30212724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
30312724Snikos.nikoleris@arm.com             i++, int_id++) {
30412724Snikos.nikoleris@arm.com
30512724Snikos.nikoleris@arm.com            uint8_t prio = irqPriority[int_id];
30612724Snikos.nikoleris@arm.com
30712724Snikos.nikoleris@arm.com            if (!DS && !is_secure_access) {
30812724Snikos.nikoleris@arm.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
30912724Snikos.nikoleris@arm.com                    // RAZ/WI for non-secure accesses for secure interrupts
31012724Snikos.nikoleris@arm.com                    continue;
31112724Snikos.nikoleris@arm.com                } else {
31212724Snikos.nikoleris@arm.com                    // NS view
31312724Snikos.nikoleris@arm.com                    prio = (prio << 1) & 0xff;
31412724Snikos.nikoleris@arm.com                }
31512724Snikos.nikoleris@arm.com            }
31612724Snikos.nikoleris@arm.com
31712724Snikos.nikoleris@arm.com            val |= prio << (i * 8);
31812724Snikos.nikoleris@arm.com        }
31912724Snikos.nikoleris@arm.com
32012724Snikos.nikoleris@arm.com        return val;
32112724Snikos.nikoleris@arm.com    } else if (GICD_ITARGETSR.contains(addr)) {
32212724Snikos.nikoleris@arm.com        // Interrupt Processor Targets Registers
32312724Snikos.nikoleris@arm.com        // ARE always on, RAZ/WI
32412724Snikos.nikoleris@arm.com        warn("Gicv3Distributor::read(): "
32512724Snikos.nikoleris@arm.com             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
32612724Snikos.nikoleris@arm.com        return 0;
32712724Snikos.nikoleris@arm.com    } else if (GICD_ICFGR.contains(addr)) {
32812724Snikos.nikoleris@arm.com        // Interrupt Configuration Registers
32912724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ICFGR.start()) * 4;
33012724Snikos.nikoleris@arm.com
33112724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
33212724Snikos.nikoleris@arm.com            return 0;
33312724Snikos.nikoleris@arm.com        }
33412724Snikos.nikoleris@arm.com
33512724Snikos.nikoleris@arm.com        uint64_t val = 0x0;
33612724Snikos.nikoleris@arm.com
33712724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
33812724Snikos.nikoleris@arm.com             i = i + 2, int_id++) {
33912724Snikos.nikoleris@arm.com
34012724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
34112724Snikos.nikoleris@arm.com            {
34212724Snikos.nikoleris@arm.com                continue;
34312724Snikos.nikoleris@arm.com            }
34412724Snikos.nikoleris@arm.com
34512724Snikos.nikoleris@arm.com            if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
34613418Sodanrc@yahoo.com.br                val |= (0x2 << i);
34712724Snikos.nikoleris@arm.com            }
34812724Snikos.nikoleris@arm.com        }
34912724Snikos.nikoleris@arm.com
35012724Snikos.nikoleris@arm.com        return val;
35112724Snikos.nikoleris@arm.com    } else if (GICD_IGRPMODR.contains(addr)) {
35213418Sodanrc@yahoo.com.br        // Interrupt Group Modifier Registers
35312724Snikos.nikoleris@arm.com        if (DS) {
35412724Snikos.nikoleris@arm.com            // RAZ/WI if security disabled
35512724Snikos.nikoleris@arm.com            return 0;
35612820Srmk35@cl.cam.ac.uk        } else {
35712724Snikos.nikoleris@arm.com            if (!is_secure_access) {
35812724Snikos.nikoleris@arm.com                // RAZ/WI for non-secure accesses
35912724Snikos.nikoleris@arm.com                return 0;
36012724Snikos.nikoleris@arm.com            } else {
36112724Snikos.nikoleris@arm.com                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
36213418Sodanrc@yahoo.com.br
36312724Snikos.nikoleris@arm.com                if (isNotSPI(first_intid)) {
36412724Snikos.nikoleris@arm.com                    return 0;
36512724Snikos.nikoleris@arm.com                }
36612724Snikos.nikoleris@arm.com
36712724Snikos.nikoleris@arm.com                uint64_t val = 0x0;
36812724Snikos.nikoleris@arm.com
36912724Snikos.nikoleris@arm.com                for (int i = 0, int_id = first_intid;
37013416Sjavier.bueno@metempsy.com                     i < 8 * size && int_id < itLines; i++, int_id++) {
37113416Sjavier.bueno@metempsy.com                    val |= irqGrpmod[int_id] << i;
37213416Sjavier.bueno@metempsy.com                }
37312724Snikos.nikoleris@arm.com
37413416Sjavier.bueno@metempsy.com                return val;
37513416Sjavier.bueno@metempsy.com            }
37612724Snikos.nikoleris@arm.com        }
37712724Snikos.nikoleris@arm.com    } else if (GICD_NSACR.contains(addr)) {
37812724Snikos.nikoleris@arm.com        // Non-secure Access Control Registers
37912724Snikos.nikoleris@arm.com        // 2 bits per interrupt
38012724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_NSACR.start()) * 4;
38112724Snikos.nikoleris@arm.com
38213416Sjavier.bueno@metempsy.com        if (isNotSPI(first_intid)) {
38312724Snikos.nikoleris@arm.com            return 0;
38412724Snikos.nikoleris@arm.com        }
38513416Sjavier.bueno@metempsy.com
38613416Sjavier.bueno@metempsy.com        if (DS || (!DS && !is_secure_access)) {
38713416Sjavier.bueno@metempsy.com            return 0;
38813416Sjavier.bueno@metempsy.com        }
38913416Sjavier.bueno@metempsy.com
39013416Sjavier.bueno@metempsy.com        uint64_t val = 0x0;
39112724Snikos.nikoleris@arm.com
39212724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid;
39312724Snikos.nikoleris@arm.com             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
39412724Snikos.nikoleris@arm.com            val |= irqNsacr[int_id] << i;
39512724Snikos.nikoleris@arm.com        }
39612724Snikos.nikoleris@arm.com
39712724Snikos.nikoleris@arm.com        return val;
39812724Snikos.nikoleris@arm.com    } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
39912724Snikos.nikoleris@arm.com        // ARE always on, RAZ/WI
40012724Snikos.nikoleris@arm.com        warn("Gicv3Distributor::read(): "
40112724Snikos.nikoleris@arm.com             "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
40212724Snikos.nikoleris@arm.com        return 0x0;
40312724Snikos.nikoleris@arm.com    } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
40412724Snikos.nikoleris@arm.com        // ARE always on, RAZ/WI
40512724Snikos.nikoleris@arm.com        warn("Gicv3Distributor::read(): "
40612724Snikos.nikoleris@arm.com             "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
40712724Snikos.nikoleris@arm.com        return 0x0;
40812724Snikos.nikoleris@arm.com    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
40912724Snikos.nikoleris@arm.com        // 64 bit registers. 2 or 1 access.
41012724Snikos.nikoleris@arm.com        int int_id = (addr - GICD_IROUTER.start()) / 8;
41112724Snikos.nikoleris@arm.com
41212724Snikos.nikoleris@arm.com        if (isNotSPI(int_id)) {
41312724Snikos.nikoleris@arm.com            return 0;
41412724Snikos.nikoleris@arm.com        }
41512724Snikos.nikoleris@arm.com
41612724Snikos.nikoleris@arm.com        if (nsAccessToSecInt(int_id, is_secure_access))
41712724Snikos.nikoleris@arm.com        {
41812724Snikos.nikoleris@arm.com            if (irqNsacr[int_id] < 3) {
41912724Snikos.nikoleris@arm.com                return 0;
42012724Snikos.nikoleris@arm.com            }
42112724Snikos.nikoleris@arm.com        }
42212724Snikos.nikoleris@arm.com
42312724Snikos.nikoleris@arm.com        if (size == 4) {
42412724Snikos.nikoleris@arm.com            if (addr & 7) { // high half of 64 bit register
42512724Snikos.nikoleris@arm.com                return irqAffinityRouting[int_id] >> 32;
42612724Snikos.nikoleris@arm.com            } else { // high low of 64 bit register
42712724Snikos.nikoleris@arm.com                return irqAffinityRouting[int_id] & 0xFFFFFFFF;
42812724Snikos.nikoleris@arm.com            }
42912724Snikos.nikoleris@arm.com        } else {
43012724Snikos.nikoleris@arm.com            return irqAffinityRouting[int_id];
43112724Snikos.nikoleris@arm.com        }
43212724Snikos.nikoleris@arm.com    }
43312724Snikos.nikoleris@arm.com
43412724Snikos.nikoleris@arm.com    switch (addr) {
43512724Snikos.nikoleris@arm.com      case GICD_CTLR: // Control Register
43612724Snikos.nikoleris@arm.com        if (!DS) {
43712724Snikos.nikoleris@arm.com            if (is_secure_access) {
43812724Snikos.nikoleris@arm.com                // E1NWF [7] RAZ/WI
43912724Snikos.nikoleris@arm.com                // DS [6] - Disable Security
44012724Snikos.nikoleris@arm.com                // ARE_NS [5] RAO/WI
44112724Snikos.nikoleris@arm.com                // ARE_S [4] RAO/WI
44212724Snikos.nikoleris@arm.com                // EnableGrp1S [2]
44312724Snikos.nikoleris@arm.com                // EnableGrp1NS [1]
44412724Snikos.nikoleris@arm.com                // EnableGrp0 [0]
44512724Snikos.nikoleris@arm.com                return (EnableGrp0 << 0) |
44612724Snikos.nikoleris@arm.com                    (EnableGrp1NS << 1) |
44712724Snikos.nikoleris@arm.com                    (EnableGrp1S << 2) |
44812724Snikos.nikoleris@arm.com                    (1 << 4) |
44912724Snikos.nikoleris@arm.com                    (1 << 5) |
45012724Snikos.nikoleris@arm.com                    (DS << 6);
45112724Snikos.nikoleris@arm.com            } else {
45212724Snikos.nikoleris@arm.com                // ARE_NS [4] RAO/WI;
45312724Snikos.nikoleris@arm.com                // EnableGrp1A [1] is a read-write alias of the Secure
45412724Snikos.nikoleris@arm.com                // GICD_CTLR.EnableGrp1NS
45512724Snikos.nikoleris@arm.com                // EnableGrp1 [0] RES0
45612724Snikos.nikoleris@arm.com                return (1 << 4) | (EnableGrp1NS << 1);
45712724Snikos.nikoleris@arm.com            }
45812724Snikos.nikoleris@arm.com        } else {
45912724Snikos.nikoleris@arm.com            return (DS << 6) | (ARE << 4) |
46012724Snikos.nikoleris@arm.com                (EnableGrp1NS << 1) | (EnableGrp0 << 0);
46112724Snikos.nikoleris@arm.com        }
46212724Snikos.nikoleris@arm.com
46313350Snikos.nikoleris@arm.com      case GICD_TYPER: // Interrupt Controller Type Register
46413350Snikos.nikoleris@arm.com        /*
46513350Snikos.nikoleris@arm.com         * RSS           [26]    == 1
46613350Snikos.nikoleris@arm.com         * (The implementation does supports targeted SGIs with affinity
46713350Snikos.nikoleris@arm.com         * level 0 values of 0 - 255)
46813350Snikos.nikoleris@arm.com         * No1N          [25]    == 1
46912724Snikos.nikoleris@arm.com         * (1 of N SPI interrupts are not supported)
47012724Snikos.nikoleris@arm.com         * A3V           [24]    == 1
47112724Snikos.nikoleris@arm.com         * (Supports nonzero values of Affinity level 3)
47212724Snikos.nikoleris@arm.com         * IDbits        [23:19] == 0xf
47312724Snikos.nikoleris@arm.com         * (The number of interrupt identifier bits supported, minus one)
47412724Snikos.nikoleris@arm.com         * DVIS          [18]    == 0
47512724Snikos.nikoleris@arm.com         * (The implementation does not support Direct Virtual LPI
47613352Snikos.nikoleris@arm.com         * injection)
47713352Snikos.nikoleris@arm.com         * LPIS          [17]    == 1
47813352Snikos.nikoleris@arm.com         * (The implementation does not support LPIs)
47912724Snikos.nikoleris@arm.com         * MBIS          [16]    == 0
48012724Snikos.nikoleris@arm.com         * (The implementation does not support message-based interrupts
48112724Snikos.nikoleris@arm.com         * by writing to Distributor registers)
48212724Snikos.nikoleris@arm.com         * SecurityExtn  [10]    == X
48312724Snikos.nikoleris@arm.com         * (The GIC implementation supports two Security states)
48412724Snikos.nikoleris@arm.com         * CPUNumber     [7:5]   == 0
48512724Snikos.nikoleris@arm.com         * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
48612794Snikos.nikoleris@arm.com         * ITLinesNumber [4:0]   == N
48712794Snikos.nikoleris@arm.com         * (MaxSPIIntId = 32 (N + 1) - 1)
48812794Snikos.nikoleris@arm.com         */
48912794Snikos.nikoleris@arm.com        {
49012794Snikos.nikoleris@arm.com            int max_spi_int_id = itLines - 1;
49112794Snikos.nikoleris@arm.com            int it_lines_number = ceil((max_spi_int_id + 1) / 32.0) - 1;
49212724Snikos.nikoleris@arm.com            return (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) |
49312724Snikos.nikoleris@arm.com                (1 << 17) | (gic->getSystem()->haveSecurity() << 10) |
49412724Snikos.nikoleris@arm.com                (it_lines_number << 0);
49512724Snikos.nikoleris@arm.com        }
49612724Snikos.nikoleris@arm.com
49712724Snikos.nikoleris@arm.com      case GICD_IIDR: // Implementer Identification Register
49812724Snikos.nikoleris@arm.com        //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
49912724Snikos.nikoleris@arm.com        return 0;
50012724Snikos.nikoleris@arm.com
50113478Sodanrc@yahoo.com.br      case GICD_STATUSR: // Error Reporting Status Register
50212724Snikos.nikoleris@arm.com        // Optional register, RAZ/WI
50312724Snikos.nikoleris@arm.com        return 0x0;
50412724Snikos.nikoleris@arm.com
50512724Snikos.nikoleris@arm.com      case GICD_PIDR0: // Peripheral ID0 Register
50612724Snikos.nikoleris@arm.com        return gicdPidr0;
50712724Snikos.nikoleris@arm.com
50812724Snikos.nikoleris@arm.com      case GICD_PIDR1: // Peripheral ID1 Register
50912724Snikos.nikoleris@arm.com        return gicdPidr1;
51012724Snikos.nikoleris@arm.com
51112724Snikos.nikoleris@arm.com      case GICD_PIDR2: // Peripheral ID2 Register
51212724Snikos.nikoleris@arm.com        return gicdPidr2;
51312724Snikos.nikoleris@arm.com
51412724Snikos.nikoleris@arm.com      case GICD_PIDR3: // Peripheral ID3 Register
51512724Snikos.nikoleris@arm.com        return gicdPidr3;
51612724Snikos.nikoleris@arm.com
51712724Snikos.nikoleris@arm.com      case GICD_PIDR4: // Peripheral ID4 Register
51812724Snikos.nikoleris@arm.com        return gicdPidr4;
51912724Snikos.nikoleris@arm.com
52012724Snikos.nikoleris@arm.com      case GICD_PIDR5: // Peripheral ID5 Register
52112724Snikos.nikoleris@arm.com      case GICD_PIDR6: // Peripheral ID6 Register
52212724Snikos.nikoleris@arm.com      case GICD_PIDR7: // Peripheral ID7 Register
52312724Snikos.nikoleris@arm.com        return 0; // RES0
52412724Snikos.nikoleris@arm.com
52512724Snikos.nikoleris@arm.com      default:
52612724Snikos.nikoleris@arm.com        panic("Gicv3Distributor::read(): invalid offset %#x\n", addr);
52712724Snikos.nikoleris@arm.com        break;
52812724Snikos.nikoleris@arm.com    }
52912724Snikos.nikoleris@arm.com}
53012724Snikos.nikoleris@arm.com
53112724Snikos.nikoleris@arm.comvoid
53212724Snikos.nikoleris@arm.comGicv3Distributor::write(Addr addr, uint64_t data, size_t size,
53312724Snikos.nikoleris@arm.com                        bool is_secure_access)
53412724Snikos.nikoleris@arm.com{
53512724Snikos.nikoleris@arm.com    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
53612724Snikos.nikoleris@arm.com        if (!DS && !is_secure_access) {
53712724Snikos.nikoleris@arm.com            // RAZ/WI for non-secure accesses
53812724Snikos.nikoleris@arm.com            return;
53912724Snikos.nikoleris@arm.com        }
54012724Snikos.nikoleris@arm.com
54112724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
54212724Snikos.nikoleris@arm.com
54312724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
54412724Snikos.nikoleris@arm.com            return;
54512724Snikos.nikoleris@arm.com        }
54612724Snikos.nikoleris@arm.com
54712724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
54812724Snikos.nikoleris@arm.com             i++, int_id++) {
54912724Snikos.nikoleris@arm.com            irqGroup[int_id] = data & (1 << i) ? 1 : 0;
55012724Snikos.nikoleris@arm.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
55112724Snikos.nikoleris@arm.com                    int_id, irqGroup[int_id]);
55213412Snikos.nikoleris@arm.com        }
55313412Snikos.nikoleris@arm.com
55413412Snikos.nikoleris@arm.com        return;
55513412Snikos.nikoleris@arm.com    } else if (GICD_ISENABLER.contains(addr)) {
55612724Snikos.nikoleris@arm.com        // Interrupt Set-Enable Registers
55712724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
55812724Snikos.nikoleris@arm.com
55912724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
56012724Snikos.nikoleris@arm.com            return;
56112724Snikos.nikoleris@arm.com        }
56212724Snikos.nikoleris@arm.com
56312724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
56412724Snikos.nikoleris@arm.com             i++, int_id++) {
56512724Snikos.nikoleris@arm.com
56612724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
56712724Snikos.nikoleris@arm.com            {
56812724Snikos.nikoleris@arm.com                continue;
56912724Snikos.nikoleris@arm.com            }
57012724Snikos.nikoleris@arm.com
57112724Snikos.nikoleris@arm.com            bool enable = data & (1 << i) ? 1 : 0;
57212724Snikos.nikoleris@arm.com
57312820Srmk35@cl.cam.ac.uk            if (enable) {
57412724Snikos.nikoleris@arm.com                if (!irqEnabled[int_id]) {
57512724Snikos.nikoleris@arm.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
57612724Snikos.nikoleris@arm.com                            "int_id %d enabled\n", int_id);
57712724Snikos.nikoleris@arm.com                }
57812724Snikos.nikoleris@arm.com
57912724Snikos.nikoleris@arm.com                irqEnabled[int_id] = true;
58012724Snikos.nikoleris@arm.com            }
58112724Snikos.nikoleris@arm.com        }
58212724Snikos.nikoleris@arm.com
58312724Snikos.nikoleris@arm.com        return;
58412724Snikos.nikoleris@arm.com    } else if (GICD_ICENABLER.contains(addr)) {
58512724Snikos.nikoleris@arm.com        // Interrupt Clear-Enable Registers
58612724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
58712724Snikos.nikoleris@arm.com
58812724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
58912724Snikos.nikoleris@arm.com            return;
59012724Snikos.nikoleris@arm.com        }
59112724Snikos.nikoleris@arm.com
59212724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
59312724Snikos.nikoleris@arm.com             i++, int_id++) {
59412724Snikos.nikoleris@arm.com
59512724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
59612724Snikos.nikoleris@arm.com            {
59712724Snikos.nikoleris@arm.com                continue;
59812724Snikos.nikoleris@arm.com            }
59912724Snikos.nikoleris@arm.com
60012724Snikos.nikoleris@arm.com            bool disable = data & (1 << i) ? 1 : 0;
60112724Snikos.nikoleris@arm.com
60212724Snikos.nikoleris@arm.com            if (disable) {
60312724Snikos.nikoleris@arm.com                if (irqEnabled[int_id]) {
60412724Snikos.nikoleris@arm.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
60512724Snikos.nikoleris@arm.com                            "int_id %d disabled\n", int_id);
60612724Snikos.nikoleris@arm.com                }
60712724Snikos.nikoleris@arm.com
60812724Snikos.nikoleris@arm.com                irqEnabled[int_id] = false;
60912724Snikos.nikoleris@arm.com            }
61012724Snikos.nikoleris@arm.com        }
61112724Snikos.nikoleris@arm.com
61212724Snikos.nikoleris@arm.com        return;
61312724Snikos.nikoleris@arm.com    } else if (GICD_ISPENDR.contains(addr)) {
61412724Snikos.nikoleris@arm.com        // Interrupt Set-Pending Registers
61512724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
61612724Snikos.nikoleris@arm.com
61712724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
61812724Snikos.nikoleris@arm.com            return;
61912724Snikos.nikoleris@arm.com        }
62012724Snikos.nikoleris@arm.com
62112724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
62212724Snikos.nikoleris@arm.com             i++, int_id++) {
62312724Snikos.nikoleris@arm.com
62412724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
62512724Snikos.nikoleris@arm.com            {
62612724Snikos.nikoleris@arm.com                if (irqNsacr[int_id] == 0) {
62712724Snikos.nikoleris@arm.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
62812724Snikos.nikoleris@arm.com                    continue;
62912724Snikos.nikoleris@arm.com                }
63012724Snikos.nikoleris@arm.com            }
63112724Snikos.nikoleris@arm.com
63212724Snikos.nikoleris@arm.com            bool pending = data & (1 << i) ? 1 : 0;
63312724Snikos.nikoleris@arm.com
63412724Snikos.nikoleris@arm.com            if (pending) {
63512724Snikos.nikoleris@arm.com                DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
63612724Snikos.nikoleris@arm.com                        "int_id %d (SPI) pending bit set\n", int_id);
63712724Snikos.nikoleris@arm.com                irqPending[int_id] = true;
63812724Snikos.nikoleris@arm.com            }
63912724Snikos.nikoleris@arm.com        }
64012724Snikos.nikoleris@arm.com
64112724Snikos.nikoleris@arm.com        update();
64212724Snikos.nikoleris@arm.com        return;
64312724Snikos.nikoleris@arm.com    } else if (GICD_ICPENDR.contains(addr)) {
64412823Srmk35@cl.cam.ac.uk        // Interrupt Clear-Pending Registers
64512823Srmk35@cl.cam.ac.uk        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
64612724Snikos.nikoleris@arm.com
64712724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
64812724Snikos.nikoleris@arm.com            return;
64912724Snikos.nikoleris@arm.com        }
65012724Snikos.nikoleris@arm.com
65112724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
65212724Snikos.nikoleris@arm.com             i++, int_id++) {
65312724Snikos.nikoleris@arm.com
65412823Srmk35@cl.cam.ac.uk            if (nsAccessToSecInt(int_id, is_secure_access))
65512823Srmk35@cl.cam.ac.uk            {
65612823Srmk35@cl.cam.ac.uk                if (irqNsacr[int_id] < 2) {
65712823Srmk35@cl.cam.ac.uk                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
65812724Snikos.nikoleris@arm.com                    continue;
65912724Snikos.nikoleris@arm.com                }
66012724Snikos.nikoleris@arm.com            }
66112724Snikos.nikoleris@arm.com
66212724Snikos.nikoleris@arm.com            bool clear = data & (1 << i) ? 1 : 0;
66312724Snikos.nikoleris@arm.com
66412724Snikos.nikoleris@arm.com            if (clear) {
66512724Snikos.nikoleris@arm.com                irqPending[int_id] = false;
66612724Snikos.nikoleris@arm.com                clearIrqCpuInterface(int_id);
66712724Snikos.nikoleris@arm.com            }
66812724Snikos.nikoleris@arm.com        }
66912724Snikos.nikoleris@arm.com
67012724Snikos.nikoleris@arm.com        update();
67112724Snikos.nikoleris@arm.com        return;
67212724Snikos.nikoleris@arm.com    } else if (GICD_ISACTIVER.contains(addr)) {
67312724Snikos.nikoleris@arm.com        // Interrupt Set-Active Registers
67412724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
67512724Snikos.nikoleris@arm.com
67612724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
67712724Snikos.nikoleris@arm.com            return;
67812724Snikos.nikoleris@arm.com        }
67912724Snikos.nikoleris@arm.com
68012724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
68112724Snikos.nikoleris@arm.com             i++, int_id++) {
68212724Snikos.nikoleris@arm.com
68312724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
68412724Snikos.nikoleris@arm.com            {
68512724Snikos.nikoleris@arm.com                continue;
68612724Snikos.nikoleris@arm.com            }
68712724Snikos.nikoleris@arm.com
68812724Snikos.nikoleris@arm.com            bool active = data & (1 << i) ? 1 : 0;
68912724Snikos.nikoleris@arm.com
69012724Snikos.nikoleris@arm.com            if (active) {
69112724Snikos.nikoleris@arm.com                irqActive[int_id] = 1;
69212724Snikos.nikoleris@arm.com            }
69312724Snikos.nikoleris@arm.com        }
69412724Snikos.nikoleris@arm.com
69512724Snikos.nikoleris@arm.com        return;
69612724Snikos.nikoleris@arm.com    } else if (GICD_ICACTIVER.contains(addr)) {
69712724Snikos.nikoleris@arm.com        // Interrupt Clear-Active Registers
69812724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
69912724Snikos.nikoleris@arm.com
70012724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
70112724Snikos.nikoleris@arm.com            return;
70212724Snikos.nikoleris@arm.com        }
70312724Snikos.nikoleris@arm.com
70412724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
70512724Snikos.nikoleris@arm.com             i++, int_id++) {
70612724Snikos.nikoleris@arm.com
70712724Snikos.nikoleris@arm.com            if (nsAccessToSecInt(int_id, is_secure_access))
70812724Snikos.nikoleris@arm.com            {
70912724Snikos.nikoleris@arm.com                continue;
71012724Snikos.nikoleris@arm.com            }
71112724Snikos.nikoleris@arm.com
71212724Snikos.nikoleris@arm.com            bool clear = data & (1 << i) ? 1 : 0;
71312724Snikos.nikoleris@arm.com
71412724Snikos.nikoleris@arm.com            if (clear) {
71512724Snikos.nikoleris@arm.com                if (irqActive[int_id]) {
71612724Snikos.nikoleris@arm.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
71712724Snikos.nikoleris@arm.com                            "int_id %d active cleared\n", int_id);
71812724Snikos.nikoleris@arm.com                }
71912724Snikos.nikoleris@arm.com
72012724Snikos.nikoleris@arm.com                irqActive[int_id] = false;
72112724Snikos.nikoleris@arm.com            }
72212724Snikos.nikoleris@arm.com        }
72312724Snikos.nikoleris@arm.com
72412724Snikos.nikoleris@arm.com        return;
72512724Snikos.nikoleris@arm.com    } else if (GICD_IPRIORITYR.contains(addr)) {
72612724Snikos.nikoleris@arm.com        // Interrupt Priority Registers
72712724Snikos.nikoleris@arm.com        int first_intid = addr - GICD_IPRIORITYR.start();
72812724Snikos.nikoleris@arm.com
72912724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
73012724Snikos.nikoleris@arm.com            return;
73112724Snikos.nikoleris@arm.com        }
73212724Snikos.nikoleris@arm.com
73312724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
73412724Snikos.nikoleris@arm.com                i++, int_id++) {
73512724Snikos.nikoleris@arm.com            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
73612724Snikos.nikoleris@arm.com
73712724Snikos.nikoleris@arm.com            if (!DS && !is_secure_access) {
73812724Snikos.nikoleris@arm.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
73912724Snikos.nikoleris@arm.com                    // RAZ/WI for non-secure accesses to secure interrupts
74012724Snikos.nikoleris@arm.com                    continue;
74112724Snikos.nikoleris@arm.com                } else {
74212724Snikos.nikoleris@arm.com                    prio = 0x80 | (prio >> 1);
74312724Snikos.nikoleris@arm.com                }
74412724Snikos.nikoleris@arm.com            }
74512724Snikos.nikoleris@arm.com
74612724Snikos.nikoleris@arm.com            irqPriority[int_id] = prio;
74712724Snikos.nikoleris@arm.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
74812724Snikos.nikoleris@arm.com                    int_id, irqPriority[int_id]);
74912724Snikos.nikoleris@arm.com        }
75012724Snikos.nikoleris@arm.com
75112724Snikos.nikoleris@arm.com        return;
75212724Snikos.nikoleris@arm.com    } else if (GICD_ITARGETSR.contains(addr)) {
75312724Snikos.nikoleris@arm.com        // Interrupt Processor Targets Registers
75412724Snikos.nikoleris@arm.com        // ARE always on, RAZ/WI
75512724Snikos.nikoleris@arm.com        warn("Gicv3Distributor::write(): "
75612724Snikos.nikoleris@arm.com             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
75712724Snikos.nikoleris@arm.com        return;
75812724Snikos.nikoleris@arm.com    } else if (GICD_ICFGR.contains(addr)) {
75912724Snikos.nikoleris@arm.com        // Interrupt Configuration Registers
76012724Snikos.nikoleris@arm.com        // for x = 0 to 15:
76112724Snikos.nikoleris@arm.com        //   GICD_ICFGR[2x] = RES0
76212724Snikos.nikoleris@arm.com        //   GICD_ICFGR[2x + 1] =
76312724Snikos.nikoleris@arm.com        //     0 level-sensitive
76412724Snikos.nikoleris@arm.com        //     1 edge-triggered
76512724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_ICFGR.start()) * 4;
76612724Snikos.nikoleris@arm.com
76712724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
76812724Snikos.nikoleris@arm.com            return;
76912724Snikos.nikoleris@arm.com        }
77012724Snikos.nikoleris@arm.com
77112724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
77212724Snikos.nikoleris@arm.com             i = i + 2, int_id++) {
77312724Snikos.nikoleris@arm.com            irqConfig[int_id] = data & (0x2 << i) ?
77412724Snikos.nikoleris@arm.com                                Gicv3::INT_EDGE_TRIGGERED :
77512724Snikos.nikoleris@arm.com                                Gicv3::INT_LEVEL_SENSITIVE;
77612724Snikos.nikoleris@arm.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
77712724Snikos.nikoleris@arm.com                    int_id, irqConfig[int_id]);
77812724Snikos.nikoleris@arm.com        }
77912724Snikos.nikoleris@arm.com
78012724Snikos.nikoleris@arm.com        return;
78112724Snikos.nikoleris@arm.com    } else if (GICD_IGRPMODR.contains(addr)) {
78212724Snikos.nikoleris@arm.com        // Interrupt Group Modifier Registers
78312724Snikos.nikoleris@arm.com        if (DS) {
78412724Snikos.nikoleris@arm.com            return;
78512724Snikos.nikoleris@arm.com        } else {
78612724Snikos.nikoleris@arm.com            if (!is_secure_access) {
78712724Snikos.nikoleris@arm.com                // RAZ/WI for non-secure accesses
78812724Snikos.nikoleris@arm.com                return;
78912724Snikos.nikoleris@arm.com            } else {
79012724Snikos.nikoleris@arm.com                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
79112724Snikos.nikoleris@arm.com
79212724Snikos.nikoleris@arm.com                if (isNotSPI(first_intid)) {
79312724Snikos.nikoleris@arm.com                    return;
79412724Snikos.nikoleris@arm.com                }
79512724Snikos.nikoleris@arm.com
79612724Snikos.nikoleris@arm.com                for (int i = 0, int_id = first_intid;
79712724Snikos.nikoleris@arm.com                     i < 8 * size && int_id < itLines; i++, int_id++) {
79812724Snikos.nikoleris@arm.com                    irqGrpmod[int_id] = bits(data, i);
79912724Snikos.nikoleris@arm.com                }
80012724Snikos.nikoleris@arm.com
80112724Snikos.nikoleris@arm.com                return ;
80212724Snikos.nikoleris@arm.com            }
80312724Snikos.nikoleris@arm.com        }
80412724Snikos.nikoleris@arm.com
80512724Snikos.nikoleris@arm.com    } else if (GICD_NSACR.contains(addr)) {
80612724Snikos.nikoleris@arm.com        // Non-secure Access Control Registers
80712724Snikos.nikoleris@arm.com        // 2 bits per interrupt
80812724Snikos.nikoleris@arm.com        int first_intid = (addr - GICD_NSACR.start()) * 4;
80912724Snikos.nikoleris@arm.com
81012724Snikos.nikoleris@arm.com        if (isNotSPI(first_intid)) {
81112724Snikos.nikoleris@arm.com            return;
81212724Snikos.nikoleris@arm.com        }
81312724Snikos.nikoleris@arm.com
81412724Snikos.nikoleris@arm.com        if (DS || (!DS && !is_secure_access)) {
81512724Snikos.nikoleris@arm.com            return;
81612724Snikos.nikoleris@arm.com        }
81712724Snikos.nikoleris@arm.com
81812724Snikos.nikoleris@arm.com        for (int i = 0, int_id = first_intid;
81912724Snikos.nikoleris@arm.com             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
82012724Snikos.nikoleris@arm.com            irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
82112724Snikos.nikoleris@arm.com        }
82212766Sqtt2@cornell.edu
82312766Sqtt2@cornell.edu        return;
82412766Sqtt2@cornell.edu    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
82512766Sqtt2@cornell.edu        // 64 bit registers. 2 accesses.
82612766Sqtt2@cornell.edu        int int_id = (addr - GICD_IROUTER.start()) / 8;
82713377Sodanrc@yahoo.com.br
82812766Sqtt2@cornell.edu        if (isNotSPI(int_id)) {
82912766Sqtt2@cornell.edu            return;
83012766Sqtt2@cornell.edu        }
83112766Sqtt2@cornell.edu
83212766Sqtt2@cornell.edu        if (nsAccessToSecInt(int_id, is_secure_access))
83312766Sqtt2@cornell.edu        {
83412766Sqtt2@cornell.edu            if (irqNsacr[int_id] < 3) {
83512766Sqtt2@cornell.edu                // Group 0 or Secure Group 1 interrupts are RAZ/WI
83612766Sqtt2@cornell.edu                return;
83712724Snikos.nikoleris@arm.com            }
83812724Snikos.nikoleris@arm.com        }
83912724Snikos.nikoleris@arm.com
84012724Snikos.nikoleris@arm.com        if (size == 4) {
84112724Snikos.nikoleris@arm.com            if (addr & 7) { // high half of 64 bit register
84212724Snikos.nikoleris@arm.com                irqAffinityRouting[int_id] =
84312724Snikos.nikoleris@arm.com                    (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
84412724Snikos.nikoleris@arm.com            } else { // low half of 64 bit register
84512724Snikos.nikoleris@arm.com                irqAffinityRouting[int_id] =
84612724Snikos.nikoleris@arm.com                    (irqAffinityRouting[int_id] & 0xffffffff00000000) |
84712724Snikos.nikoleris@arm.com                    (data & 0xffffffff);
84812724Snikos.nikoleris@arm.com            }
84912724Snikos.nikoleris@arm.com        } else {
85012724Snikos.nikoleris@arm.com            irqAffinityRouting[int_id] = data;
85112724Snikos.nikoleris@arm.com        }
85212724Snikos.nikoleris@arm.com
85312724Snikos.nikoleris@arm.com        DPRINTF(GIC, "Gicv3Distributor::write(): "
85412724Snikos.nikoleris@arm.com                "int_id %d GICD_IROUTER %#llx\n",
85512724Snikos.nikoleris@arm.com                int_id, irqAffinityRouting[int_id]);
85612724Snikos.nikoleris@arm.com        return;
85712724Snikos.nikoleris@arm.com    }
85812724Snikos.nikoleris@arm.com
85912724Snikos.nikoleris@arm.com    switch (addr) {
86012724Snikos.nikoleris@arm.com      case GICD_CTLR: // Control Register
86112724Snikos.nikoleris@arm.com        if (DS) {
86212724Snikos.nikoleris@arm.com            /*
86312724Snikos.nikoleris@arm.com             * E1NWF [7]
86412724Snikos.nikoleris@arm.com             * 1 of N wakeup functionality not supported, RAZ/WI
86512724Snikos.nikoleris@arm.com             * DS [6] - RAO/WI
86612724Snikos.nikoleris@arm.com             * ARE [4]
86712724Snikos.nikoleris@arm.com             * affinity routing always on, no GICv2 legacy, RAO/WI
86812724Snikos.nikoleris@arm.com             * EnableGrp1 [1]
86912724Snikos.nikoleris@arm.com             * EnableGrp0 [0]
87012724Snikos.nikoleris@arm.com             */
87112724Snikos.nikoleris@arm.com            if ((data & (1 << 4)) == 0) {
87212794Snikos.nikoleris@arm.com                warn("Gicv3Distributor::write(): "
87312794Snikos.nikoleris@arm.com                        "setting ARE to 0 is not supported!\n");
87412724Snikos.nikoleris@arm.com            }
87512724Snikos.nikoleris@arm.com
87612724Snikos.nikoleris@arm.com            EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
87712724Snikos.nikoleris@arm.com            EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
87812724Snikos.nikoleris@arm.com            DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
87912724Snikos.nikoleris@arm.com                    "EnableGrp1NS %d EnableGrp0 %d\n",
88012724Snikos.nikoleris@arm.com                    EnableGrp1NS, EnableGrp0);
88112724Snikos.nikoleris@arm.com        } else {
88212724Snikos.nikoleris@arm.com            if (is_secure_access) {
88312724Snikos.nikoleris@arm.com                /*
88412724Snikos.nikoleris@arm.com                 * E1NWF [7]
88512724Snikos.nikoleris@arm.com                 * 1 of N wakeup functionality not supported, RAZ/WI
88612724Snikos.nikoleris@arm.com                 * DS [6]
88713418Sodanrc@yahoo.com.br                 * ARE_NS [5]
88813418Sodanrc@yahoo.com.br                 * affinity routing always on, no GICv2 legacy, RAO/WI
88913418Sodanrc@yahoo.com.br                 * ARE_S [4]
89013418Sodanrc@yahoo.com.br                 * affinity routing always on, no GICv2 legacy, RAO/WI
89113418Sodanrc@yahoo.com.br                 * EnableGrp1S [2]
89213418Sodanrc@yahoo.com.br                 * EnableGrp1NS [1]
89313418Sodanrc@yahoo.com.br                 * EnableGrp0 [0]
89413418Sodanrc@yahoo.com.br                 */
89513418Sodanrc@yahoo.com.br                if ((data & (1 << 5)) == 0) {
89613418Sodanrc@yahoo.com.br                    warn("Gicv3Distributor::write(): "
89713418Sodanrc@yahoo.com.br                            "setting ARE_NS to 0 is not supported!\n");
89813418Sodanrc@yahoo.com.br                }
89913418Sodanrc@yahoo.com.br
90013418Sodanrc@yahoo.com.br                if ((data & (1 << 4)) == 0) {
90113418Sodanrc@yahoo.com.br                    warn("Gicv3Distributor::write(): "
90213418Sodanrc@yahoo.com.br                            "setting ARE_S to 0 is not supported!\n");
90313477Sodanrc@yahoo.com.br                }
90413477Sodanrc@yahoo.com.br
90513477Sodanrc@yahoo.com.br                DS = data & GICD_CTLR_DS;
90613477Sodanrc@yahoo.com.br                EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S;
90713477Sodanrc@yahoo.com.br                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
90813418Sodanrc@yahoo.com.br                EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
90913418Sodanrc@yahoo.com.br                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
91013418Sodanrc@yahoo.com.br                        "DS %d "
91113418Sodanrc@yahoo.com.br                        "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
91213418Sodanrc@yahoo.com.br                        DS, EnableGrp1S, EnableGrp1NS, EnableGrp0);
91312724Snikos.nikoleris@arm.com
91412724Snikos.nikoleris@arm.com                if (data & GICD_CTLR_DS) {
91512724Snikos.nikoleris@arm.com                    EnableGrp1S = 0;
91612724Snikos.nikoleris@arm.com                }
91712724Snikos.nikoleris@arm.com            } else {
91812724Snikos.nikoleris@arm.com                /*
91912724Snikos.nikoleris@arm.com                 * ARE_NS [4] RAO/WI;
92012724Snikos.nikoleris@arm.com                 * EnableGrp1A [1] is a read-write alias of the Secure
92112724Snikos.nikoleris@arm.com                 * GICD_CTLR.EnableGrp1NS
92212724Snikos.nikoleris@arm.com                 * EnableGrp1 [0] RES0
92312724Snikos.nikoleris@arm.com                 */
92412724Snikos.nikoleris@arm.com                if ((data & (1 << 4)) == 0) {
92513418Sodanrc@yahoo.com.br                    warn("Gicv3Distributor::write(): "
92613418Sodanrc@yahoo.com.br                            "setting ARE_NS to 0 is not supported!\n");
92713418Sodanrc@yahoo.com.br                }
92813418Sodanrc@yahoo.com.br
92913418Sodanrc@yahoo.com.br                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A;
93013418Sodanrc@yahoo.com.br                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
93112724Snikos.nikoleris@arm.com                        "EnableGrp1NS %d\n", EnableGrp1NS);
93212724Snikos.nikoleris@arm.com            }
93312724Snikos.nikoleris@arm.com        }
93412724Snikos.nikoleris@arm.com
93512724Snikos.nikoleris@arm.com        update();
93612724Snikos.nikoleris@arm.com
93712724Snikos.nikoleris@arm.com        break;
93812724Snikos.nikoleris@arm.com
93912724Snikos.nikoleris@arm.com      default:
94012724Snikos.nikoleris@arm.com        panic("Gicv3Distributor::write(): invalid offset %#x\n", addr);
94112724Snikos.nikoleris@arm.com        break;
94212724Snikos.nikoleris@arm.com    }
94312724Snikos.nikoleris@arm.com}
94412724Snikos.nikoleris@arm.com
94512724Snikos.nikoleris@arm.comvoid
94612724Snikos.nikoleris@arm.comGicv3Distributor::sendInt(uint32_t int_id)
94712724Snikos.nikoleris@arm.com{
94812724Snikos.nikoleris@arm.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
94912724Snikos.nikoleris@arm.com    panic_if(int_id > itLines, "Invalid SPI!");
95012724Snikos.nikoleris@arm.com    irqPending[int_id] = true;
95112724Snikos.nikoleris@arm.com    DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
95212724Snikos.nikoleris@arm.com            "int_id %d (SPI) pending bit set\n", int_id);
95312724Snikos.nikoleris@arm.com    update();
95412724Snikos.nikoleris@arm.com}
95512724Snikos.nikoleris@arm.com
95612724Snikos.nikoleris@arm.comvoid
95712724Snikos.nikoleris@arm.comGicv3Distributor::deassertSPI(uint32_t int_id)
95812724Snikos.nikoleris@arm.com{
95912724Snikos.nikoleris@arm.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
96012724Snikos.nikoleris@arm.com    panic_if(int_id > itLines, "Invalid SPI!");
96112724Snikos.nikoleris@arm.com    irqPending[int_id] = false;
96212724Snikos.nikoleris@arm.com    clearIrqCpuInterface(int_id);
96312724Snikos.nikoleris@arm.com
96412724Snikos.nikoleris@arm.com    update();
96512724Snikos.nikoleris@arm.com}
96612724Snikos.nikoleris@arm.com
96712724Snikos.nikoleris@arm.comGicv3CPUInterface*
96812724Snikos.nikoleris@arm.comGicv3Distributor::route(uint32_t int_id)
96912724Snikos.nikoleris@arm.com{
97012724Snikos.nikoleris@arm.com    IROUTER affinity_routing = irqAffinityRouting[int_id];
97112724Snikos.nikoleris@arm.com    Gicv3Redistributor * target_redistributor = nullptr;
97212724Snikos.nikoleris@arm.com
97312724Snikos.nikoleris@arm.com    const Gicv3::GroupId int_group = getIntGroup(int_id);
97412724Snikos.nikoleris@arm.com
97512724Snikos.nikoleris@arm.com    if (affinity_routing.IRM) {
97612724Snikos.nikoleris@arm.com        // Interrupts routed to any PE defined as a participating node
97712724Snikos.nikoleris@arm.com        for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
97812724Snikos.nikoleris@arm.com            Gicv3Redistributor * redistributor_i =
97912724Snikos.nikoleris@arm.com                gic->getRedistributor(i);
98012724Snikos.nikoleris@arm.com
98112724Snikos.nikoleris@arm.com            if (redistributor_i->
98212724Snikos.nikoleris@arm.com                    canBeSelectedFor1toNInterrupt(int_group)) {
98312724Snikos.nikoleris@arm.com                target_redistributor = redistributor_i;
98412724Snikos.nikoleris@arm.com                break;
98512724Snikos.nikoleris@arm.com            }
98612724Snikos.nikoleris@arm.com        }
98712724Snikos.nikoleris@arm.com    } else {
98812724Snikos.nikoleris@arm.com        uint32_t affinity = (affinity_routing.Aff3 << 24) |
98912724Snikos.nikoleris@arm.com                            (affinity_routing.Aff2 << 16) |
99012724Snikos.nikoleris@arm.com                            (affinity_routing.Aff1 << 8) |
99112724Snikos.nikoleris@arm.com                            (affinity_routing.Aff0 << 0);
99212724Snikos.nikoleris@arm.com        target_redistributor =
99312724Snikos.nikoleris@arm.com            gic->getRedistributorByAffinity(affinity);
99412724Snikos.nikoleris@arm.com    }
99512724Snikos.nikoleris@arm.com
99612724Snikos.nikoleris@arm.com    if (!target_redistributor) {
99712724Snikos.nikoleris@arm.com        // Interrrupts targeting not present cpus must remain pending
99812724Snikos.nikoleris@arm.com        return nullptr;
99912724Snikos.nikoleris@arm.com    } else {
100012724Snikos.nikoleris@arm.com        return target_redistributor->getCPUInterface();
100112754Sodanrc@yahoo.com.br    }
100212724Snikos.nikoleris@arm.com}
100312724Snikos.nikoleris@arm.com
100412724Snikos.nikoleris@arm.comvoid
100512724Snikos.nikoleris@arm.comGicv3Distributor::clearIrqCpuInterface(uint32_t int_id)
100612724Snikos.nikoleris@arm.com{
100712724Snikos.nikoleris@arm.com    auto cpu_interface = route(int_id);
100813445Sodanrc@yahoo.com.br    if (cpu_interface)
100912724Snikos.nikoleris@arm.com        cpu_interface->hppi.prio = 0xff;
101012724Snikos.nikoleris@arm.com}
101112724Snikos.nikoleris@arm.com
101212724Snikos.nikoleris@arm.comvoid
101312724Snikos.nikoleris@arm.comGicv3Distributor::update()
101412724Snikos.nikoleris@arm.com{
101512724Snikos.nikoleris@arm.com    // Find the highest priority pending SPI
101612724Snikos.nikoleris@arm.com    for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
101712724Snikos.nikoleris@arm.com         int_id++) {
101812724Snikos.nikoleris@arm.com        Gicv3::GroupId int_group = getIntGroup(int_id);
101912724Snikos.nikoleris@arm.com        bool group_enabled = groupEnabled(int_group);
102012724Snikos.nikoleris@arm.com
102112724Snikos.nikoleris@arm.com        if (irqPending[int_id] && irqEnabled[int_id] &&
102212724Snikos.nikoleris@arm.com            !irqActive[int_id] && group_enabled) {
102312724Snikos.nikoleris@arm.com
102412724Snikos.nikoleris@arm.com            // Find the cpu interface where to route the interrupt
102512724Snikos.nikoleris@arm.com            Gicv3CPUInterface *target_cpu_interface = route(int_id);
102612724Snikos.nikoleris@arm.com
102712724Snikos.nikoleris@arm.com            // Invalid routing
102813477Sodanrc@yahoo.com.br            if (!target_cpu_interface) continue;
102913477Sodanrc@yahoo.com.br
103012724Snikos.nikoleris@arm.com            if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
103112724Snikos.nikoleris@arm.com                (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
103212724Snikos.nikoleris@arm.com                int_id < target_cpu_interface->hppi.intid)) {
103312724Snikos.nikoleris@arm.com
103412724Snikos.nikoleris@arm.com                target_cpu_interface->hppi.intid = int_id;
103512724Snikos.nikoleris@arm.com                target_cpu_interface->hppi.prio = irqPriority[int_id];
103612724Snikos.nikoleris@arm.com                target_cpu_interface->hppi.group = int_group;
103712724Snikos.nikoleris@arm.com            }
103812724Snikos.nikoleris@arm.com        }
103912724Snikos.nikoleris@arm.com    }
104012724Snikos.nikoleris@arm.com
104112724Snikos.nikoleris@arm.com    // Update all redistributors
104212724Snikos.nikoleris@arm.com    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
104312724Snikos.nikoleris@arm.com        gic->getRedistributor(i)->update();
104412724Snikos.nikoleris@arm.com    }
104512724Snikos.nikoleris@arm.com}
104612724Snikos.nikoleris@arm.com
104712724Snikos.nikoleris@arm.comGicv3::IntStatus
104812724Snikos.nikoleris@arm.comGicv3Distributor::intStatus(uint32_t int_id) const
104912724Snikos.nikoleris@arm.com{
105012724Snikos.nikoleris@arm.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
105112724Snikos.nikoleris@arm.com    panic_if(int_id > itLines, "Invalid SPI!");
105212724Snikos.nikoleris@arm.com
105312724Snikos.nikoleris@arm.com    if (irqPending[int_id]) {
105412724Snikos.nikoleris@arm.com        if (irqActive[int_id]) {
105512724Snikos.nikoleris@arm.com            return Gicv3::INT_ACTIVE_PENDING;
105612724Snikos.nikoleris@arm.com        }
105712724Snikos.nikoleris@arm.com
105812754Sodanrc@yahoo.com.br        return Gicv3::INT_PENDING;
105912724Snikos.nikoleris@arm.com    } else if (irqActive[int_id]) {
106012724Snikos.nikoleris@arm.com        return Gicv3::INT_ACTIVE;
106112724Snikos.nikoleris@arm.com    } else {
106212724Snikos.nikoleris@arm.com        return Gicv3::INT_INACTIVE;
106312724Snikos.nikoleris@arm.com    }
106412724Snikos.nikoleris@arm.com}
106512724Snikos.nikoleris@arm.com
106613445Sodanrc@yahoo.com.brGicv3::GroupId
106712724Snikos.nikoleris@arm.comGicv3Distributor::getIntGroup(int int_id) const
106812724Snikos.nikoleris@arm.com{
106912724Snikos.nikoleris@arm.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
107012724Snikos.nikoleris@arm.com    panic_if(int_id > itLines, "Invalid SPI!");
107112724Snikos.nikoleris@arm.com
107212724Snikos.nikoleris@arm.com    if (DS) {
107312724Snikos.nikoleris@arm.com        if (irqGroup[int_id] == 1) {
107412724Snikos.nikoleris@arm.com            return Gicv3::G1NS;
107512724Snikos.nikoleris@arm.com        } else {
107612724Snikos.nikoleris@arm.com            return Gicv3::G0S;
107712724Snikos.nikoleris@arm.com        }
107812724Snikos.nikoleris@arm.com    } else {
107912724Snikos.nikoleris@arm.com        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
108012724Snikos.nikoleris@arm.com            return Gicv3::G0S;
108112724Snikos.nikoleris@arm.com        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
108212724Snikos.nikoleris@arm.com            return Gicv3::G1NS;
108312724Snikos.nikoleris@arm.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
108412724Snikos.nikoleris@arm.com            return Gicv3::G1S;
108513477Sodanrc@yahoo.com.br        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
108613477Sodanrc@yahoo.com.br            return Gicv3::G1NS;
108712724Snikos.nikoleris@arm.com        }
108812724Snikos.nikoleris@arm.com    }
108912724Snikos.nikoleris@arm.com
109012724Snikos.nikoleris@arm.com    M5_UNREACHABLE;
109112724Snikos.nikoleris@arm.com}
109212724Snikos.nikoleris@arm.com
109312724Snikos.nikoleris@arm.comvoid
109412724Snikos.nikoleris@arm.comGicv3Distributor::activateIRQ(uint32_t int_id)
109512724Snikos.nikoleris@arm.com{
109612724Snikos.nikoleris@arm.com    irqPending[int_id] = false;
109712724Snikos.nikoleris@arm.com    irqActive[int_id] = true;
109812724Snikos.nikoleris@arm.com}
109912724Snikos.nikoleris@arm.com
110012724Snikos.nikoleris@arm.comvoid
110112724Snikos.nikoleris@arm.comGicv3Distributor::deactivateIRQ(uint32_t int_id)
110212724Snikos.nikoleris@arm.com{
110312724Snikos.nikoleris@arm.com    irqActive[int_id] = false;
110412724Snikos.nikoleris@arm.com}
110512724Snikos.nikoleris@arm.com
110612724Snikos.nikoleris@arm.comvoid
110712724Snikos.nikoleris@arm.comGicv3Distributor::serialize(CheckpointOut & cp) const
110812724Snikos.nikoleris@arm.com{
110912724Snikos.nikoleris@arm.com    SERIALIZE_SCALAR(ARE);
111012724Snikos.nikoleris@arm.com    SERIALIZE_SCALAR(DS);
111112724Snikos.nikoleris@arm.com    SERIALIZE_SCALAR(EnableGrp1S);
111212724Snikos.nikoleris@arm.com    SERIALIZE_SCALAR(EnableGrp1NS);
111312724Snikos.nikoleris@arm.com    SERIALIZE_SCALAR(EnableGrp0);
111412724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqGroup);
111512724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqEnabled);
111612724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqPending);
111712724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqActive);
111812724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqPriority);
111912724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqConfig);
112012724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqGrpmod);
112112724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqNsacr);
112212724Snikos.nikoleris@arm.com    SERIALIZE_CONTAINER(irqAffinityRouting);
112312724Snikos.nikoleris@arm.com}
112412724Snikos.nikoleris@arm.com
112512724Snikos.nikoleris@arm.comvoid
112612724Snikos.nikoleris@arm.comGicv3Distributor::unserialize(CheckpointIn & cp)
112712724Snikos.nikoleris@arm.com{
112812724Snikos.nikoleris@arm.com    UNSERIALIZE_SCALAR(ARE);
112912724Snikos.nikoleris@arm.com    UNSERIALIZE_SCALAR(DS);
113013350Snikos.nikoleris@arm.com    UNSERIALIZE_SCALAR(EnableGrp1S);
113112724Snikos.nikoleris@arm.com    UNSERIALIZE_SCALAR(EnableGrp1NS);
113212724Snikos.nikoleris@arm.com    UNSERIALIZE_SCALAR(EnableGrp0);
113312724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqGroup);
113412724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqEnabled);
113512724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqPending);
113612724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqActive);
113712724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqPriority);
113812724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqConfig);
113912724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqGrpmod);
114012724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqNsacr);
114112724Snikos.nikoleris@arm.com    UNSERIALIZE_CONTAINER(irqAffinityRouting);
114212724Snikos.nikoleris@arm.com}
114313350Snikos.nikoleris@arm.com