113014Sciro.santilli@arm.com/*
213014Sciro.santilli@arm.com * Copyright (c) 2010, 2013, 2015-2018 ARM Limited
313014Sciro.santilli@arm.com * All rights reserved
413014Sciro.santilli@arm.com *
513014Sciro.santilli@arm.com * The license below extends only to copyright in the software and shall
613014Sciro.santilli@arm.com * not be construed as granting a license to any other intellectual
713014Sciro.santilli@arm.com * property including but not limited to intellectual property relating
813014Sciro.santilli@arm.com * to a hardware implementation of the functionality of the software
913014Sciro.santilli@arm.com * licensed hereunder.  You may use the software subject to the license
1013014Sciro.santilli@arm.com * terms below provided that you ensure that this notice is replicated
1113014Sciro.santilli@arm.com * unmodified and in its entirety in all distributions of the software,
1213014Sciro.santilli@arm.com * modified or unmodified, in source code or in binary form.
1313014Sciro.santilli@arm.com *
1413014Sciro.santilli@arm.com * Copyright (c) 2005 The Regents of The University of Michigan
1513014Sciro.santilli@arm.com * All rights reserved.
1613014Sciro.santilli@arm.com *
1713014Sciro.santilli@arm.com * Redistribution and use in source and binary forms, with or without
1813014Sciro.santilli@arm.com * modification, are permitted provided that the following conditions are
1913014Sciro.santilli@arm.com * met: redistributions of source code must retain the above copyright
2013014Sciro.santilli@arm.com * notice, this list of conditions and the following disclaimer;
2113014Sciro.santilli@arm.com * redistributions in binary form must reproduce the above copyright
2213014Sciro.santilli@arm.com * notice, this list of conditions and the following disclaimer in the
2313014Sciro.santilli@arm.com * documentation and/or other materials provided with the distribution;
2413014Sciro.santilli@arm.com * neither the name of the copyright holders nor the names of its
2513014Sciro.santilli@arm.com * contributors may be used to endorse or promote products derived from
2613014Sciro.santilli@arm.com * this software without specific prior written permission.
2713014Sciro.santilli@arm.com *
2813014Sciro.santilli@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2913014Sciro.santilli@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3013014Sciro.santilli@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3113014Sciro.santilli@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3213014Sciro.santilli@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3313014Sciro.santilli@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3413014Sciro.santilli@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3513014Sciro.santilli@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3613014Sciro.santilli@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3713014Sciro.santilli@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3813014Sciro.santilli@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3913014Sciro.santilli@arm.com *
4013014Sciro.santilli@arm.com * Authors: Ali Saidi
4113014Sciro.santilli@arm.com *          Prakash Ramrakhyani
4213014Sciro.santilli@arm.com */
4313014Sciro.santilli@arm.com
4413014Sciro.santilli@arm.com#include "dev/arm/gic_v2.hh"
4513014Sciro.santilli@arm.com
4613014Sciro.santilli@arm.com#include "base/trace.hh"
4713014Sciro.santilli@arm.com#include "debug/Checkpoint.hh"
4813014Sciro.santilli@arm.com#include "debug/GIC.hh"
4913014Sciro.santilli@arm.com#include "debug/IPI.hh"
5013014Sciro.santilli@arm.com#include "debug/Interrupt.hh"
5113014Sciro.santilli@arm.com#include "mem/packet.hh"
5213014Sciro.santilli@arm.com#include "mem/packet_access.hh"
5313014Sciro.santilli@arm.com
5413014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_IGROUPR   (0x080, 0x0ff);
5513014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ISENABLER (0x100, 0x17f);
5613014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ICENABLER (0x180, 0x1ff);
5713014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ISPENDR   (0x200, 0x27f);
5813014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ICPENDR   (0x280, 0x2ff);
5913014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ISACTIVER (0x300, 0x37f);
6013014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ICACTIVER (0x380, 0x3ff);
6113014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_IPRIORITYR(0x400, 0x7ff);
6213014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ITARGETSR (0x800, 0xbff);
6313014Sciro.santilli@arm.comconst AddrRange GicV2::GICD_ICFGR     (0xc00, 0xcff);
6413014Sciro.santilli@arm.com
6513014Sciro.santilli@arm.comGicV2::GicV2(const Params *p)
6613014Sciro.santilli@arm.com    : BaseGic(p),
6713505Sgiacomo.travaglini@arm.com      gicdPIDR(p->gicd_pidr),
6813505Sgiacomo.travaglini@arm.com      gicdIIDR(p->gicd_iidr),
6913505Sgiacomo.travaglini@arm.com      giccIIDR(p->gicc_iidr),
7013014Sciro.santilli@arm.com      distRange(RangeSize(p->dist_addr, DIST_SIZE)),
7113014Sciro.santilli@arm.com      cpuRange(RangeSize(p->cpu_addr, p->cpu_size)),
7213014Sciro.santilli@arm.com      addrRanges{distRange, cpuRange},
7313014Sciro.santilli@arm.com      distPioDelay(p->dist_pio_delay),
7413014Sciro.santilli@arm.com      cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
7513014Sciro.santilli@arm.com      enabled(false), haveGem5Extensions(p->gem5_extensions),
7613014Sciro.santilli@arm.com      itLines(p->it_lines),
7713014Sciro.santilli@arm.com      intEnabled {}, pendingInt {}, activeInt {},
7813014Sciro.santilli@arm.com      intPriority {}, cpuTarget {}, intConfig {},
7913014Sciro.santilli@arm.com      cpuSgiPending {}, cpuSgiActive {},
8013014Sciro.santilli@arm.com      cpuSgiPendingExt {}, cpuSgiActiveExt {},
8113014Sciro.santilli@arm.com      cpuPpiPending {}, cpuPpiActive {},
8213014Sciro.santilli@arm.com      pendingDelayedInterrupts(0)
8313014Sciro.santilli@arm.com{
8413014Sciro.santilli@arm.com    for (int x = 0; x < CPU_MAX; x++) {
8513014Sciro.santilli@arm.com        iccrpr[x] = 0xff;
8613109Sgiacomo.travaglini@arm.com        cpuControl[x] = 0;
8713014Sciro.santilli@arm.com        cpuPriority[x] = 0xff;
8813014Sciro.santilli@arm.com        cpuBpr[x] = GICC_BPR_MINIMUM;
8913014Sciro.santilli@arm.com        // Initialize cpu highest int
9013014Sciro.santilli@arm.com        cpuHighestInt[x] = SPURIOUS_INT;
9113014Sciro.santilli@arm.com        postIntEvent[x] =
9213014Sciro.santilli@arm.com            new EventFunctionWrapper([this, x]{ postDelayedInt(x); },
9313014Sciro.santilli@arm.com                                     "Post Interrupt to CPU");
9413111Sgiacomo.travaglini@arm.com        postFiqEvent[x] =
9513111Sgiacomo.travaglini@arm.com            new EventFunctionWrapper([this, x]{ postDelayedFiq(x); },
9613111Sgiacomo.travaglini@arm.com                                     "Post FIQ to CPU");
9713014Sciro.santilli@arm.com    }
9813109Sgiacomo.travaglini@arm.com    DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled(0),
9913109Sgiacomo.travaglini@arm.com            cpuEnabled(1));
10013014Sciro.santilli@arm.com
10113014Sciro.santilli@arm.com    gem5ExtensionsEnabled = false;
10213014Sciro.santilli@arm.com}
10313014Sciro.santilli@arm.com
10413014Sciro.santilli@arm.comGicV2::~GicV2()
10513014Sciro.santilli@arm.com{
10613111Sgiacomo.travaglini@arm.com    for (int x = 0; x < CPU_MAX; x++) {
10713014Sciro.santilli@arm.com        delete postIntEvent[x];
10813111Sgiacomo.travaglini@arm.com        delete postFiqEvent[x];
10913111Sgiacomo.travaglini@arm.com    }
11013014Sciro.santilli@arm.com}
11113014Sciro.santilli@arm.com
11213014Sciro.santilli@arm.comTick
11313014Sciro.santilli@arm.comGicV2::read(PacketPtr pkt)
11413014Sciro.santilli@arm.com{
11513014Sciro.santilli@arm.com    const Addr addr = pkt->getAddr();
11613014Sciro.santilli@arm.com
11713014Sciro.santilli@arm.com    if (distRange.contains(addr))
11813014Sciro.santilli@arm.com        return readDistributor(pkt);
11913014Sciro.santilli@arm.com    else if (cpuRange.contains(addr))
12013014Sciro.santilli@arm.com        return readCpu(pkt);
12113014Sciro.santilli@arm.com    else
12213014Sciro.santilli@arm.com        panic("Read to unknown address %#x\n", pkt->getAddr());
12313014Sciro.santilli@arm.com}
12413014Sciro.santilli@arm.com
12513014Sciro.santilli@arm.com
12613014Sciro.santilli@arm.comTick
12713014Sciro.santilli@arm.comGicV2::write(PacketPtr pkt)
12813014Sciro.santilli@arm.com{
12913014Sciro.santilli@arm.com    const Addr addr = pkt->getAddr();
13013014Sciro.santilli@arm.com
13113014Sciro.santilli@arm.com    if (distRange.contains(addr))
13213014Sciro.santilli@arm.com        return writeDistributor(pkt);
13313014Sciro.santilli@arm.com    else if (cpuRange.contains(addr))
13413014Sciro.santilli@arm.com        return writeCpu(pkt);
13513014Sciro.santilli@arm.com    else
13613014Sciro.santilli@arm.com        panic("Write to unknown address %#x\n", pkt->getAddr());
13713014Sciro.santilli@arm.com}
13813014Sciro.santilli@arm.com
13913014Sciro.santilli@arm.comTick
14013014Sciro.santilli@arm.comGicV2::readDistributor(PacketPtr pkt)
14113014Sciro.santilli@arm.com{
14213014Sciro.santilli@arm.com    const Addr daddr = pkt->getAddr() - distRange.start();
14313014Sciro.santilli@arm.com    const ContextID ctx = pkt->req->contextId();
14413014Sciro.santilli@arm.com
14513014Sciro.santilli@arm.com    DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
14613014Sciro.santilli@arm.com
14713014Sciro.santilli@arm.com    const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize());
14813014Sciro.santilli@arm.com
14913014Sciro.santilli@arm.com    switch (pkt->getSize()) {
15013014Sciro.santilli@arm.com      case 1:
15113230Sgabeblack@google.com        pkt->setLE<uint8_t>(resp);
15213014Sciro.santilli@arm.com        break;
15313014Sciro.santilli@arm.com      case 2:
15413230Sgabeblack@google.com        pkt->setLE<uint16_t>(resp);
15513014Sciro.santilli@arm.com        break;
15613014Sciro.santilli@arm.com      case 4:
15713230Sgabeblack@google.com        pkt->setLE<uint32_t>(resp);
15813014Sciro.santilli@arm.com        break;
15913014Sciro.santilli@arm.com      default:
16013014Sciro.santilli@arm.com        panic("Invalid size while reading Distributor regs in GIC: %d\n",
16113014Sciro.santilli@arm.com               pkt->getSize());
16213014Sciro.santilli@arm.com    }
16313014Sciro.santilli@arm.com
16413014Sciro.santilli@arm.com    pkt->makeAtomicResponse();
16513014Sciro.santilli@arm.com    return distPioDelay;
16613014Sciro.santilli@arm.com}
16713014Sciro.santilli@arm.com
16813014Sciro.santilli@arm.comuint32_t
16913014Sciro.santilli@arm.comGicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
17013014Sciro.santilli@arm.com{
17113014Sciro.santilli@arm.com    if (GICD_IGROUPR.contains(daddr)) {
17213110Sgiacomo.travaglini@arm.com        uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2;
17313110Sgiacomo.travaglini@arm.com        assert(ix < 32);
17413110Sgiacomo.travaglini@arm.com        return getIntGroup(ctx, ix);
17513014Sciro.santilli@arm.com    }
17613014Sciro.santilli@arm.com
17713014Sciro.santilli@arm.com    if (GICD_ISENABLER.contains(daddr)) {
17813014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
17913014Sciro.santilli@arm.com        assert(ix < 32);
18013014Sciro.santilli@arm.com        return getIntEnabled(ctx, ix);
18113014Sciro.santilli@arm.com    }
18213014Sciro.santilli@arm.com
18313014Sciro.santilli@arm.com    if (GICD_ICENABLER.contains(daddr)) {
18413014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
18513014Sciro.santilli@arm.com        assert(ix < 32);
18613014Sciro.santilli@arm.com        return getIntEnabled(ctx, ix);
18713014Sciro.santilli@arm.com    }
18813014Sciro.santilli@arm.com
18913014Sciro.santilli@arm.com    if (GICD_ISPENDR.contains(daddr)) {
19013014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
19113014Sciro.santilli@arm.com        assert(ix < 32);
19213014Sciro.santilli@arm.com        return getPendingInt(ctx, ix);
19313014Sciro.santilli@arm.com    }
19413014Sciro.santilli@arm.com
19513014Sciro.santilli@arm.com    if (GICD_ICPENDR.contains(daddr)) {
19613014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
19713014Sciro.santilli@arm.com        assert(ix < 32);
19813014Sciro.santilli@arm.com        return getPendingInt(ctx, ix);
19913014Sciro.santilli@arm.com    }
20013014Sciro.santilli@arm.com
20113014Sciro.santilli@arm.com    if (GICD_ISACTIVER.contains(daddr)) {
20213014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
20313014Sciro.santilli@arm.com        assert(ix < 32);
20413014Sciro.santilli@arm.com        return getActiveInt(ctx, ix);
20513014Sciro.santilli@arm.com    }
20613014Sciro.santilli@arm.com
20713014Sciro.santilli@arm.com    if (GICD_ICACTIVER.contains(daddr)) {
20813014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
20913014Sciro.santilli@arm.com        assert(ix < 32);
21013014Sciro.santilli@arm.com        return getActiveInt(ctx, ix);
21113014Sciro.santilli@arm.com    }
21213014Sciro.santilli@arm.com
21313014Sciro.santilli@arm.com    if (GICD_IPRIORITYR.contains(daddr)) {
21413014Sciro.santilli@arm.com        Addr int_num = daddr - GICD_IPRIORITYR.start();
21513014Sciro.santilli@arm.com        assert(int_num < INT_LINES_MAX);
21613014Sciro.santilli@arm.com        DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",
21713014Sciro.santilli@arm.com                int_num);
21813014Sciro.santilli@arm.com
21913014Sciro.santilli@arm.com        switch (resp_sz) {
22013014Sciro.santilli@arm.com          default: // will panic() after return to caller anyway
22113014Sciro.santilli@arm.com          case 1:
22213014Sciro.santilli@arm.com            return getIntPriority(ctx, int_num);
22313014Sciro.santilli@arm.com          case 2:
22413014Sciro.santilli@arm.com            assert((int_num + 1) < INT_LINES_MAX);
22513014Sciro.santilli@arm.com            return (getIntPriority(ctx, int_num) |
22613014Sciro.santilli@arm.com                    getIntPriority(ctx, int_num+1) << 8);
22713014Sciro.santilli@arm.com          case 4:
22813014Sciro.santilli@arm.com            assert((int_num + 3) < INT_LINES_MAX);
22913014Sciro.santilli@arm.com            return (getIntPriority(ctx, int_num) |
23013014Sciro.santilli@arm.com                    getIntPriority(ctx, int_num+1) << 8 |
23113014Sciro.santilli@arm.com                    getIntPriority(ctx, int_num+2) << 16 |
23213014Sciro.santilli@arm.com                    getIntPriority(ctx, int_num+3) << 24);
23313014Sciro.santilli@arm.com        }
23413014Sciro.santilli@arm.com    }
23513014Sciro.santilli@arm.com
23613014Sciro.santilli@arm.com    if (GICD_ITARGETSR.contains(daddr)) {
23713014Sciro.santilli@arm.com        Addr int_num = daddr - GICD_ITARGETSR.start();
23813014Sciro.santilli@arm.com        DPRINTF(GIC, "Reading processor target register for int# %#x \n",
23913014Sciro.santilli@arm.com                 int_num);
24013014Sciro.santilli@arm.com        assert(int_num < INT_LINES_MAX);
24113014Sciro.santilli@arm.com
24213014Sciro.santilli@arm.com        if (resp_sz == 1) {
24313014Sciro.santilli@arm.com            return getCpuTarget(ctx, int_num);
24413014Sciro.santilli@arm.com        } else {
24513014Sciro.santilli@arm.com            assert(resp_sz == 4);
24613014Sciro.santilli@arm.com            int_num = mbits(int_num, 31, 2);
24713014Sciro.santilli@arm.com            return (getCpuTarget(ctx, int_num) |
24813014Sciro.santilli@arm.com                    getCpuTarget(ctx, int_num+1) << 8 |
24913014Sciro.santilli@arm.com                    getCpuTarget(ctx, int_num+2) << 16 |
25013014Sciro.santilli@arm.com                    getCpuTarget(ctx, int_num+3) << 24) ;
25113014Sciro.santilli@arm.com        }
25213014Sciro.santilli@arm.com    }
25313014Sciro.santilli@arm.com
25413014Sciro.santilli@arm.com    if (GICD_ICFGR.contains(daddr)) {
25513014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
25613014Sciro.santilli@arm.com        assert(ix < 64);
25713014Sciro.santilli@arm.com        /** @todo software generated interrupts and PPIs
25813014Sciro.santilli@arm.com         * can't be configured in some ways */
25913014Sciro.santilli@arm.com        return intConfig[ix];
26013014Sciro.santilli@arm.com    }
26113014Sciro.santilli@arm.com
26213014Sciro.santilli@arm.com    switch(daddr) {
26313014Sciro.santilli@arm.com      case GICD_CTLR:
26413014Sciro.santilli@arm.com        return enabled;
26513014Sciro.santilli@arm.com      case GICD_TYPER:
26613014Sciro.santilli@arm.com        /* The 0x100 is a made-up flag to show that gem5 extensions
26713014Sciro.santilli@arm.com         * are available,
26813014Sciro.santilli@arm.com         * write 0x200 to this register to enable it.  */
26913014Sciro.santilli@arm.com        return (((sys->numRunningContexts() - 1) << 5) |
27013014Sciro.santilli@arm.com                (itLines/INT_BITS_MAX -1) |
27113014Sciro.santilli@arm.com                (haveGem5Extensions ? 0x100 : 0x0));
27213014Sciro.santilli@arm.com      case GICD_PIDR0:
27313014Sciro.santilli@arm.com        //ARM defined DevID
27413505Sgiacomo.travaglini@arm.com        return (gicdPIDR & 0xFF);
27513014Sciro.santilli@arm.com      case GICD_PIDR1:
27613505Sgiacomo.travaglini@arm.com        return ((gicdPIDR >> 8) & 0xFF);
27713014Sciro.santilli@arm.com      case GICD_PIDR2:
27813505Sgiacomo.travaglini@arm.com        return ((gicdPIDR >> 16) & 0xFF);
27913014Sciro.santilli@arm.com      case GICD_PIDR3:
28013505Sgiacomo.travaglini@arm.com        return ((gicdPIDR >> 24) & 0xFF);
28113014Sciro.santilli@arm.com      case GICD_IIDR:
28213014Sciro.santilli@arm.com         /* revision id is resorted to 1 and variant to 0*/
28313505Sgiacomo.travaglini@arm.com        return gicdIIDR;
28413014Sciro.santilli@arm.com      default:
28513014Sciro.santilli@arm.com        panic("Tried to read Gic distributor at offset %#x\n", daddr);
28613014Sciro.santilli@arm.com        break;
28713014Sciro.santilli@arm.com    }
28813014Sciro.santilli@arm.com}
28913014Sciro.santilli@arm.com
29013014Sciro.santilli@arm.comTick
29113014Sciro.santilli@arm.comGicV2::readCpu(PacketPtr pkt)
29213014Sciro.santilli@arm.com{
29313014Sciro.santilli@arm.com    const Addr daddr = pkt->getAddr() - cpuRange.start();
29413014Sciro.santilli@arm.com
29513014Sciro.santilli@arm.com    assert(pkt->req->hasContextId());
29613014Sciro.santilli@arm.com    const ContextID ctx = pkt->req->contextId();
29713014Sciro.santilli@arm.com    assert(ctx < sys->numRunningContexts());
29813014Sciro.santilli@arm.com
29913014Sciro.santilli@arm.com    DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
30013014Sciro.santilli@arm.com            ctx);
30113014Sciro.santilli@arm.com
30213230Sgabeblack@google.com    pkt->setLE<uint32_t>(readCpu(ctx, daddr));
30313014Sciro.santilli@arm.com
30413014Sciro.santilli@arm.com    pkt->makeAtomicResponse();
30513014Sciro.santilli@arm.com    return cpuPioDelay;
30613014Sciro.santilli@arm.com}
30713014Sciro.santilli@arm.com
30813014Sciro.santilli@arm.comuint32_t
30913014Sciro.santilli@arm.comGicV2::readCpu(ContextID ctx, Addr daddr)
31013014Sciro.santilli@arm.com{
31113014Sciro.santilli@arm.com    switch(daddr) {
31213014Sciro.santilli@arm.com      case GICC_IIDR:
31313505Sgiacomo.travaglini@arm.com        return giccIIDR;
31413014Sciro.santilli@arm.com      case GICC_CTLR:
31513109Sgiacomo.travaglini@arm.com        return cpuControl[ctx];
31613014Sciro.santilli@arm.com      case GICC_PMR:
31713014Sciro.santilli@arm.com        return cpuPriority[ctx];
31813014Sciro.santilli@arm.com      case GICC_BPR:
31913014Sciro.santilli@arm.com        return cpuBpr[ctx];
32013014Sciro.santilli@arm.com      case GICC_IAR:
32113109Sgiacomo.travaglini@arm.com        if (enabled && cpuEnabled(ctx)) {
32213014Sciro.santilli@arm.com            int active_int = cpuHighestInt[ctx];
32313014Sciro.santilli@arm.com            IAR iar = 0;
32413014Sciro.santilli@arm.com            iar.ack_id = active_int;
32513014Sciro.santilli@arm.com            iar.cpu_id = 0;
32613014Sciro.santilli@arm.com            if (active_int < SGI_MAX) {
32713014Sciro.santilli@arm.com                // this is a software interrupt from another CPU
32813014Sciro.santilli@arm.com                if (!gem5ExtensionsEnabled) {
32913014Sciro.santilli@arm.com                    panic_if(!cpuSgiPending[active_int],
33013014Sciro.santilli@arm.com                            "Interrupt %d active but no CPU generated it?\n",
33113014Sciro.santilli@arm.com                            active_int);
33213014Sciro.santilli@arm.com                    for (int x = 0; x < sys->numRunningContexts(); x++) {
33313014Sciro.santilli@arm.com                        // See which CPU generated the interrupt
33413014Sciro.santilli@arm.com                        uint8_t cpugen =
33513014Sciro.santilli@arm.com                            bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
33613014Sciro.santilli@arm.com                        if (cpugen & (1 << ctx)) {
33713014Sciro.santilli@arm.com                            iar.cpu_id = x;
33813014Sciro.santilli@arm.com                            break;
33913014Sciro.santilli@arm.com                        }
34013014Sciro.santilli@arm.com                    }
34113014Sciro.santilli@arm.com                    uint64_t sgi_num = ULL(1) << (ctx + 8 * iar.cpu_id);
34213014Sciro.santilli@arm.com                    cpuSgiActive[iar.ack_id] |= sgi_num;
34313014Sciro.santilli@arm.com                    cpuSgiPending[iar.ack_id] &= ~sgi_num;
34413014Sciro.santilli@arm.com                } else {
34513014Sciro.santilli@arm.com                    uint64_t sgi_num = ULL(1) << iar.ack_id;
34613014Sciro.santilli@arm.com                    cpuSgiActiveExt[ctx] |= sgi_num;
34713014Sciro.santilli@arm.com                    cpuSgiPendingExt[ctx] &= ~sgi_num;
34813014Sciro.santilli@arm.com                }
34913014Sciro.santilli@arm.com            } else if (active_int < (SGI_MAX + PPI_MAX) ) {
35013014Sciro.santilli@arm.com                uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX);
35113014Sciro.santilli@arm.com                cpuPpiActive[ctx] |= int_num;
35213014Sciro.santilli@arm.com                updateRunPri();
35313014Sciro.santilli@arm.com                cpuPpiPending[ctx] &= ~int_num;
35413014Sciro.santilli@arm.com
35513014Sciro.santilli@arm.com            } else {
35613014Sciro.santilli@arm.com                uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]);
35713014Sciro.santilli@arm.com                getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num;
35813014Sciro.santilli@arm.com                updateRunPri();
35913108Sadrien.pesle@arm.com                if (!isLevelSensitive(ctx, active_int)) {
36013108Sadrien.pesle@arm.com                    getPendingInt(ctx, intNumToWord(cpuHighestInt[ctx]))
36113108Sadrien.pesle@arm.com                      &= ~int_num;
36213108Sadrien.pesle@arm.com                }
36313014Sciro.santilli@arm.com            }
36413014Sciro.santilli@arm.com
36513014Sciro.santilli@arm.com            DPRINTF(Interrupt,
36613014Sciro.santilli@arm.com                    "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
36713014Sciro.santilli@arm.com                    ctx, iar.ack_id, iar.cpu_id, iar);
36813014Sciro.santilli@arm.com            cpuHighestInt[ctx] = SPURIOUS_INT;
36913014Sciro.santilli@arm.com            updateIntState(-1);
37013112Sgiacomo.travaglini@arm.com            clearInt(ctx, active_int);
37113014Sciro.santilli@arm.com            return iar;
37213014Sciro.santilli@arm.com        } else {
37313014Sciro.santilli@arm.com             return SPURIOUS_INT;
37413014Sciro.santilli@arm.com        }
37513014Sciro.santilli@arm.com
37613014Sciro.santilli@arm.com        break;
37713014Sciro.santilli@arm.com      case GICC_RPR:
37813014Sciro.santilli@arm.com        return iccrpr[0];
37913014Sciro.santilli@arm.com      case GICC_HPPIR:
38013014Sciro.santilli@arm.com        panic("Need to implement HPIR");
38113014Sciro.santilli@arm.com        break;
38213014Sciro.santilli@arm.com      default:
38313014Sciro.santilli@arm.com        panic("Tried to read Gic cpu at offset %#x\n", daddr);
38413014Sciro.santilli@arm.com        break;
38513014Sciro.santilli@arm.com    }
38613014Sciro.santilli@arm.com}
38713014Sciro.santilli@arm.com
38813014Sciro.santilli@arm.comTick
38913014Sciro.santilli@arm.comGicV2::writeDistributor(PacketPtr pkt)
39013014Sciro.santilli@arm.com{
39113014Sciro.santilli@arm.com    const Addr daddr = pkt->getAddr() - distRange.start();
39213014Sciro.santilli@arm.com
39313014Sciro.santilli@arm.com    assert(pkt->req->hasContextId());
39413014Sciro.santilli@arm.com    const ContextID ctx = pkt->req->contextId();
39513014Sciro.santilli@arm.com    const size_t data_sz = pkt->getSize();
39613014Sciro.santilli@arm.com
39713014Sciro.santilli@arm.com    uint32_t pkt_data M5_VAR_USED;
39813014Sciro.santilli@arm.com    switch (data_sz)
39913014Sciro.santilli@arm.com    {
40013014Sciro.santilli@arm.com      case 1:
40113230Sgabeblack@google.com        pkt_data = pkt->getLE<uint8_t>();
40213014Sciro.santilli@arm.com        break;
40313014Sciro.santilli@arm.com      case 2:
40413230Sgabeblack@google.com        pkt_data = pkt->getLE<uint16_t>();
40513014Sciro.santilli@arm.com        break;
40613014Sciro.santilli@arm.com      case 4:
40713230Sgabeblack@google.com        pkt_data = pkt->getLE<uint32_t>();
40813014Sciro.santilli@arm.com        break;
40913014Sciro.santilli@arm.com      default:
41013014Sciro.santilli@arm.com        panic("Invalid size when writing to priority regs in Gic: %d\n",
41113014Sciro.santilli@arm.com              data_sz);
41213014Sciro.santilli@arm.com    }
41313014Sciro.santilli@arm.com
41413014Sciro.santilli@arm.com    DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
41513014Sciro.santilli@arm.com            daddr, data_sz, pkt_data);
41613014Sciro.santilli@arm.com
41713014Sciro.santilli@arm.com    writeDistributor(ctx, daddr, pkt_data, data_sz);
41813014Sciro.santilli@arm.com
41913014Sciro.santilli@arm.com    pkt->makeAtomicResponse();
42013014Sciro.santilli@arm.com    return distPioDelay;
42113014Sciro.santilli@arm.com}
42213014Sciro.santilli@arm.com
42313014Sciro.santilli@arm.comvoid
42413014Sciro.santilli@arm.comGicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
42513014Sciro.santilli@arm.com                        size_t data_sz)
42613014Sciro.santilli@arm.com{
42713014Sciro.santilli@arm.com    if (GICD_IGROUPR.contains(daddr)) {
42813110Sgiacomo.travaglini@arm.com        uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2;
42913110Sgiacomo.travaglini@arm.com        assert(ix < 32);
43013110Sgiacomo.travaglini@arm.com        getIntGroup(ctx, ix) |= data;
43113110Sgiacomo.travaglini@arm.com        return;
43213014Sciro.santilli@arm.com    }
43313014Sciro.santilli@arm.com
43413014Sciro.santilli@arm.com    if (GICD_ISENABLER.contains(daddr)) {
43513014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
43613014Sciro.santilli@arm.com        assert(ix < 32);
43713014Sciro.santilli@arm.com        getIntEnabled(ctx, ix) |= data;
43813014Sciro.santilli@arm.com        return;
43913014Sciro.santilli@arm.com    }
44013014Sciro.santilli@arm.com
44113014Sciro.santilli@arm.com    if (GICD_ICENABLER.contains(daddr)) {
44213014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
44313014Sciro.santilli@arm.com        assert(ix < 32);
44413014Sciro.santilli@arm.com        getIntEnabled(ctx, ix) &= ~data;
44513014Sciro.santilli@arm.com        return;
44613014Sciro.santilli@arm.com    }
44713014Sciro.santilli@arm.com
44813014Sciro.santilli@arm.com    if (GICD_ISPENDR.contains(daddr)) {
44913014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
45013014Sciro.santilli@arm.com        auto mask = data;
45113014Sciro.santilli@arm.com        if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
45213014Sciro.santilli@arm.com        getPendingInt(ctx, ix) |= mask;
45313014Sciro.santilli@arm.com        updateIntState(ix);
45413014Sciro.santilli@arm.com        return;
45513014Sciro.santilli@arm.com    }
45613014Sciro.santilli@arm.com
45713014Sciro.santilli@arm.com    if (GICD_ICPENDR.contains(daddr)) {
45813014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
45913014Sciro.santilli@arm.com        auto mask = data;
46013014Sciro.santilli@arm.com        if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
46113014Sciro.santilli@arm.com        getPendingInt(ctx, ix) &= ~mask;
46213014Sciro.santilli@arm.com        updateIntState(ix);
46313014Sciro.santilli@arm.com        return;
46413014Sciro.santilli@arm.com    }
46513014Sciro.santilli@arm.com
46613014Sciro.santilli@arm.com    if (GICD_ISACTIVER.contains(daddr)) {
46713014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
46813014Sciro.santilli@arm.com        getActiveInt(ctx, ix) |= data;
46913014Sciro.santilli@arm.com        return;
47013014Sciro.santilli@arm.com    }
47113014Sciro.santilli@arm.com
47213014Sciro.santilli@arm.com    if (GICD_ICACTIVER.contains(daddr)) {
47313014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
47413014Sciro.santilli@arm.com        getActiveInt(ctx, ix) &= ~data;
47513014Sciro.santilli@arm.com        return;
47613014Sciro.santilli@arm.com    }
47713014Sciro.santilli@arm.com
47813014Sciro.santilli@arm.com    if (GICD_IPRIORITYR.contains(daddr)) {
47913014Sciro.santilli@arm.com        Addr int_num = daddr - GICD_IPRIORITYR.start();
48013014Sciro.santilli@arm.com        switch(data_sz) {
48113014Sciro.santilli@arm.com          case 1:
48213014Sciro.santilli@arm.com            getIntPriority(ctx, int_num) = data;
48313014Sciro.santilli@arm.com            break;
48413014Sciro.santilli@arm.com          case 2: {
48513014Sciro.santilli@arm.com            getIntPriority(ctx, int_num) = bits(data, 7, 0);
48613014Sciro.santilli@arm.com            getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
48713014Sciro.santilli@arm.com            break;
48813014Sciro.santilli@arm.com          }
48913014Sciro.santilli@arm.com          case 4: {
49013014Sciro.santilli@arm.com            getIntPriority(ctx, int_num) = bits(data, 7, 0);
49113014Sciro.santilli@arm.com            getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
49213014Sciro.santilli@arm.com            getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
49313014Sciro.santilli@arm.com            getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
49413014Sciro.santilli@arm.com            break;
49513014Sciro.santilli@arm.com          }
49613014Sciro.santilli@arm.com          default:
49713014Sciro.santilli@arm.com            panic("Invalid size when writing to priority regs in Gic: %d\n",
49813014Sciro.santilli@arm.com                   data_sz);
49913014Sciro.santilli@arm.com        }
50013014Sciro.santilli@arm.com
50113014Sciro.santilli@arm.com        updateIntState(-1);
50213014Sciro.santilli@arm.com        updateRunPri();
50313014Sciro.santilli@arm.com        return;
50413014Sciro.santilli@arm.com    }
50513014Sciro.santilli@arm.com
50613014Sciro.santilli@arm.com    if (GICD_ITARGETSR.contains(daddr)) {
50713014Sciro.santilli@arm.com        Addr int_num = daddr - GICD_ITARGETSR.start();
50813014Sciro.santilli@arm.com        // Interrupts 0-31 are read only
50913014Sciro.santilli@arm.com        unsigned offset = SGI_MAX + PPI_MAX;
51013014Sciro.santilli@arm.com        if (int_num >= offset) {
51113014Sciro.santilli@arm.com            unsigned ix = int_num - offset; // index into cpuTarget array
51213014Sciro.santilli@arm.com            if (data_sz == 1) {
51313014Sciro.santilli@arm.com                cpuTarget[ix] = data & 0xff;
51413014Sciro.santilli@arm.com            } else {
51513014Sciro.santilli@arm.com                assert (data_sz == 4);
51613014Sciro.santilli@arm.com                cpuTarget[ix]   = bits(data, 7, 0);
51713014Sciro.santilli@arm.com                cpuTarget[ix+1] = bits(data, 15, 8);
51813014Sciro.santilli@arm.com                cpuTarget[ix+2] = bits(data, 23, 16);
51913014Sciro.santilli@arm.com                cpuTarget[ix+3] = bits(data, 31, 24);
52013014Sciro.santilli@arm.com            }
52113014Sciro.santilli@arm.com            updateIntState(int_num >> 2);
52213014Sciro.santilli@arm.com        }
52313014Sciro.santilli@arm.com        return;
52413014Sciro.santilli@arm.com    }
52513014Sciro.santilli@arm.com
52613014Sciro.santilli@arm.com    if (GICD_ICFGR.contains(daddr)) {
52713014Sciro.santilli@arm.com        uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
52813014Sciro.santilli@arm.com        assert(ix < INT_BITS_MAX*2);
52913014Sciro.santilli@arm.com        intConfig[ix] = data;
53013014Sciro.santilli@arm.com        if (data & NN_CONFIG_MASK)
53113014Sciro.santilli@arm.com            warn("GIC N:N mode selected and not supported at this time\n");
53213014Sciro.santilli@arm.com        return;
53313014Sciro.santilli@arm.com    }
53413014Sciro.santilli@arm.com
53513014Sciro.santilli@arm.com    switch(daddr) {
53613014Sciro.santilli@arm.com      case GICD_CTLR:
53713014Sciro.santilli@arm.com        enabled = data;
53813014Sciro.santilli@arm.com        DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
53913014Sciro.santilli@arm.com        break;
54013014Sciro.santilli@arm.com      case GICD_TYPER:
54113014Sciro.santilli@arm.com        /* 0x200 is a made-up flag to enable gem5 extension functionality.
54213014Sciro.santilli@arm.com         * This reg is not normally written.
54313014Sciro.santilli@arm.com         */
54413014Sciro.santilli@arm.com        gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions;
54513014Sciro.santilli@arm.com        DPRINTF(GIC, "gem5 extensions %s\n",
54613014Sciro.santilli@arm.com                gem5ExtensionsEnabled ? "enabled" : "disabled");
54713014Sciro.santilli@arm.com        break;
54813014Sciro.santilli@arm.com      case GICD_SGIR:
54913014Sciro.santilli@arm.com        softInt(ctx, data);
55013014Sciro.santilli@arm.com        break;
55113014Sciro.santilli@arm.com      default:
55213014Sciro.santilli@arm.com        panic("Tried to write Gic distributor at offset %#x\n", daddr);
55313014Sciro.santilli@arm.com        break;
55413014Sciro.santilli@arm.com    }
55513014Sciro.santilli@arm.com}
55613014Sciro.santilli@arm.com
55713014Sciro.santilli@arm.comTick
55813014Sciro.santilli@arm.comGicV2::writeCpu(PacketPtr pkt)
55913014Sciro.santilli@arm.com{
56013014Sciro.santilli@arm.com    const Addr daddr = pkt->getAddr() - cpuRange.start();
56113014Sciro.santilli@arm.com
56213014Sciro.santilli@arm.com    assert(pkt->req->hasContextId());
56313014Sciro.santilli@arm.com    const ContextID ctx = pkt->req->contextId();
56413230Sgabeblack@google.com    const uint32_t data = pkt->getLE<uint32_t>();
56513014Sciro.santilli@arm.com
56613014Sciro.santilli@arm.com    DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
56713014Sciro.santilli@arm.com            ctx, daddr, data);
56813014Sciro.santilli@arm.com
56913014Sciro.santilli@arm.com    writeCpu(ctx, daddr, data);
57013014Sciro.santilli@arm.com
57113014Sciro.santilli@arm.com    pkt->makeAtomicResponse();
57213014Sciro.santilli@arm.com    return cpuPioDelay;
57313014Sciro.santilli@arm.com}
57413014Sciro.santilli@arm.com
57513014Sciro.santilli@arm.comvoid
57613014Sciro.santilli@arm.comGicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
57713014Sciro.santilli@arm.com{
57813014Sciro.santilli@arm.com    switch(daddr) {
57913014Sciro.santilli@arm.com      case GICC_CTLR:
58013109Sgiacomo.travaglini@arm.com        cpuControl[ctx] = data;
58113014Sciro.santilli@arm.com        break;
58213014Sciro.santilli@arm.com      case GICC_PMR:
58313014Sciro.santilli@arm.com        cpuPriority[ctx] = data;
58413014Sciro.santilli@arm.com        break;
58513014Sciro.santilli@arm.com      case GICC_BPR: {
58613014Sciro.santilli@arm.com        auto bpr = data & 0x7;
58713014Sciro.santilli@arm.com        if (bpr < GICC_BPR_MINIMUM)
58813014Sciro.santilli@arm.com            bpr = GICC_BPR_MINIMUM;
58913014Sciro.santilli@arm.com        cpuBpr[ctx] = bpr;
59013014Sciro.santilli@arm.com        break;
59113014Sciro.santilli@arm.com      }
59213014Sciro.santilli@arm.com      case GICC_EOIR: {
59313014Sciro.santilli@arm.com        const IAR iar = data;
59413014Sciro.santilli@arm.com        if (iar.ack_id < SGI_MAX) {
59513014Sciro.santilli@arm.com            // Clear out the bit that corresponds to the cleared int
59613014Sciro.santilli@arm.com            uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id);
59713014Sciro.santilli@arm.com            if (!(cpuSgiActive[iar.ack_id] & clr_int) &&
59813014Sciro.santilli@arm.com                !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id)))
59913014Sciro.santilli@arm.com                panic("Done handling a SGI that isn't active?\n");
60013014Sciro.santilli@arm.com            if (gem5ExtensionsEnabled)
60113014Sciro.santilli@arm.com                cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id);
60213014Sciro.santilli@arm.com            else
60313014Sciro.santilli@arm.com                cpuSgiActive[iar.ack_id] &= ~clr_int;
60413014Sciro.santilli@arm.com        } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
60513014Sciro.santilli@arm.com            uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
60613014Sciro.santilli@arm.com            if (!(cpuPpiActive[ctx] & int_num))
60713337Sadrien.pesle@arm.com                warn("CPU %d Done handling a PPI interrupt "
60813014Sciro.santilli@arm.com                      "that isn't active?\n", ctx);
60913014Sciro.santilli@arm.com            cpuPpiActive[ctx] &= ~int_num;
61013014Sciro.santilli@arm.com        } else {
61113014Sciro.santilli@arm.com            uint32_t int_num = 1 << intNumToBit(iar.ack_id);
61213014Sciro.santilli@arm.com            if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num))
61313014Sciro.santilli@arm.com                warn("Done handling interrupt that isn't active: %d\n",
61413014Sciro.santilli@arm.com                      intNumToBit(iar.ack_id));
61513014Sciro.santilli@arm.com            getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num;
61613014Sciro.santilli@arm.com        }
61713014Sciro.santilli@arm.com        updateRunPri();
61813014Sciro.santilli@arm.com        DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
61913014Sciro.santilli@arm.com                ctx, iar.ack_id, iar.cpu_id);
62013014Sciro.santilli@arm.com        break;
62113014Sciro.santilli@arm.com      }
62213014Sciro.santilli@arm.com      case GICC_APR0:
62313014Sciro.santilli@arm.com      case GICC_APR1:
62413014Sciro.santilli@arm.com      case GICC_APR2:
62513014Sciro.santilli@arm.com      case GICC_APR3:
62613014Sciro.santilli@arm.com        warn("GIC APRn write ignored because not implemented: %#x\n", daddr);
62713014Sciro.santilli@arm.com        break;
62813503Sanouk.vanlaer@arm.com      case GICC_DIR:
62913503Sanouk.vanlaer@arm.com        warn("GIC DIR write ignored because not implemented: %#x\n", daddr);
63013503Sanouk.vanlaer@arm.com        break;
63113014Sciro.santilli@arm.com      default:
63213014Sciro.santilli@arm.com        panic("Tried to write Gic cpu at offset %#x\n", daddr);
63313014Sciro.santilli@arm.com        break;
63413014Sciro.santilli@arm.com    }
63513109Sgiacomo.travaglini@arm.com    if (cpuEnabled(ctx)) updateIntState(-1);
63613014Sciro.santilli@arm.com}
63713014Sciro.santilli@arm.com
63813014Sciro.santilli@arm.comGicV2::BankedRegs&
63913014Sciro.santilli@arm.comGicV2::getBankedRegs(ContextID ctx) {
64013014Sciro.santilli@arm.com    if (bankedRegs.size() <= ctx)
64113014Sciro.santilli@arm.com        bankedRegs.resize(ctx + 1);
64213014Sciro.santilli@arm.com
64313014Sciro.santilli@arm.com    if (!bankedRegs[ctx])
64413014Sciro.santilli@arm.com        bankedRegs[ctx] = new BankedRegs;
64513014Sciro.santilli@arm.com    return *bankedRegs[ctx];
64613014Sciro.santilli@arm.com}
64713014Sciro.santilli@arm.com
64813014Sciro.santilli@arm.comvoid
64913014Sciro.santilli@arm.comGicV2::softInt(ContextID ctx, SWI swi)
65013014Sciro.santilli@arm.com{
65113014Sciro.santilli@arm.com    if (gem5ExtensionsEnabled) {
65213014Sciro.santilli@arm.com        switch (swi.list_type) {
65313014Sciro.santilli@arm.com          case 0: {
65413014Sciro.santilli@arm.com             // interrupt cpus specified
65513014Sciro.santilli@arm.com             int dest = swi.cpu_list;
65613014Sciro.santilli@arm.com             DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
65713014Sciro.santilli@arm.com                    ctx, dest);
65813109Sgiacomo.travaglini@arm.com             if (cpuEnabled(dest)) {
65913014Sciro.santilli@arm.com                 cpuSgiPendingExt[dest] |= (1 << swi.sgi_id);
66013014Sciro.santilli@arm.com                 DPRINTF(IPI, "SGI[%d]=%#x\n", dest,
66113014Sciro.santilli@arm.com                         cpuSgiPendingExt[dest]);
66213014Sciro.santilli@arm.com             }
66313014Sciro.santilli@arm.com          } break;
66413014Sciro.santilli@arm.com          case 1: {
66513014Sciro.santilli@arm.com             // interrupt all
66613014Sciro.santilli@arm.com             for (int i = 0; i < sys->numContexts(); i++) {
66713014Sciro.santilli@arm.com                 DPRINTF(IPI, "Processing CPU %d\n", i);
66813109Sgiacomo.travaglini@arm.com                 if (!cpuEnabled(i))
66913014Sciro.santilli@arm.com                     continue;
67013014Sciro.santilli@arm.com                 cpuSgiPendingExt[i] |= 1 << swi.sgi_id;
67113014Sciro.santilli@arm.com                 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
67213014Sciro.santilli@arm.com                         cpuSgiPendingExt[i]);
67313014Sciro.santilli@arm.com              }
67413014Sciro.santilli@arm.com          } break;
67513014Sciro.santilli@arm.com          case 2: {
67613014Sciro.santilli@arm.com            // Interrupt requesting cpu only
67713014Sciro.santilli@arm.com            DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
67813014Sciro.santilli@arm.com                    ctx, ctx);
67913109Sgiacomo.travaglini@arm.com            if (cpuEnabled(ctx)) {
68013014Sciro.santilli@arm.com                cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id);
68113014Sciro.santilli@arm.com                DPRINTF(IPI, "SGI[%d]=%#x\n", ctx,
68213014Sciro.santilli@arm.com                        cpuSgiPendingExt[ctx]);
68313014Sciro.santilli@arm.com            }
68413014Sciro.santilli@arm.com          } break;
68513014Sciro.santilli@arm.com        }
68613014Sciro.santilli@arm.com    } else {
68713014Sciro.santilli@arm.com        switch (swi.list_type) {
68813014Sciro.santilli@arm.com          case 1:
68913014Sciro.santilli@arm.com            // interrupt all
69013014Sciro.santilli@arm.com            uint8_t cpu_list;
69113014Sciro.santilli@arm.com            cpu_list = 0;
69213014Sciro.santilli@arm.com            for (int x = 0; x < sys->numContexts(); x++)
69313109Sgiacomo.travaglini@arm.com                cpu_list |= cpuEnabled(x) ? 1 << x : 0;
69413014Sciro.santilli@arm.com            swi.cpu_list = cpu_list;
69513014Sciro.santilli@arm.com            break;
69613014Sciro.santilli@arm.com          case 2:
69713014Sciro.santilli@arm.com            // interrupt requesting cpu only
69813014Sciro.santilli@arm.com            swi.cpu_list = 1 << ctx;
69913014Sciro.santilli@arm.com            break;
70013014Sciro.santilli@arm.com            // else interrupt cpus specified
70113014Sciro.santilli@arm.com        }
70213014Sciro.santilli@arm.com
70313014Sciro.santilli@arm.com        DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx,
70413014Sciro.santilli@arm.com                swi.cpu_list);
70513014Sciro.santilli@arm.com        for (int i = 0; i < sys->numContexts(); i++) {
70613014Sciro.santilli@arm.com            DPRINTF(IPI, "Processing CPU %d\n", i);
70713109Sgiacomo.travaglini@arm.com            if (!cpuEnabled(i))
70813014Sciro.santilli@arm.com                continue;
70913014Sciro.santilli@arm.com            if (swi.cpu_list & (1 << i))
71013014Sciro.santilli@arm.com                cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx);
71113014Sciro.santilli@arm.com            DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
71213014Sciro.santilli@arm.com                    cpuSgiPending[swi.sgi_id]);
71313014Sciro.santilli@arm.com        }
71413014Sciro.santilli@arm.com    }
71513014Sciro.santilli@arm.com    updateIntState(-1);
71613014Sciro.santilli@arm.com}
71713014Sciro.santilli@arm.com
71813014Sciro.santilli@arm.comuint64_t
71913014Sciro.santilli@arm.comGicV2::genSwiMask(int cpu)
72013014Sciro.santilli@arm.com{
72113014Sciro.santilli@arm.com    if (cpu > sys->numContexts())
72213014Sciro.santilli@arm.com        panic("Invalid CPU ID\n");
72313014Sciro.santilli@arm.com    return ULL(0x0101010101010101) << cpu;
72413014Sciro.santilli@arm.com}
72513014Sciro.santilli@arm.com
72613014Sciro.santilli@arm.comuint8_t
72713014Sciro.santilli@arm.comGicV2::getCpuPriority(unsigned cpu)
72813014Sciro.santilli@arm.com{
72913014Sciro.santilli@arm.com    // see Table 3-2 in IHI0048B.b (GICv2)
73013014Sciro.santilli@arm.com    // mask some low-order priority bits per BPR value
73113014Sciro.santilli@arm.com    // NB: the GIC prioritization scheme is upside down:
73213014Sciro.santilli@arm.com    // lower values are higher priority; masking off bits
73313014Sciro.santilli@arm.com    // actually creates a higher priority, not lower.
73413014Sciro.santilli@arm.com    return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu]));
73513014Sciro.santilli@arm.com}
73613014Sciro.santilli@arm.com
73713014Sciro.santilli@arm.comvoid
73813014Sciro.santilli@arm.comGicV2::updateIntState(int hint)
73913014Sciro.santilli@arm.com{
74013014Sciro.santilli@arm.com    for (int cpu = 0; cpu < sys->numContexts(); cpu++) {
74113109Sgiacomo.travaglini@arm.com        if (!cpuEnabled(cpu))
74213014Sciro.santilli@arm.com            continue;
74313014Sciro.santilli@arm.com
74413014Sciro.santilli@arm.com        /*@todo use hint to do less work. */
74513014Sciro.santilli@arm.com        int highest_int = SPURIOUS_INT;
74613014Sciro.santilli@arm.com        // Priorities below that set in GICC_PMR can be ignored
74713014Sciro.santilli@arm.com        uint8_t highest_pri = getCpuPriority(cpu);
74813014Sciro.santilli@arm.com
74913014Sciro.santilli@arm.com        // Check SGIs
75013014Sciro.santilli@arm.com        for (int swi = 0; swi < SGI_MAX; swi++) {
75113014Sciro.santilli@arm.com            if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu])
75213014Sciro.santilli@arm.com                continue;
75313014Sciro.santilli@arm.com            if ((cpuSgiPending[swi] & genSwiMask(cpu)) ||
75413014Sciro.santilli@arm.com                (cpuSgiPendingExt[cpu] & (1 << swi)))
75513014Sciro.santilli@arm.com                if (highest_pri > getIntPriority(cpu, swi)) {
75613014Sciro.santilli@arm.com                    highest_pri = getIntPriority(cpu, swi);
75713014Sciro.santilli@arm.com                    highest_int = swi;
75813014Sciro.santilli@arm.com                }
75913014Sciro.santilli@arm.com        }
76013014Sciro.santilli@arm.com
76113014Sciro.santilli@arm.com        // Check PPIs
76213014Sciro.santilli@arm.com        if (cpuPpiPending[cpu]) {
76313105Sgiacomo.travaglini@arm.com            for (int ppi_idx = 0, int_num = SGI_MAX;
76413105Sgiacomo.travaglini@arm.com                 int_num < PPI_MAX + SGI_MAX;
76513105Sgiacomo.travaglini@arm.com                 ppi_idx++, int_num++) {
76613105Sgiacomo.travaglini@arm.com
76713105Sgiacomo.travaglini@arm.com                const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx);
76813105Sgiacomo.travaglini@arm.com                const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num);
76913105Sgiacomo.travaglini@arm.com                const bool higher_priority =
77013105Sgiacomo.travaglini@arm.com                    highest_pri > getIntPriority(cpu, int_num);
77113105Sgiacomo.travaglini@arm.com
77213105Sgiacomo.travaglini@arm.com                if (ppi_pending && ppi_enabled && higher_priority) {
77313105Sgiacomo.travaglini@arm.com                    highest_pri = getIntPriority(cpu, int_num);
77413105Sgiacomo.travaglini@arm.com                    highest_int = int_num;
77513014Sciro.santilli@arm.com                }
77613014Sciro.santilli@arm.com            }
77713014Sciro.santilli@arm.com        }
77813014Sciro.santilli@arm.com
77913014Sciro.santilli@arm.com        bool mp_sys = sys->numRunningContexts() > 1;
78013014Sciro.santilli@arm.com        // Check other ints
78113014Sciro.santilli@arm.com        for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
78213014Sciro.santilli@arm.com            if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) {
78313014Sciro.santilli@arm.com                for (int y = 0; y < INT_BITS_MAX; y++) {
78413014Sciro.santilli@arm.com                   uint32_t int_nm = x * INT_BITS_MAX + y;
78513014Sciro.santilli@arm.com                   DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
78613014Sciro.santilli@arm.com                    /* Set current pending int as highest int for current cpu
78713014Sciro.santilli@arm.com                       if the interrupt's priority higher than current priority
78813014Sciro.santilli@arm.com                       and if current cpu is the target (for mp configs only)
78913014Sciro.santilli@arm.com                     */
79013014Sciro.santilli@arm.com                    if ((bits(getIntEnabled(cpu, x), y)
79113014Sciro.santilli@arm.com                        &bits(getPendingInt(cpu, x), y)) &&
79213014Sciro.santilli@arm.com                        (getIntPriority(cpu, int_nm) < highest_pri))
79313014Sciro.santilli@arm.com                        if ((!mp_sys) ||
79413014Sciro.santilli@arm.com                            (gem5ExtensionsEnabled
79513014Sciro.santilli@arm.com                               ? (getCpuTarget(cpu, int_nm) == cpu)
79613014Sciro.santilli@arm.com                               : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) {
79713014Sciro.santilli@arm.com                            highest_pri = getIntPriority(cpu, int_nm);
79813014Sciro.santilli@arm.com                            highest_int = int_nm;
79913014Sciro.santilli@arm.com                        }
80013014Sciro.santilli@arm.com                }
80113014Sciro.santilli@arm.com            }
80213014Sciro.santilli@arm.com        }
80313014Sciro.santilli@arm.com
80413108Sadrien.pesle@arm.com        uint32_t prev_highest = cpuHighestInt[cpu];
80513014Sciro.santilli@arm.com        cpuHighestInt[cpu] = highest_int;
80613014Sciro.santilli@arm.com
80713108Sadrien.pesle@arm.com        if (highest_int == SPURIOUS_INT) {
80813108Sadrien.pesle@arm.com            if (isLevelSensitive(cpu, prev_highest)) {
80913108Sadrien.pesle@arm.com
81013108Sadrien.pesle@arm.com                DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu);
81113112Sgiacomo.travaglini@arm.com                clearInt(cpu, prev_highest);
81213108Sadrien.pesle@arm.com            }
81313014Sciro.santilli@arm.com            continue;
81413108Sadrien.pesle@arm.com        }
81513014Sciro.santilli@arm.com
81613014Sciro.santilli@arm.com        /* @todo make this work for more than one cpu, need to handle 1:N, N:N
81713014Sciro.santilli@arm.com         * models */
81813109Sgiacomo.travaglini@arm.com        if (enabled && cpuEnabled(cpu) &&
81913014Sciro.santilli@arm.com            (highest_pri < getCpuPriority(cpu)) &&
82013014Sciro.santilli@arm.com            !(getActiveInt(cpu, intNumToWord(highest_int))
82113014Sciro.santilli@arm.com              & (1 << intNumToBit(highest_int)))) {
82213014Sciro.santilli@arm.com
82313014Sciro.santilli@arm.com            DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
82413014Sciro.santilli@arm.com                    cpu);
82513112Sgiacomo.travaglini@arm.com
82613112Sgiacomo.travaglini@arm.com            if (isFiq(cpu, highest_int)) {
82713112Sgiacomo.travaglini@arm.com                postFiq(cpu, curTick() + intLatency);
82813112Sgiacomo.travaglini@arm.com            } else {
82913112Sgiacomo.travaglini@arm.com                postInt(cpu, curTick() + intLatency);
83013112Sgiacomo.travaglini@arm.com            }
83113014Sciro.santilli@arm.com        }
83213014Sciro.santilli@arm.com    }
83313014Sciro.santilli@arm.com}
83413014Sciro.santilli@arm.com
83513014Sciro.santilli@arm.comvoid
83613014Sciro.santilli@arm.comGicV2::updateRunPri()
83713014Sciro.santilli@arm.com{
83813014Sciro.santilli@arm.com    for (int cpu = 0; cpu < sys->numContexts(); cpu++) {
83913109Sgiacomo.travaglini@arm.com        if (!cpuEnabled(cpu))
84013014Sciro.santilli@arm.com            continue;
84113014Sciro.santilli@arm.com        uint8_t maxPriority = 0xff;
84213014Sciro.santilli@arm.com        for (int i = 0; i < itLines; i++) {
84313014Sciro.santilli@arm.com            if (i < SGI_MAX) {
84413014Sciro.santilli@arm.com                if (((cpuSgiActive[i] & genSwiMask(cpu)) ||
84513014Sciro.santilli@arm.com                     (cpuSgiActiveExt[cpu] & (1 << i))) &&
84613014Sciro.santilli@arm.com                        (getIntPriority(cpu, i) < maxPriority))
84713014Sciro.santilli@arm.com                    maxPriority = getIntPriority(cpu, i);
84813014Sciro.santilli@arm.com            } else if (i < (SGI_MAX + PPI_MAX)) {
84913014Sciro.santilli@arm.com                if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
85013014Sciro.santilli@arm.com                        (getIntPriority(cpu, i) < maxPriority))
85113014Sciro.santilli@arm.com                    maxPriority = getIntPriority(cpu, i);
85213014Sciro.santilli@arm.com
85313014Sciro.santilli@arm.com            } else {
85413014Sciro.santilli@arm.com                if (getActiveInt(cpu, intNumToWord(i))
85513014Sciro.santilli@arm.com                    & (1 << intNumToBit(i)))
85613014Sciro.santilli@arm.com                    if (getIntPriority(cpu, i) < maxPriority)
85713014Sciro.santilli@arm.com                        maxPriority = getIntPriority(cpu, i);
85813014Sciro.santilli@arm.com            }
85913014Sciro.santilli@arm.com        }
86013014Sciro.santilli@arm.com        iccrpr[cpu] = maxPriority;
86113014Sciro.santilli@arm.com    }
86213014Sciro.santilli@arm.com}
86313014Sciro.santilli@arm.com
86413014Sciro.santilli@arm.comvoid
86513014Sciro.santilli@arm.comGicV2::sendInt(uint32_t num)
86613014Sciro.santilli@arm.com{
86713014Sciro.santilli@arm.com    uint8_t target = getCpuTarget(0, num);
86813014Sciro.santilli@arm.com    DPRINTF(Interrupt, "Received Interrupt number %d,  cpuTarget %#x: \n",
86913014Sciro.santilli@arm.com            num, target);
87013014Sciro.santilli@arm.com    if ((target & (target - 1)) && !gem5ExtensionsEnabled)
87113014Sciro.santilli@arm.com        panic("Multiple targets for peripheral interrupts is not supported\n");
87213014Sciro.santilli@arm.com    panic_if(num < SGI_MAX + PPI_MAX,
87313014Sciro.santilli@arm.com             "sentInt() must only be used for interrupts 32 and higher");
87413014Sciro.santilli@arm.com    getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num);
87513014Sciro.santilli@arm.com    updateIntState(intNumToWord(num));
87613014Sciro.santilli@arm.com}
87713014Sciro.santilli@arm.com
87813014Sciro.santilli@arm.comvoid
87913014Sciro.santilli@arm.comGicV2::sendPPInt(uint32_t num, uint32_t cpu)
88013014Sciro.santilli@arm.com{
88113014Sciro.santilli@arm.com    DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n",
88213014Sciro.santilli@arm.com            num, cpu);
88313014Sciro.santilli@arm.com    cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
88413014Sciro.santilli@arm.com    updateIntState(intNumToWord(num));
88513014Sciro.santilli@arm.com}
88613014Sciro.santilli@arm.com
88713014Sciro.santilli@arm.comvoid
88813108Sadrien.pesle@arm.comGicV2::clearInt(uint32_t num)
88913014Sciro.santilli@arm.com{
89013108Sadrien.pesle@arm.com    if (isLevelSensitive(0, num)) {
89113108Sadrien.pesle@arm.com        uint8_t target = getCpuTarget(0, num);
89213108Sadrien.pesle@arm.com
89313108Sadrien.pesle@arm.com        DPRINTF(Interrupt,
89413108Sadrien.pesle@arm.com                "Received Clear interrupt number %d, cpuTarget %#x:\n",
89513108Sadrien.pesle@arm.com                num, target);
89613108Sadrien.pesle@arm.com
89713108Sadrien.pesle@arm.com        getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num));
89813108Sadrien.pesle@arm.com        updateIntState(intNumToWord(num));
89913108Sadrien.pesle@arm.com    } else {
90013108Sadrien.pesle@arm.com        /* Nothing to do :
90113108Sadrien.pesle@arm.com         * Edge-triggered interrupt remain pending until software
90213108Sadrien.pesle@arm.com         * writes GICD_ICPENDR or reads GICC_IAR */
90313108Sadrien.pesle@arm.com    }
90413014Sciro.santilli@arm.com}
90513014Sciro.santilli@arm.com
90613014Sciro.santilli@arm.comvoid
90713014Sciro.santilli@arm.comGicV2::clearPPInt(uint32_t num, uint32_t cpu)
90813014Sciro.santilli@arm.com{
90913014Sciro.santilli@arm.com    DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n",
91013014Sciro.santilli@arm.com            num, cpu);
91113014Sciro.santilli@arm.com    cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX));
91213014Sciro.santilli@arm.com    updateIntState(intNumToWord(num));
91313014Sciro.santilli@arm.com}
91413014Sciro.santilli@arm.com
91513014Sciro.santilli@arm.comvoid
91613112Sgiacomo.travaglini@arm.comGicV2::clearInt(ContextID ctx, uint32_t int_num)
91713112Sgiacomo.travaglini@arm.com{
91813112Sgiacomo.travaglini@arm.com    if (isFiq(ctx, int_num)) {
91913112Sgiacomo.travaglini@arm.com        platform->intrctrl->clear(ctx, ArmISA::INT_FIQ, 0);
92013112Sgiacomo.travaglini@arm.com    } else {
92113112Sgiacomo.travaglini@arm.com        platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0);
92213112Sgiacomo.travaglini@arm.com    }
92313112Sgiacomo.travaglini@arm.com}
92413112Sgiacomo.travaglini@arm.com
92513112Sgiacomo.travaglini@arm.comvoid
92613014Sciro.santilli@arm.comGicV2::postInt(uint32_t cpu, Tick when)
92713014Sciro.santilli@arm.com{
92813014Sciro.santilli@arm.com    if (!(postIntEvent[cpu]->scheduled())) {
92913014Sciro.santilli@arm.com        ++pendingDelayedInterrupts;
93013014Sciro.santilli@arm.com        eventq->schedule(postIntEvent[cpu], when);
93113014Sciro.santilli@arm.com    }
93213014Sciro.santilli@arm.com}
93313014Sciro.santilli@arm.com
93413014Sciro.santilli@arm.comvoid
93513014Sciro.santilli@arm.comGicV2::postDelayedInt(uint32_t cpu)
93613014Sciro.santilli@arm.com{
93713014Sciro.santilli@arm.com    platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0);
93813014Sciro.santilli@arm.com    --pendingDelayedInterrupts;
93913014Sciro.santilli@arm.com    assert(pendingDelayedInterrupts >= 0);
94013014Sciro.santilli@arm.com    if (pendingDelayedInterrupts == 0)
94113014Sciro.santilli@arm.com        signalDrainDone();
94213014Sciro.santilli@arm.com}
94313014Sciro.santilli@arm.com
94413111Sgiacomo.travaglini@arm.comvoid
94513111Sgiacomo.travaglini@arm.comGicV2::postFiq(uint32_t cpu, Tick when)
94613111Sgiacomo.travaglini@arm.com{
94713111Sgiacomo.travaglini@arm.com    if (!(postFiqEvent[cpu]->scheduled())) {
94813111Sgiacomo.travaglini@arm.com        ++pendingDelayedInterrupts;
94913111Sgiacomo.travaglini@arm.com        eventq->schedule(postFiqEvent[cpu], when);
95013111Sgiacomo.travaglini@arm.com    }
95113111Sgiacomo.travaglini@arm.com}
95213111Sgiacomo.travaglini@arm.com
95313111Sgiacomo.travaglini@arm.comvoid
95413111Sgiacomo.travaglini@arm.comGicV2::postDelayedFiq(uint32_t cpu)
95513111Sgiacomo.travaglini@arm.com{
95613111Sgiacomo.travaglini@arm.com    platform->intrctrl->post(cpu, ArmISA::INT_FIQ, 0);
95713111Sgiacomo.travaglini@arm.com    --pendingDelayedInterrupts;
95813111Sgiacomo.travaglini@arm.com    assert(pendingDelayedInterrupts >= 0);
95913111Sgiacomo.travaglini@arm.com    if (pendingDelayedInterrupts == 0)
96013111Sgiacomo.travaglini@arm.com        signalDrainDone();
96113111Sgiacomo.travaglini@arm.com}
96213111Sgiacomo.travaglini@arm.com
96313014Sciro.santilli@arm.comDrainState
96413014Sciro.santilli@arm.comGicV2::drain()
96513014Sciro.santilli@arm.com{
96613014Sciro.santilli@arm.com    if (pendingDelayedInterrupts == 0) {
96713014Sciro.santilli@arm.com        return DrainState::Drained;
96813014Sciro.santilli@arm.com    } else {
96913014Sciro.santilli@arm.com        return DrainState::Draining;
97013014Sciro.santilli@arm.com    }
97113014Sciro.santilli@arm.com}
97213014Sciro.santilli@arm.com
97313014Sciro.santilli@arm.com
97413014Sciro.santilli@arm.comvoid
97513014Sciro.santilli@arm.comGicV2::drainResume()
97613014Sciro.santilli@arm.com{
97713014Sciro.santilli@arm.com    // There may be pending interrupts if checkpointed from Kvm; post them.
97813014Sciro.santilli@arm.com    updateIntState(-1);
97913014Sciro.santilli@arm.com}
98013014Sciro.santilli@arm.com
98113014Sciro.santilli@arm.comvoid
98213014Sciro.santilli@arm.comGicV2::serialize(CheckpointOut &cp) const
98313014Sciro.santilli@arm.com{
98413014Sciro.santilli@arm.com    DPRINTF(Checkpoint, "Serializing Arm GIC\n");
98513014Sciro.santilli@arm.com
98613014Sciro.santilli@arm.com    SERIALIZE_SCALAR(enabled);
98713014Sciro.santilli@arm.com    SERIALIZE_SCALAR(itLines);
98813014Sciro.santilli@arm.com    SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1);
98913014Sciro.santilli@arm.com    SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1);
99013014Sciro.santilli@arm.com    SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1);
99113110Sgiacomo.travaglini@arm.com    SERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1);
99213014Sciro.santilli@arm.com    SERIALIZE_ARRAY(iccrpr, CPU_MAX);
99313014Sciro.santilli@arm.com    SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES);
99413014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES);
99513014Sciro.santilli@arm.com    SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
99613109Sgiacomo.travaglini@arm.com    SERIALIZE_ARRAY(cpuControl, CPU_MAX);
99713014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
99813014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuBpr, CPU_MAX);
99913014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
100013014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
100113014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
100213014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX);
100313014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX);
100413014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
100513014Sciro.santilli@arm.com    SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
100613014Sciro.santilli@arm.com    SERIALIZE_SCALAR(gem5ExtensionsEnabled);
100713014Sciro.santilli@arm.com
100813014Sciro.santilli@arm.com    for (uint32_t i=0; i < bankedRegs.size(); ++i) {
100913014Sciro.santilli@arm.com        if (!bankedRegs[i])
101013014Sciro.santilli@arm.com            continue;
101113014Sciro.santilli@arm.com        bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i));
101213014Sciro.santilli@arm.com    }
101313014Sciro.santilli@arm.com}
101413014Sciro.santilli@arm.com
101513014Sciro.santilli@arm.comvoid
101613014Sciro.santilli@arm.comGicV2::BankedRegs::serialize(CheckpointOut &cp) const
101713014Sciro.santilli@arm.com{
101813014Sciro.santilli@arm.com    SERIALIZE_SCALAR(intEnabled);
101913014Sciro.santilli@arm.com    SERIALIZE_SCALAR(pendingInt);
102013014Sciro.santilli@arm.com    SERIALIZE_SCALAR(activeInt);
102113110Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(intGroup);
102213014Sciro.santilli@arm.com    SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
102313014Sciro.santilli@arm.com}
102413014Sciro.santilli@arm.com
102513014Sciro.santilli@arm.comvoid
102613014Sciro.santilli@arm.comGicV2::unserialize(CheckpointIn &cp)
102713014Sciro.santilli@arm.com{
102813014Sciro.santilli@arm.com    DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
102913014Sciro.santilli@arm.com
103013014Sciro.santilli@arm.com    UNSERIALIZE_SCALAR(enabled);
103113014Sciro.santilli@arm.com    UNSERIALIZE_SCALAR(itLines);
103213014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1);
103313014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1);
103413014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1);
103513110Sgiacomo.travaglini@arm.com    UNSERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1);
103613014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
103713014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES);
103813014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES);
103913014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
104013109Sgiacomo.travaglini@arm.com    UNSERIALIZE_ARRAY(cpuControl, CPU_MAX);
104113014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
104213014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX);
104313014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
104413014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
104513014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
104613014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX);
104713014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX);
104813014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
104913014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
105013014Sciro.santilli@arm.com
105113014Sciro.santilli@arm.com    // Handle checkpoints from before we drained the GIC to prevent
105213014Sciro.santilli@arm.com    // in-flight interrupts.
105313014Sciro.santilli@arm.com    if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) {
105413014Sciro.santilli@arm.com        Tick interrupt_time[CPU_MAX];
105513014Sciro.santilli@arm.com        UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
105613014Sciro.santilli@arm.com
105713014Sciro.santilli@arm.com        for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
105813014Sciro.santilli@arm.com            if (interrupt_time[cpu])
105913014Sciro.santilli@arm.com                schedule(postIntEvent[cpu], interrupt_time[cpu]);
106013014Sciro.santilli@arm.com        }
106113014Sciro.santilli@arm.com    }
106213014Sciro.santilli@arm.com
106313014Sciro.santilli@arm.com    if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled))
106413014Sciro.santilli@arm.com        gem5ExtensionsEnabled = false;
106513014Sciro.santilli@arm.com
106613014Sciro.santilli@arm.com    for (uint32_t i=0; i < CPU_MAX; ++i) {
106713014Sciro.santilli@arm.com        ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i));
106813014Sciro.santilli@arm.com        if (cp.sectionExists(Serializable::currentSection())) {
106913014Sciro.santilli@arm.com            getBankedRegs(i).unserialize(cp);
107013014Sciro.santilli@arm.com        }
107113014Sciro.santilli@arm.com    }
107213014Sciro.santilli@arm.com}
107313014Sciro.santilli@arm.com
107413014Sciro.santilli@arm.comvoid
107513014Sciro.santilli@arm.comGicV2::BankedRegs::unserialize(CheckpointIn &cp)
107613014Sciro.santilli@arm.com{
107713014Sciro.santilli@arm.com    UNSERIALIZE_SCALAR(intEnabled);
107813014Sciro.santilli@arm.com    UNSERIALIZE_SCALAR(pendingInt);
107913014Sciro.santilli@arm.com    UNSERIALIZE_SCALAR(activeInt);
108013110Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(intGroup);
108113014Sciro.santilli@arm.com    UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
108213014Sciro.santilli@arm.com}
108313014Sciro.santilli@arm.com
108413014Sciro.santilli@arm.comGicV2 *
108513014Sciro.santilli@arm.comGicV2Params::create()
108613014Sciro.santilli@arm.com{
108713014Sciro.santilli@arm.com    return new GicV2(this);
108813014Sciro.santilli@arm.com}
1089