gic_v2.cc revision 13112
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), 6713014Sciro.santilli@arm.com distRange(RangeSize(p->dist_addr, DIST_SIZE)), 6813014Sciro.santilli@arm.com cpuRange(RangeSize(p->cpu_addr, p->cpu_size)), 6913014Sciro.santilli@arm.com addrRanges{distRange, cpuRange}, 7013014Sciro.santilli@arm.com distPioDelay(p->dist_pio_delay), 7113014Sciro.santilli@arm.com cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency), 7213014Sciro.santilli@arm.com enabled(false), haveGem5Extensions(p->gem5_extensions), 7313014Sciro.santilli@arm.com itLines(p->it_lines), 7413014Sciro.santilli@arm.com intEnabled {}, pendingInt {}, activeInt {}, 7513014Sciro.santilli@arm.com intPriority {}, cpuTarget {}, intConfig {}, 7613014Sciro.santilli@arm.com cpuSgiPending {}, cpuSgiActive {}, 7713014Sciro.santilli@arm.com cpuSgiPendingExt {}, cpuSgiActiveExt {}, 7813014Sciro.santilli@arm.com cpuPpiPending {}, cpuPpiActive {}, 7913014Sciro.santilli@arm.com pendingDelayedInterrupts(0) 8013014Sciro.santilli@arm.com{ 8113014Sciro.santilli@arm.com for (int x = 0; x < CPU_MAX; x++) { 8213014Sciro.santilli@arm.com iccrpr[x] = 0xff; 8313109Sgiacomo.travaglini@arm.com cpuControl[x] = 0; 8413014Sciro.santilli@arm.com cpuPriority[x] = 0xff; 8513014Sciro.santilli@arm.com cpuBpr[x] = GICC_BPR_MINIMUM; 8613014Sciro.santilli@arm.com // Initialize cpu highest int 8713014Sciro.santilli@arm.com cpuHighestInt[x] = SPURIOUS_INT; 8813014Sciro.santilli@arm.com postIntEvent[x] = 8913014Sciro.santilli@arm.com new EventFunctionWrapper([this, x]{ postDelayedInt(x); }, 9013014Sciro.santilli@arm.com "Post Interrupt to CPU"); 9113111Sgiacomo.travaglini@arm.com postFiqEvent[x] = 9213111Sgiacomo.travaglini@arm.com new EventFunctionWrapper([this, x]{ postDelayedFiq(x); }, 9313111Sgiacomo.travaglini@arm.com "Post FIQ to CPU"); 9413014Sciro.santilli@arm.com } 9513109Sgiacomo.travaglini@arm.com DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled(0), 9613109Sgiacomo.travaglini@arm.com cpuEnabled(1)); 9713014Sciro.santilli@arm.com 9813014Sciro.santilli@arm.com gem5ExtensionsEnabled = false; 9913014Sciro.santilli@arm.com} 10013014Sciro.santilli@arm.com 10113014Sciro.santilli@arm.comGicV2::~GicV2() 10213014Sciro.santilli@arm.com{ 10313111Sgiacomo.travaglini@arm.com for (int x = 0; x < CPU_MAX; x++) { 10413014Sciro.santilli@arm.com delete postIntEvent[x]; 10513111Sgiacomo.travaglini@arm.com delete postFiqEvent[x]; 10613111Sgiacomo.travaglini@arm.com } 10713014Sciro.santilli@arm.com} 10813014Sciro.santilli@arm.com 10913014Sciro.santilli@arm.comTick 11013014Sciro.santilli@arm.comGicV2::read(PacketPtr pkt) 11113014Sciro.santilli@arm.com{ 11213014Sciro.santilli@arm.com const Addr addr = pkt->getAddr(); 11313014Sciro.santilli@arm.com 11413014Sciro.santilli@arm.com if (distRange.contains(addr)) 11513014Sciro.santilli@arm.com return readDistributor(pkt); 11613014Sciro.santilli@arm.com else if (cpuRange.contains(addr)) 11713014Sciro.santilli@arm.com return readCpu(pkt); 11813014Sciro.santilli@arm.com else 11913014Sciro.santilli@arm.com panic("Read to unknown address %#x\n", pkt->getAddr()); 12013014Sciro.santilli@arm.com} 12113014Sciro.santilli@arm.com 12213014Sciro.santilli@arm.com 12313014Sciro.santilli@arm.comTick 12413014Sciro.santilli@arm.comGicV2::write(PacketPtr pkt) 12513014Sciro.santilli@arm.com{ 12613014Sciro.santilli@arm.com const Addr addr = pkt->getAddr(); 12713014Sciro.santilli@arm.com 12813014Sciro.santilli@arm.com if (distRange.contains(addr)) 12913014Sciro.santilli@arm.com return writeDistributor(pkt); 13013014Sciro.santilli@arm.com else if (cpuRange.contains(addr)) 13113014Sciro.santilli@arm.com return writeCpu(pkt); 13213014Sciro.santilli@arm.com else 13313014Sciro.santilli@arm.com panic("Write to unknown address %#x\n", pkt->getAddr()); 13413014Sciro.santilli@arm.com} 13513014Sciro.santilli@arm.com 13613014Sciro.santilli@arm.comTick 13713014Sciro.santilli@arm.comGicV2::readDistributor(PacketPtr pkt) 13813014Sciro.santilli@arm.com{ 13913014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - distRange.start(); 14013014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 14113014Sciro.santilli@arm.com 14213014Sciro.santilli@arm.com DPRINTF(GIC, "gic distributor read register %#x\n", daddr); 14313014Sciro.santilli@arm.com 14413014Sciro.santilli@arm.com const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize()); 14513014Sciro.santilli@arm.com 14613014Sciro.santilli@arm.com switch (pkt->getSize()) { 14713014Sciro.santilli@arm.com case 1: 14813014Sciro.santilli@arm.com pkt->set<uint8_t>(resp); 14913014Sciro.santilli@arm.com break; 15013014Sciro.santilli@arm.com case 2: 15113014Sciro.santilli@arm.com pkt->set<uint16_t>(resp); 15213014Sciro.santilli@arm.com break; 15313014Sciro.santilli@arm.com case 4: 15413014Sciro.santilli@arm.com pkt->set<uint32_t>(resp); 15513014Sciro.santilli@arm.com break; 15613014Sciro.santilli@arm.com default: 15713014Sciro.santilli@arm.com panic("Invalid size while reading Distributor regs in GIC: %d\n", 15813014Sciro.santilli@arm.com pkt->getSize()); 15913014Sciro.santilli@arm.com } 16013014Sciro.santilli@arm.com 16113014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 16213014Sciro.santilli@arm.com return distPioDelay; 16313014Sciro.santilli@arm.com} 16413014Sciro.santilli@arm.com 16513014Sciro.santilli@arm.comuint32_t 16613014Sciro.santilli@arm.comGicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz) 16713014Sciro.santilli@arm.com{ 16813014Sciro.santilli@arm.com if (GICD_IGROUPR.contains(daddr)) { 16913110Sgiacomo.travaglini@arm.com uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; 17013110Sgiacomo.travaglini@arm.com assert(ix < 32); 17113110Sgiacomo.travaglini@arm.com return getIntGroup(ctx, ix); 17213014Sciro.santilli@arm.com } 17313014Sciro.santilli@arm.com 17413014Sciro.santilli@arm.com if (GICD_ISENABLER.contains(daddr)) { 17513014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 17613014Sciro.santilli@arm.com assert(ix < 32); 17713014Sciro.santilli@arm.com return getIntEnabled(ctx, ix); 17813014Sciro.santilli@arm.com } 17913014Sciro.santilli@arm.com 18013014Sciro.santilli@arm.com if (GICD_ICENABLER.contains(daddr)) { 18113014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 18213014Sciro.santilli@arm.com assert(ix < 32); 18313014Sciro.santilli@arm.com return getIntEnabled(ctx, ix); 18413014Sciro.santilli@arm.com } 18513014Sciro.santilli@arm.com 18613014Sciro.santilli@arm.com if (GICD_ISPENDR.contains(daddr)) { 18713014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 18813014Sciro.santilli@arm.com assert(ix < 32); 18913014Sciro.santilli@arm.com return getPendingInt(ctx, ix); 19013014Sciro.santilli@arm.com } 19113014Sciro.santilli@arm.com 19213014Sciro.santilli@arm.com if (GICD_ICPENDR.contains(daddr)) { 19313014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 19413014Sciro.santilli@arm.com assert(ix < 32); 19513014Sciro.santilli@arm.com return getPendingInt(ctx, ix); 19613014Sciro.santilli@arm.com } 19713014Sciro.santilli@arm.com 19813014Sciro.santilli@arm.com if (GICD_ISACTIVER.contains(daddr)) { 19913014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 20013014Sciro.santilli@arm.com assert(ix < 32); 20113014Sciro.santilli@arm.com return getActiveInt(ctx, ix); 20213014Sciro.santilli@arm.com } 20313014Sciro.santilli@arm.com 20413014Sciro.santilli@arm.com if (GICD_ICACTIVER.contains(daddr)) { 20513014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 20613014Sciro.santilli@arm.com assert(ix < 32); 20713014Sciro.santilli@arm.com return getActiveInt(ctx, ix); 20813014Sciro.santilli@arm.com } 20913014Sciro.santilli@arm.com 21013014Sciro.santilli@arm.com if (GICD_IPRIORITYR.contains(daddr)) { 21113014Sciro.santilli@arm.com Addr int_num = daddr - GICD_IPRIORITYR.start(); 21213014Sciro.santilli@arm.com assert(int_num < INT_LINES_MAX); 21313014Sciro.santilli@arm.com DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n", 21413014Sciro.santilli@arm.com int_num); 21513014Sciro.santilli@arm.com 21613014Sciro.santilli@arm.com switch (resp_sz) { 21713014Sciro.santilli@arm.com default: // will panic() after return to caller anyway 21813014Sciro.santilli@arm.com case 1: 21913014Sciro.santilli@arm.com return getIntPriority(ctx, int_num); 22013014Sciro.santilli@arm.com case 2: 22113014Sciro.santilli@arm.com assert((int_num + 1) < INT_LINES_MAX); 22213014Sciro.santilli@arm.com return (getIntPriority(ctx, int_num) | 22313014Sciro.santilli@arm.com getIntPriority(ctx, int_num+1) << 8); 22413014Sciro.santilli@arm.com case 4: 22513014Sciro.santilli@arm.com assert((int_num + 3) < INT_LINES_MAX); 22613014Sciro.santilli@arm.com return (getIntPriority(ctx, int_num) | 22713014Sciro.santilli@arm.com getIntPriority(ctx, int_num+1) << 8 | 22813014Sciro.santilli@arm.com getIntPriority(ctx, int_num+2) << 16 | 22913014Sciro.santilli@arm.com getIntPriority(ctx, int_num+3) << 24); 23013014Sciro.santilli@arm.com } 23113014Sciro.santilli@arm.com } 23213014Sciro.santilli@arm.com 23313014Sciro.santilli@arm.com if (GICD_ITARGETSR.contains(daddr)) { 23413014Sciro.santilli@arm.com Addr int_num = daddr - GICD_ITARGETSR.start(); 23513014Sciro.santilli@arm.com DPRINTF(GIC, "Reading processor target register for int# %#x \n", 23613014Sciro.santilli@arm.com int_num); 23713014Sciro.santilli@arm.com assert(int_num < INT_LINES_MAX); 23813014Sciro.santilli@arm.com 23913014Sciro.santilli@arm.com if (resp_sz == 1) { 24013014Sciro.santilli@arm.com return getCpuTarget(ctx, int_num); 24113014Sciro.santilli@arm.com } else { 24213014Sciro.santilli@arm.com assert(resp_sz == 4); 24313014Sciro.santilli@arm.com int_num = mbits(int_num, 31, 2); 24413014Sciro.santilli@arm.com return (getCpuTarget(ctx, int_num) | 24513014Sciro.santilli@arm.com getCpuTarget(ctx, int_num+1) << 8 | 24613014Sciro.santilli@arm.com getCpuTarget(ctx, int_num+2) << 16 | 24713014Sciro.santilli@arm.com getCpuTarget(ctx, int_num+3) << 24) ; 24813014Sciro.santilli@arm.com } 24913014Sciro.santilli@arm.com } 25013014Sciro.santilli@arm.com 25113014Sciro.santilli@arm.com if (GICD_ICFGR.contains(daddr)) { 25213014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 25313014Sciro.santilli@arm.com assert(ix < 64); 25413014Sciro.santilli@arm.com /** @todo software generated interrupts and PPIs 25513014Sciro.santilli@arm.com * can't be configured in some ways */ 25613014Sciro.santilli@arm.com return intConfig[ix]; 25713014Sciro.santilli@arm.com } 25813014Sciro.santilli@arm.com 25913014Sciro.santilli@arm.com switch(daddr) { 26013014Sciro.santilli@arm.com case GICD_CTLR: 26113014Sciro.santilli@arm.com return enabled; 26213014Sciro.santilli@arm.com case GICD_TYPER: 26313014Sciro.santilli@arm.com /* The 0x100 is a made-up flag to show that gem5 extensions 26413014Sciro.santilli@arm.com * are available, 26513014Sciro.santilli@arm.com * write 0x200 to this register to enable it. */ 26613014Sciro.santilli@arm.com return (((sys->numRunningContexts() - 1) << 5) | 26713014Sciro.santilli@arm.com (itLines/INT_BITS_MAX -1) | 26813014Sciro.santilli@arm.com (haveGem5Extensions ? 0x100 : 0x0)); 26913014Sciro.santilli@arm.com case GICD_PIDR0: 27013014Sciro.santilli@arm.com //ARM defined DevID 27113014Sciro.santilli@arm.com return (GICD_400_PIDR_VALUE & 0xFF); 27213014Sciro.santilli@arm.com case GICD_PIDR1: 27313014Sciro.santilli@arm.com return ((GICD_400_PIDR_VALUE >> 8) & 0xFF); 27413014Sciro.santilli@arm.com case GICD_PIDR2: 27513014Sciro.santilli@arm.com return ((GICD_400_PIDR_VALUE >> 16) & 0xFF); 27613014Sciro.santilli@arm.com case GICD_PIDR3: 27713014Sciro.santilli@arm.com return ((GICD_400_PIDR_VALUE >> 24) & 0xFF); 27813014Sciro.santilli@arm.com case GICD_IIDR: 27913014Sciro.santilli@arm.com /* revision id is resorted to 1 and variant to 0*/ 28013014Sciro.santilli@arm.com return GICD_400_IIDR_VALUE; 28113014Sciro.santilli@arm.com default: 28213014Sciro.santilli@arm.com panic("Tried to read Gic distributor at offset %#x\n", daddr); 28313014Sciro.santilli@arm.com break; 28413014Sciro.santilli@arm.com } 28513014Sciro.santilli@arm.com} 28613014Sciro.santilli@arm.com 28713014Sciro.santilli@arm.comTick 28813014Sciro.santilli@arm.comGicV2::readCpu(PacketPtr pkt) 28913014Sciro.santilli@arm.com{ 29013014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - cpuRange.start(); 29113014Sciro.santilli@arm.com 29213014Sciro.santilli@arm.com assert(pkt->req->hasContextId()); 29313014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 29413014Sciro.santilli@arm.com assert(ctx < sys->numRunningContexts()); 29513014Sciro.santilli@arm.com 29613014Sciro.santilli@arm.com DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, 29713014Sciro.santilli@arm.com ctx); 29813014Sciro.santilli@arm.com 29913014Sciro.santilli@arm.com pkt->set<uint32_t>(readCpu(ctx, daddr)); 30013014Sciro.santilli@arm.com 30113014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 30213014Sciro.santilli@arm.com return cpuPioDelay; 30313014Sciro.santilli@arm.com} 30413014Sciro.santilli@arm.com 30513014Sciro.santilli@arm.comuint32_t 30613014Sciro.santilli@arm.comGicV2::readCpu(ContextID ctx, Addr daddr) 30713014Sciro.santilli@arm.com{ 30813014Sciro.santilli@arm.com switch(daddr) { 30913014Sciro.santilli@arm.com case GICC_IIDR: 31013014Sciro.santilli@arm.com return GICC_400_IIDR_VALUE; 31113014Sciro.santilli@arm.com case GICC_CTLR: 31213109Sgiacomo.travaglini@arm.com return cpuControl[ctx]; 31313014Sciro.santilli@arm.com case GICC_PMR: 31413014Sciro.santilli@arm.com return cpuPriority[ctx]; 31513014Sciro.santilli@arm.com case GICC_BPR: 31613014Sciro.santilli@arm.com return cpuBpr[ctx]; 31713014Sciro.santilli@arm.com case GICC_IAR: 31813109Sgiacomo.travaglini@arm.com if (enabled && cpuEnabled(ctx)) { 31913014Sciro.santilli@arm.com int active_int = cpuHighestInt[ctx]; 32013014Sciro.santilli@arm.com IAR iar = 0; 32113014Sciro.santilli@arm.com iar.ack_id = active_int; 32213014Sciro.santilli@arm.com iar.cpu_id = 0; 32313014Sciro.santilli@arm.com if (active_int < SGI_MAX) { 32413014Sciro.santilli@arm.com // this is a software interrupt from another CPU 32513014Sciro.santilli@arm.com if (!gem5ExtensionsEnabled) { 32613014Sciro.santilli@arm.com panic_if(!cpuSgiPending[active_int], 32713014Sciro.santilli@arm.com "Interrupt %d active but no CPU generated it?\n", 32813014Sciro.santilli@arm.com active_int); 32913014Sciro.santilli@arm.com for (int x = 0; x < sys->numRunningContexts(); x++) { 33013014Sciro.santilli@arm.com // See which CPU generated the interrupt 33113014Sciro.santilli@arm.com uint8_t cpugen = 33213014Sciro.santilli@arm.com bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x); 33313014Sciro.santilli@arm.com if (cpugen & (1 << ctx)) { 33413014Sciro.santilli@arm.com iar.cpu_id = x; 33513014Sciro.santilli@arm.com break; 33613014Sciro.santilli@arm.com } 33713014Sciro.santilli@arm.com } 33813014Sciro.santilli@arm.com uint64_t sgi_num = ULL(1) << (ctx + 8 * iar.cpu_id); 33913014Sciro.santilli@arm.com cpuSgiActive[iar.ack_id] |= sgi_num; 34013014Sciro.santilli@arm.com cpuSgiPending[iar.ack_id] &= ~sgi_num; 34113014Sciro.santilli@arm.com } else { 34213014Sciro.santilli@arm.com uint64_t sgi_num = ULL(1) << iar.ack_id; 34313014Sciro.santilli@arm.com cpuSgiActiveExt[ctx] |= sgi_num; 34413014Sciro.santilli@arm.com cpuSgiPendingExt[ctx] &= ~sgi_num; 34513014Sciro.santilli@arm.com } 34613014Sciro.santilli@arm.com } else if (active_int < (SGI_MAX + PPI_MAX) ) { 34713014Sciro.santilli@arm.com uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX); 34813014Sciro.santilli@arm.com cpuPpiActive[ctx] |= int_num; 34913014Sciro.santilli@arm.com updateRunPri(); 35013014Sciro.santilli@arm.com cpuPpiPending[ctx] &= ~int_num; 35113014Sciro.santilli@arm.com 35213014Sciro.santilli@arm.com } else { 35313014Sciro.santilli@arm.com uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]); 35413014Sciro.santilli@arm.com getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num; 35513014Sciro.santilli@arm.com updateRunPri(); 35613108Sadrien.pesle@arm.com if (!isLevelSensitive(ctx, active_int)) { 35713108Sadrien.pesle@arm.com getPendingInt(ctx, intNumToWord(cpuHighestInt[ctx])) 35813108Sadrien.pesle@arm.com &= ~int_num; 35913108Sadrien.pesle@arm.com } 36013014Sciro.santilli@arm.com } 36113014Sciro.santilli@arm.com 36213014Sciro.santilli@arm.com DPRINTF(Interrupt, 36313014Sciro.santilli@arm.com "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n", 36413014Sciro.santilli@arm.com ctx, iar.ack_id, iar.cpu_id, iar); 36513014Sciro.santilli@arm.com cpuHighestInt[ctx] = SPURIOUS_INT; 36613014Sciro.santilli@arm.com updateIntState(-1); 36713112Sgiacomo.travaglini@arm.com clearInt(ctx, active_int); 36813014Sciro.santilli@arm.com return iar; 36913014Sciro.santilli@arm.com } else { 37013014Sciro.santilli@arm.com return SPURIOUS_INT; 37113014Sciro.santilli@arm.com } 37213014Sciro.santilli@arm.com 37313014Sciro.santilli@arm.com break; 37413014Sciro.santilli@arm.com case GICC_RPR: 37513014Sciro.santilli@arm.com return iccrpr[0]; 37613014Sciro.santilli@arm.com case GICC_HPPIR: 37713014Sciro.santilli@arm.com panic("Need to implement HPIR"); 37813014Sciro.santilli@arm.com break; 37913014Sciro.santilli@arm.com default: 38013014Sciro.santilli@arm.com panic("Tried to read Gic cpu at offset %#x\n", daddr); 38113014Sciro.santilli@arm.com break; 38213014Sciro.santilli@arm.com } 38313014Sciro.santilli@arm.com} 38413014Sciro.santilli@arm.com 38513014Sciro.santilli@arm.comTick 38613014Sciro.santilli@arm.comGicV2::writeDistributor(PacketPtr pkt) 38713014Sciro.santilli@arm.com{ 38813014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - distRange.start(); 38913014Sciro.santilli@arm.com 39013014Sciro.santilli@arm.com assert(pkt->req->hasContextId()); 39113014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 39213014Sciro.santilli@arm.com const size_t data_sz = pkt->getSize(); 39313014Sciro.santilli@arm.com 39413014Sciro.santilli@arm.com uint32_t pkt_data M5_VAR_USED; 39513014Sciro.santilli@arm.com switch (data_sz) 39613014Sciro.santilli@arm.com { 39713014Sciro.santilli@arm.com case 1: 39813014Sciro.santilli@arm.com pkt_data = pkt->get<uint8_t>(); 39913014Sciro.santilli@arm.com break; 40013014Sciro.santilli@arm.com case 2: 40113014Sciro.santilli@arm.com pkt_data = pkt->get<uint16_t>(); 40213014Sciro.santilli@arm.com break; 40313014Sciro.santilli@arm.com case 4: 40413014Sciro.santilli@arm.com pkt_data = pkt->get<uint32_t>(); 40513014Sciro.santilli@arm.com break; 40613014Sciro.santilli@arm.com default: 40713014Sciro.santilli@arm.com panic("Invalid size when writing to priority regs in Gic: %d\n", 40813014Sciro.santilli@arm.com data_sz); 40913014Sciro.santilli@arm.com } 41013014Sciro.santilli@arm.com 41113014Sciro.santilli@arm.com DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n", 41213014Sciro.santilli@arm.com daddr, data_sz, pkt_data); 41313014Sciro.santilli@arm.com 41413014Sciro.santilli@arm.com writeDistributor(ctx, daddr, pkt_data, data_sz); 41513014Sciro.santilli@arm.com 41613014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 41713014Sciro.santilli@arm.com return distPioDelay; 41813014Sciro.santilli@arm.com} 41913014Sciro.santilli@arm.com 42013014Sciro.santilli@arm.comvoid 42113014Sciro.santilli@arm.comGicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data, 42213014Sciro.santilli@arm.com size_t data_sz) 42313014Sciro.santilli@arm.com{ 42413014Sciro.santilli@arm.com if (GICD_IGROUPR.contains(daddr)) { 42513110Sgiacomo.travaglini@arm.com uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; 42613110Sgiacomo.travaglini@arm.com assert(ix < 32); 42713110Sgiacomo.travaglini@arm.com getIntGroup(ctx, ix) |= data; 42813110Sgiacomo.travaglini@arm.com return; 42913014Sciro.santilli@arm.com } 43013014Sciro.santilli@arm.com 43113014Sciro.santilli@arm.com if (GICD_ISENABLER.contains(daddr)) { 43213014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 43313014Sciro.santilli@arm.com assert(ix < 32); 43413014Sciro.santilli@arm.com getIntEnabled(ctx, ix) |= data; 43513014Sciro.santilli@arm.com return; 43613014Sciro.santilli@arm.com } 43713014Sciro.santilli@arm.com 43813014Sciro.santilli@arm.com if (GICD_ICENABLER.contains(daddr)) { 43913014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 44013014Sciro.santilli@arm.com assert(ix < 32); 44113014Sciro.santilli@arm.com getIntEnabled(ctx, ix) &= ~data; 44213014Sciro.santilli@arm.com return; 44313014Sciro.santilli@arm.com } 44413014Sciro.santilli@arm.com 44513014Sciro.santilli@arm.com if (GICD_ISPENDR.contains(daddr)) { 44613014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 44713014Sciro.santilli@arm.com auto mask = data; 44813014Sciro.santilli@arm.com if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 44913014Sciro.santilli@arm.com getPendingInt(ctx, ix) |= mask; 45013014Sciro.santilli@arm.com updateIntState(ix); 45113014Sciro.santilli@arm.com return; 45213014Sciro.santilli@arm.com } 45313014Sciro.santilli@arm.com 45413014Sciro.santilli@arm.com if (GICD_ICPENDR.contains(daddr)) { 45513014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 45613014Sciro.santilli@arm.com auto mask = data; 45713014Sciro.santilli@arm.com if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 45813014Sciro.santilli@arm.com getPendingInt(ctx, ix) &= ~mask; 45913014Sciro.santilli@arm.com updateIntState(ix); 46013014Sciro.santilli@arm.com return; 46113014Sciro.santilli@arm.com } 46213014Sciro.santilli@arm.com 46313014Sciro.santilli@arm.com if (GICD_ISACTIVER.contains(daddr)) { 46413014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 46513014Sciro.santilli@arm.com getActiveInt(ctx, ix) |= data; 46613014Sciro.santilli@arm.com return; 46713014Sciro.santilli@arm.com } 46813014Sciro.santilli@arm.com 46913014Sciro.santilli@arm.com if (GICD_ICACTIVER.contains(daddr)) { 47013014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 47113014Sciro.santilli@arm.com getActiveInt(ctx, ix) &= ~data; 47213014Sciro.santilli@arm.com return; 47313014Sciro.santilli@arm.com } 47413014Sciro.santilli@arm.com 47513014Sciro.santilli@arm.com if (GICD_IPRIORITYR.contains(daddr)) { 47613014Sciro.santilli@arm.com Addr int_num = daddr - GICD_IPRIORITYR.start(); 47713014Sciro.santilli@arm.com switch(data_sz) { 47813014Sciro.santilli@arm.com case 1: 47913014Sciro.santilli@arm.com getIntPriority(ctx, int_num) = data; 48013014Sciro.santilli@arm.com break; 48113014Sciro.santilli@arm.com case 2: { 48213014Sciro.santilli@arm.com getIntPriority(ctx, int_num) = bits(data, 7, 0); 48313014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 48413014Sciro.santilli@arm.com break; 48513014Sciro.santilli@arm.com } 48613014Sciro.santilli@arm.com case 4: { 48713014Sciro.santilli@arm.com getIntPriority(ctx, int_num) = bits(data, 7, 0); 48813014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 48913014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 2) = bits(data, 23, 16); 49013014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 3) = bits(data, 31, 24); 49113014Sciro.santilli@arm.com break; 49213014Sciro.santilli@arm.com } 49313014Sciro.santilli@arm.com default: 49413014Sciro.santilli@arm.com panic("Invalid size when writing to priority regs in Gic: %d\n", 49513014Sciro.santilli@arm.com data_sz); 49613014Sciro.santilli@arm.com } 49713014Sciro.santilli@arm.com 49813014Sciro.santilli@arm.com updateIntState(-1); 49913014Sciro.santilli@arm.com updateRunPri(); 50013014Sciro.santilli@arm.com return; 50113014Sciro.santilli@arm.com } 50213014Sciro.santilli@arm.com 50313014Sciro.santilli@arm.com if (GICD_ITARGETSR.contains(daddr)) { 50413014Sciro.santilli@arm.com Addr int_num = daddr - GICD_ITARGETSR.start(); 50513014Sciro.santilli@arm.com // Interrupts 0-31 are read only 50613014Sciro.santilli@arm.com unsigned offset = SGI_MAX + PPI_MAX; 50713014Sciro.santilli@arm.com if (int_num >= offset) { 50813014Sciro.santilli@arm.com unsigned ix = int_num - offset; // index into cpuTarget array 50913014Sciro.santilli@arm.com if (data_sz == 1) { 51013014Sciro.santilli@arm.com cpuTarget[ix] = data & 0xff; 51113014Sciro.santilli@arm.com } else { 51213014Sciro.santilli@arm.com assert (data_sz == 4); 51313014Sciro.santilli@arm.com cpuTarget[ix] = bits(data, 7, 0); 51413014Sciro.santilli@arm.com cpuTarget[ix+1] = bits(data, 15, 8); 51513014Sciro.santilli@arm.com cpuTarget[ix+2] = bits(data, 23, 16); 51613014Sciro.santilli@arm.com cpuTarget[ix+3] = bits(data, 31, 24); 51713014Sciro.santilli@arm.com } 51813014Sciro.santilli@arm.com updateIntState(int_num >> 2); 51913014Sciro.santilli@arm.com } 52013014Sciro.santilli@arm.com return; 52113014Sciro.santilli@arm.com } 52213014Sciro.santilli@arm.com 52313014Sciro.santilli@arm.com if (GICD_ICFGR.contains(daddr)) { 52413014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 52513014Sciro.santilli@arm.com assert(ix < INT_BITS_MAX*2); 52613014Sciro.santilli@arm.com intConfig[ix] = data; 52713014Sciro.santilli@arm.com if (data & NN_CONFIG_MASK) 52813014Sciro.santilli@arm.com warn("GIC N:N mode selected and not supported at this time\n"); 52913014Sciro.santilli@arm.com return; 53013014Sciro.santilli@arm.com } 53113014Sciro.santilli@arm.com 53213014Sciro.santilli@arm.com switch(daddr) { 53313014Sciro.santilli@arm.com case GICD_CTLR: 53413014Sciro.santilli@arm.com enabled = data; 53513014Sciro.santilli@arm.com DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled); 53613014Sciro.santilli@arm.com break; 53713014Sciro.santilli@arm.com case GICD_TYPER: 53813014Sciro.santilli@arm.com /* 0x200 is a made-up flag to enable gem5 extension functionality. 53913014Sciro.santilli@arm.com * This reg is not normally written. 54013014Sciro.santilli@arm.com */ 54113014Sciro.santilli@arm.com gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions; 54213014Sciro.santilli@arm.com DPRINTF(GIC, "gem5 extensions %s\n", 54313014Sciro.santilli@arm.com gem5ExtensionsEnabled ? "enabled" : "disabled"); 54413014Sciro.santilli@arm.com break; 54513014Sciro.santilli@arm.com case GICD_SGIR: 54613014Sciro.santilli@arm.com softInt(ctx, data); 54713014Sciro.santilli@arm.com break; 54813014Sciro.santilli@arm.com default: 54913014Sciro.santilli@arm.com panic("Tried to write Gic distributor at offset %#x\n", daddr); 55013014Sciro.santilli@arm.com break; 55113014Sciro.santilli@arm.com } 55213014Sciro.santilli@arm.com} 55313014Sciro.santilli@arm.com 55413014Sciro.santilli@arm.comTick 55513014Sciro.santilli@arm.comGicV2::writeCpu(PacketPtr pkt) 55613014Sciro.santilli@arm.com{ 55713014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - cpuRange.start(); 55813014Sciro.santilli@arm.com 55913014Sciro.santilli@arm.com assert(pkt->req->hasContextId()); 56013014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 56113014Sciro.santilli@arm.com const uint32_t data = pkt->get<uint32_t>(); 56213014Sciro.santilli@arm.com 56313014Sciro.santilli@arm.com DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n", 56413014Sciro.santilli@arm.com ctx, daddr, data); 56513014Sciro.santilli@arm.com 56613014Sciro.santilli@arm.com writeCpu(ctx, daddr, data); 56713014Sciro.santilli@arm.com 56813014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 56913014Sciro.santilli@arm.com return cpuPioDelay; 57013014Sciro.santilli@arm.com} 57113014Sciro.santilli@arm.com 57213014Sciro.santilli@arm.comvoid 57313014Sciro.santilli@arm.comGicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data) 57413014Sciro.santilli@arm.com{ 57513014Sciro.santilli@arm.com switch(daddr) { 57613014Sciro.santilli@arm.com case GICC_CTLR: 57713109Sgiacomo.travaglini@arm.com cpuControl[ctx] = data; 57813014Sciro.santilli@arm.com break; 57913014Sciro.santilli@arm.com case GICC_PMR: 58013014Sciro.santilli@arm.com cpuPriority[ctx] = data; 58113014Sciro.santilli@arm.com break; 58213014Sciro.santilli@arm.com case GICC_BPR: { 58313014Sciro.santilli@arm.com auto bpr = data & 0x7; 58413014Sciro.santilli@arm.com if (bpr < GICC_BPR_MINIMUM) 58513014Sciro.santilli@arm.com bpr = GICC_BPR_MINIMUM; 58613014Sciro.santilli@arm.com cpuBpr[ctx] = bpr; 58713014Sciro.santilli@arm.com break; 58813014Sciro.santilli@arm.com } 58913014Sciro.santilli@arm.com case GICC_EOIR: { 59013014Sciro.santilli@arm.com const IAR iar = data; 59113014Sciro.santilli@arm.com if (iar.ack_id < SGI_MAX) { 59213014Sciro.santilli@arm.com // Clear out the bit that corresponds to the cleared int 59313014Sciro.santilli@arm.com uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id); 59413014Sciro.santilli@arm.com if (!(cpuSgiActive[iar.ack_id] & clr_int) && 59513014Sciro.santilli@arm.com !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id))) 59613014Sciro.santilli@arm.com panic("Done handling a SGI that isn't active?\n"); 59713014Sciro.santilli@arm.com if (gem5ExtensionsEnabled) 59813014Sciro.santilli@arm.com cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id); 59913014Sciro.santilli@arm.com else 60013014Sciro.santilli@arm.com cpuSgiActive[iar.ack_id] &= ~clr_int; 60113014Sciro.santilli@arm.com } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) { 60213014Sciro.santilli@arm.com uint32_t int_num = 1 << (iar.ack_id - SGI_MAX); 60313014Sciro.santilli@arm.com if (!(cpuPpiActive[ctx] & int_num)) 60413014Sciro.santilli@arm.com panic("CPU %d Done handling a PPI interrupt " 60513014Sciro.santilli@arm.com "that isn't active?\n", ctx); 60613014Sciro.santilli@arm.com cpuPpiActive[ctx] &= ~int_num; 60713014Sciro.santilli@arm.com } else { 60813014Sciro.santilli@arm.com uint32_t int_num = 1 << intNumToBit(iar.ack_id); 60913014Sciro.santilli@arm.com if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num)) 61013014Sciro.santilli@arm.com warn("Done handling interrupt that isn't active: %d\n", 61113014Sciro.santilli@arm.com intNumToBit(iar.ack_id)); 61213014Sciro.santilli@arm.com getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num; 61313014Sciro.santilli@arm.com } 61413014Sciro.santilli@arm.com updateRunPri(); 61513014Sciro.santilli@arm.com DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n", 61613014Sciro.santilli@arm.com ctx, iar.ack_id, iar.cpu_id); 61713014Sciro.santilli@arm.com break; 61813014Sciro.santilli@arm.com } 61913014Sciro.santilli@arm.com case GICC_APR0: 62013014Sciro.santilli@arm.com case GICC_APR1: 62113014Sciro.santilli@arm.com case GICC_APR2: 62213014Sciro.santilli@arm.com case GICC_APR3: 62313014Sciro.santilli@arm.com warn("GIC APRn write ignored because not implemented: %#x\n", daddr); 62413014Sciro.santilli@arm.com break; 62513014Sciro.santilli@arm.com default: 62613014Sciro.santilli@arm.com panic("Tried to write Gic cpu at offset %#x\n", daddr); 62713014Sciro.santilli@arm.com break; 62813014Sciro.santilli@arm.com } 62913109Sgiacomo.travaglini@arm.com if (cpuEnabled(ctx)) updateIntState(-1); 63013014Sciro.santilli@arm.com} 63113014Sciro.santilli@arm.com 63213014Sciro.santilli@arm.comGicV2::BankedRegs& 63313014Sciro.santilli@arm.comGicV2::getBankedRegs(ContextID ctx) { 63413014Sciro.santilli@arm.com if (bankedRegs.size() <= ctx) 63513014Sciro.santilli@arm.com bankedRegs.resize(ctx + 1); 63613014Sciro.santilli@arm.com 63713014Sciro.santilli@arm.com if (!bankedRegs[ctx]) 63813014Sciro.santilli@arm.com bankedRegs[ctx] = new BankedRegs; 63913014Sciro.santilli@arm.com return *bankedRegs[ctx]; 64013014Sciro.santilli@arm.com} 64113014Sciro.santilli@arm.com 64213014Sciro.santilli@arm.comvoid 64313014Sciro.santilli@arm.comGicV2::softInt(ContextID ctx, SWI swi) 64413014Sciro.santilli@arm.com{ 64513014Sciro.santilli@arm.com if (gem5ExtensionsEnabled) { 64613014Sciro.santilli@arm.com switch (swi.list_type) { 64713014Sciro.santilli@arm.com case 0: { 64813014Sciro.santilli@arm.com // interrupt cpus specified 64913014Sciro.santilli@arm.com int dest = swi.cpu_list; 65013014Sciro.santilli@arm.com DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 65113014Sciro.santilli@arm.com ctx, dest); 65213109Sgiacomo.travaglini@arm.com if (cpuEnabled(dest)) { 65313014Sciro.santilli@arm.com cpuSgiPendingExt[dest] |= (1 << swi.sgi_id); 65413014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", dest, 65513014Sciro.santilli@arm.com cpuSgiPendingExt[dest]); 65613014Sciro.santilli@arm.com } 65713014Sciro.santilli@arm.com } break; 65813014Sciro.santilli@arm.com case 1: { 65913014Sciro.santilli@arm.com // interrupt all 66013014Sciro.santilli@arm.com for (int i = 0; i < sys->numContexts(); i++) { 66113014Sciro.santilli@arm.com DPRINTF(IPI, "Processing CPU %d\n", i); 66213109Sgiacomo.travaglini@arm.com if (!cpuEnabled(i)) 66313014Sciro.santilli@arm.com continue; 66413014Sciro.santilli@arm.com cpuSgiPendingExt[i] |= 1 << swi.sgi_id; 66513014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 66613014Sciro.santilli@arm.com cpuSgiPendingExt[i]); 66713014Sciro.santilli@arm.com } 66813014Sciro.santilli@arm.com } break; 66913014Sciro.santilli@arm.com case 2: { 67013014Sciro.santilli@arm.com // Interrupt requesting cpu only 67113014Sciro.santilli@arm.com DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 67213014Sciro.santilli@arm.com ctx, ctx); 67313109Sgiacomo.travaglini@arm.com if (cpuEnabled(ctx)) { 67413014Sciro.santilli@arm.com cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id); 67513014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", ctx, 67613014Sciro.santilli@arm.com cpuSgiPendingExt[ctx]); 67713014Sciro.santilli@arm.com } 67813014Sciro.santilli@arm.com } break; 67913014Sciro.santilli@arm.com } 68013014Sciro.santilli@arm.com } else { 68113014Sciro.santilli@arm.com switch (swi.list_type) { 68213014Sciro.santilli@arm.com case 1: 68313014Sciro.santilli@arm.com // interrupt all 68413014Sciro.santilli@arm.com uint8_t cpu_list; 68513014Sciro.santilli@arm.com cpu_list = 0; 68613014Sciro.santilli@arm.com for (int x = 0; x < sys->numContexts(); x++) 68713109Sgiacomo.travaglini@arm.com cpu_list |= cpuEnabled(x) ? 1 << x : 0; 68813014Sciro.santilli@arm.com swi.cpu_list = cpu_list; 68913014Sciro.santilli@arm.com break; 69013014Sciro.santilli@arm.com case 2: 69113014Sciro.santilli@arm.com // interrupt requesting cpu only 69213014Sciro.santilli@arm.com swi.cpu_list = 1 << ctx; 69313014Sciro.santilli@arm.com break; 69413014Sciro.santilli@arm.com // else interrupt cpus specified 69513014Sciro.santilli@arm.com } 69613014Sciro.santilli@arm.com 69713014Sciro.santilli@arm.com DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx, 69813014Sciro.santilli@arm.com swi.cpu_list); 69913014Sciro.santilli@arm.com for (int i = 0; i < sys->numContexts(); i++) { 70013014Sciro.santilli@arm.com DPRINTF(IPI, "Processing CPU %d\n", i); 70113109Sgiacomo.travaglini@arm.com if (!cpuEnabled(i)) 70213014Sciro.santilli@arm.com continue; 70313014Sciro.santilli@arm.com if (swi.cpu_list & (1 << i)) 70413014Sciro.santilli@arm.com cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx); 70513014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 70613014Sciro.santilli@arm.com cpuSgiPending[swi.sgi_id]); 70713014Sciro.santilli@arm.com } 70813014Sciro.santilli@arm.com } 70913014Sciro.santilli@arm.com updateIntState(-1); 71013014Sciro.santilli@arm.com} 71113014Sciro.santilli@arm.com 71213014Sciro.santilli@arm.comuint64_t 71313014Sciro.santilli@arm.comGicV2::genSwiMask(int cpu) 71413014Sciro.santilli@arm.com{ 71513014Sciro.santilli@arm.com if (cpu > sys->numContexts()) 71613014Sciro.santilli@arm.com panic("Invalid CPU ID\n"); 71713014Sciro.santilli@arm.com return ULL(0x0101010101010101) << cpu; 71813014Sciro.santilli@arm.com} 71913014Sciro.santilli@arm.com 72013014Sciro.santilli@arm.comuint8_t 72113014Sciro.santilli@arm.comGicV2::getCpuPriority(unsigned cpu) 72213014Sciro.santilli@arm.com{ 72313014Sciro.santilli@arm.com // see Table 3-2 in IHI0048B.b (GICv2) 72413014Sciro.santilli@arm.com // mask some low-order priority bits per BPR value 72513014Sciro.santilli@arm.com // NB: the GIC prioritization scheme is upside down: 72613014Sciro.santilli@arm.com // lower values are higher priority; masking off bits 72713014Sciro.santilli@arm.com // actually creates a higher priority, not lower. 72813014Sciro.santilli@arm.com return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu])); 72913014Sciro.santilli@arm.com} 73013014Sciro.santilli@arm.com 73113014Sciro.santilli@arm.comvoid 73213014Sciro.santilli@arm.comGicV2::updateIntState(int hint) 73313014Sciro.santilli@arm.com{ 73413014Sciro.santilli@arm.com for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 73513109Sgiacomo.travaglini@arm.com if (!cpuEnabled(cpu)) 73613014Sciro.santilli@arm.com continue; 73713014Sciro.santilli@arm.com 73813014Sciro.santilli@arm.com /*@todo use hint to do less work. */ 73913014Sciro.santilli@arm.com int highest_int = SPURIOUS_INT; 74013014Sciro.santilli@arm.com // Priorities below that set in GICC_PMR can be ignored 74113014Sciro.santilli@arm.com uint8_t highest_pri = getCpuPriority(cpu); 74213014Sciro.santilli@arm.com 74313014Sciro.santilli@arm.com // Check SGIs 74413014Sciro.santilli@arm.com for (int swi = 0; swi < SGI_MAX; swi++) { 74513014Sciro.santilli@arm.com if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu]) 74613014Sciro.santilli@arm.com continue; 74713014Sciro.santilli@arm.com if ((cpuSgiPending[swi] & genSwiMask(cpu)) || 74813014Sciro.santilli@arm.com (cpuSgiPendingExt[cpu] & (1 << swi))) 74913014Sciro.santilli@arm.com if (highest_pri > getIntPriority(cpu, swi)) { 75013014Sciro.santilli@arm.com highest_pri = getIntPriority(cpu, swi); 75113014Sciro.santilli@arm.com highest_int = swi; 75213014Sciro.santilli@arm.com } 75313014Sciro.santilli@arm.com } 75413014Sciro.santilli@arm.com 75513014Sciro.santilli@arm.com // Check PPIs 75613014Sciro.santilli@arm.com if (cpuPpiPending[cpu]) { 75713105Sgiacomo.travaglini@arm.com for (int ppi_idx = 0, int_num = SGI_MAX; 75813105Sgiacomo.travaglini@arm.com int_num < PPI_MAX + SGI_MAX; 75913105Sgiacomo.travaglini@arm.com ppi_idx++, int_num++) { 76013105Sgiacomo.travaglini@arm.com 76113105Sgiacomo.travaglini@arm.com const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx); 76213105Sgiacomo.travaglini@arm.com const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num); 76313105Sgiacomo.travaglini@arm.com const bool higher_priority = 76413105Sgiacomo.travaglini@arm.com highest_pri > getIntPriority(cpu, int_num); 76513105Sgiacomo.travaglini@arm.com 76613105Sgiacomo.travaglini@arm.com if (ppi_pending && ppi_enabled && higher_priority) { 76713105Sgiacomo.travaglini@arm.com highest_pri = getIntPriority(cpu, int_num); 76813105Sgiacomo.travaglini@arm.com highest_int = int_num; 76913014Sciro.santilli@arm.com } 77013014Sciro.santilli@arm.com } 77113014Sciro.santilli@arm.com } 77213014Sciro.santilli@arm.com 77313014Sciro.santilli@arm.com bool mp_sys = sys->numRunningContexts() > 1; 77413014Sciro.santilli@arm.com // Check other ints 77513014Sciro.santilli@arm.com for (int x = 0; x < (itLines/INT_BITS_MAX); x++) { 77613014Sciro.santilli@arm.com if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) { 77713014Sciro.santilli@arm.com for (int y = 0; y < INT_BITS_MAX; y++) { 77813014Sciro.santilli@arm.com uint32_t int_nm = x * INT_BITS_MAX + y; 77913014Sciro.santilli@arm.com DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm); 78013014Sciro.santilli@arm.com /* Set current pending int as highest int for current cpu 78113014Sciro.santilli@arm.com if the interrupt's priority higher than current priority 78213014Sciro.santilli@arm.com and if current cpu is the target (for mp configs only) 78313014Sciro.santilli@arm.com */ 78413014Sciro.santilli@arm.com if ((bits(getIntEnabled(cpu, x), y) 78513014Sciro.santilli@arm.com &bits(getPendingInt(cpu, x), y)) && 78613014Sciro.santilli@arm.com (getIntPriority(cpu, int_nm) < highest_pri)) 78713014Sciro.santilli@arm.com if ((!mp_sys) || 78813014Sciro.santilli@arm.com (gem5ExtensionsEnabled 78913014Sciro.santilli@arm.com ? (getCpuTarget(cpu, int_nm) == cpu) 79013014Sciro.santilli@arm.com : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) { 79113014Sciro.santilli@arm.com highest_pri = getIntPriority(cpu, int_nm); 79213014Sciro.santilli@arm.com highest_int = int_nm; 79313014Sciro.santilli@arm.com } 79413014Sciro.santilli@arm.com } 79513014Sciro.santilli@arm.com } 79613014Sciro.santilli@arm.com } 79713014Sciro.santilli@arm.com 79813108Sadrien.pesle@arm.com uint32_t prev_highest = cpuHighestInt[cpu]; 79913014Sciro.santilli@arm.com cpuHighestInt[cpu] = highest_int; 80013014Sciro.santilli@arm.com 80113108Sadrien.pesle@arm.com if (highest_int == SPURIOUS_INT) { 80213108Sadrien.pesle@arm.com if (isLevelSensitive(cpu, prev_highest)) { 80313108Sadrien.pesle@arm.com 80413108Sadrien.pesle@arm.com DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu); 80513112Sgiacomo.travaglini@arm.com clearInt(cpu, prev_highest); 80613108Sadrien.pesle@arm.com } 80713014Sciro.santilli@arm.com continue; 80813108Sadrien.pesle@arm.com } 80913014Sciro.santilli@arm.com 81013014Sciro.santilli@arm.com /* @todo make this work for more than one cpu, need to handle 1:N, N:N 81113014Sciro.santilli@arm.com * models */ 81213109Sgiacomo.travaglini@arm.com if (enabled && cpuEnabled(cpu) && 81313014Sciro.santilli@arm.com (highest_pri < getCpuPriority(cpu)) && 81413014Sciro.santilli@arm.com !(getActiveInt(cpu, intNumToWord(highest_int)) 81513014Sciro.santilli@arm.com & (1 << intNumToBit(highest_int)))) { 81613014Sciro.santilli@arm.com 81713014Sciro.santilli@arm.com DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int, 81813014Sciro.santilli@arm.com cpu); 81913112Sgiacomo.travaglini@arm.com 82013112Sgiacomo.travaglini@arm.com if (isFiq(cpu, highest_int)) { 82113112Sgiacomo.travaglini@arm.com postFiq(cpu, curTick() + intLatency); 82213112Sgiacomo.travaglini@arm.com } else { 82313112Sgiacomo.travaglini@arm.com postInt(cpu, curTick() + intLatency); 82413112Sgiacomo.travaglini@arm.com } 82513014Sciro.santilli@arm.com } 82613014Sciro.santilli@arm.com } 82713014Sciro.santilli@arm.com} 82813014Sciro.santilli@arm.com 82913014Sciro.santilli@arm.comvoid 83013014Sciro.santilli@arm.comGicV2::updateRunPri() 83113014Sciro.santilli@arm.com{ 83213014Sciro.santilli@arm.com for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 83313109Sgiacomo.travaglini@arm.com if (!cpuEnabled(cpu)) 83413014Sciro.santilli@arm.com continue; 83513014Sciro.santilli@arm.com uint8_t maxPriority = 0xff; 83613014Sciro.santilli@arm.com for (int i = 0; i < itLines; i++) { 83713014Sciro.santilli@arm.com if (i < SGI_MAX) { 83813014Sciro.santilli@arm.com if (((cpuSgiActive[i] & genSwiMask(cpu)) || 83913014Sciro.santilli@arm.com (cpuSgiActiveExt[cpu] & (1 << i))) && 84013014Sciro.santilli@arm.com (getIntPriority(cpu, i) < maxPriority)) 84113014Sciro.santilli@arm.com maxPriority = getIntPriority(cpu, i); 84213014Sciro.santilli@arm.com } else if (i < (SGI_MAX + PPI_MAX)) { 84313014Sciro.santilli@arm.com if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) && 84413014Sciro.santilli@arm.com (getIntPriority(cpu, i) < maxPriority)) 84513014Sciro.santilli@arm.com maxPriority = getIntPriority(cpu, i); 84613014Sciro.santilli@arm.com 84713014Sciro.santilli@arm.com } else { 84813014Sciro.santilli@arm.com if (getActiveInt(cpu, intNumToWord(i)) 84913014Sciro.santilli@arm.com & (1 << intNumToBit(i))) 85013014Sciro.santilli@arm.com if (getIntPriority(cpu, i) < maxPriority) 85113014Sciro.santilli@arm.com maxPriority = getIntPriority(cpu, i); 85213014Sciro.santilli@arm.com } 85313014Sciro.santilli@arm.com } 85413014Sciro.santilli@arm.com iccrpr[cpu] = maxPriority; 85513014Sciro.santilli@arm.com } 85613014Sciro.santilli@arm.com} 85713014Sciro.santilli@arm.com 85813014Sciro.santilli@arm.comvoid 85913014Sciro.santilli@arm.comGicV2::sendInt(uint32_t num) 86013014Sciro.santilli@arm.com{ 86113014Sciro.santilli@arm.com uint8_t target = getCpuTarget(0, num); 86213014Sciro.santilli@arm.com DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n", 86313014Sciro.santilli@arm.com num, target); 86413014Sciro.santilli@arm.com if ((target & (target - 1)) && !gem5ExtensionsEnabled) 86513014Sciro.santilli@arm.com panic("Multiple targets for peripheral interrupts is not supported\n"); 86613014Sciro.santilli@arm.com panic_if(num < SGI_MAX + PPI_MAX, 86713014Sciro.santilli@arm.com "sentInt() must only be used for interrupts 32 and higher"); 86813014Sciro.santilli@arm.com getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num); 86913014Sciro.santilli@arm.com updateIntState(intNumToWord(num)); 87013014Sciro.santilli@arm.com} 87113014Sciro.santilli@arm.com 87213014Sciro.santilli@arm.comvoid 87313014Sciro.santilli@arm.comGicV2::sendPPInt(uint32_t num, uint32_t cpu) 87413014Sciro.santilli@arm.com{ 87513014Sciro.santilli@arm.com DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n", 87613014Sciro.santilli@arm.com num, cpu); 87713014Sciro.santilli@arm.com cpuPpiPending[cpu] |= 1 << (num - SGI_MAX); 87813014Sciro.santilli@arm.com updateIntState(intNumToWord(num)); 87913014Sciro.santilli@arm.com} 88013014Sciro.santilli@arm.com 88113014Sciro.santilli@arm.comvoid 88213108Sadrien.pesle@arm.comGicV2::clearInt(uint32_t num) 88313014Sciro.santilli@arm.com{ 88413108Sadrien.pesle@arm.com if (isLevelSensitive(0, num)) { 88513108Sadrien.pesle@arm.com uint8_t target = getCpuTarget(0, num); 88613108Sadrien.pesle@arm.com 88713108Sadrien.pesle@arm.com DPRINTF(Interrupt, 88813108Sadrien.pesle@arm.com "Received Clear interrupt number %d, cpuTarget %#x:\n", 88913108Sadrien.pesle@arm.com num, target); 89013108Sadrien.pesle@arm.com 89113108Sadrien.pesle@arm.com getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num)); 89213108Sadrien.pesle@arm.com updateIntState(intNumToWord(num)); 89313108Sadrien.pesle@arm.com } else { 89413108Sadrien.pesle@arm.com /* Nothing to do : 89513108Sadrien.pesle@arm.com * Edge-triggered interrupt remain pending until software 89613108Sadrien.pesle@arm.com * writes GICD_ICPENDR or reads GICC_IAR */ 89713108Sadrien.pesle@arm.com } 89813014Sciro.santilli@arm.com} 89913014Sciro.santilli@arm.com 90013014Sciro.santilli@arm.comvoid 90113014Sciro.santilli@arm.comGicV2::clearPPInt(uint32_t num, uint32_t cpu) 90213014Sciro.santilli@arm.com{ 90313014Sciro.santilli@arm.com DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n", 90413014Sciro.santilli@arm.com num, cpu); 90513014Sciro.santilli@arm.com cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX)); 90613014Sciro.santilli@arm.com updateIntState(intNumToWord(num)); 90713014Sciro.santilli@arm.com} 90813014Sciro.santilli@arm.com 90913014Sciro.santilli@arm.comvoid 91013112Sgiacomo.travaglini@arm.comGicV2::clearInt(ContextID ctx, uint32_t int_num) 91113112Sgiacomo.travaglini@arm.com{ 91213112Sgiacomo.travaglini@arm.com if (isFiq(ctx, int_num)) { 91313112Sgiacomo.travaglini@arm.com platform->intrctrl->clear(ctx, ArmISA::INT_FIQ, 0); 91413112Sgiacomo.travaglini@arm.com } else { 91513112Sgiacomo.travaglini@arm.com platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0); 91613112Sgiacomo.travaglini@arm.com } 91713112Sgiacomo.travaglini@arm.com} 91813112Sgiacomo.travaglini@arm.com 91913112Sgiacomo.travaglini@arm.comvoid 92013014Sciro.santilli@arm.comGicV2::postInt(uint32_t cpu, Tick when) 92113014Sciro.santilli@arm.com{ 92213014Sciro.santilli@arm.com if (!(postIntEvent[cpu]->scheduled())) { 92313014Sciro.santilli@arm.com ++pendingDelayedInterrupts; 92413014Sciro.santilli@arm.com eventq->schedule(postIntEvent[cpu], when); 92513014Sciro.santilli@arm.com } 92613014Sciro.santilli@arm.com} 92713014Sciro.santilli@arm.com 92813014Sciro.santilli@arm.comvoid 92913014Sciro.santilli@arm.comGicV2::postDelayedInt(uint32_t cpu) 93013014Sciro.santilli@arm.com{ 93113014Sciro.santilli@arm.com platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0); 93213014Sciro.santilli@arm.com --pendingDelayedInterrupts; 93313014Sciro.santilli@arm.com assert(pendingDelayedInterrupts >= 0); 93413014Sciro.santilli@arm.com if (pendingDelayedInterrupts == 0) 93513014Sciro.santilli@arm.com signalDrainDone(); 93613014Sciro.santilli@arm.com} 93713014Sciro.santilli@arm.com 93813111Sgiacomo.travaglini@arm.comvoid 93913111Sgiacomo.travaglini@arm.comGicV2::postFiq(uint32_t cpu, Tick when) 94013111Sgiacomo.travaglini@arm.com{ 94113111Sgiacomo.travaglini@arm.com if (!(postFiqEvent[cpu]->scheduled())) { 94213111Sgiacomo.travaglini@arm.com ++pendingDelayedInterrupts; 94313111Sgiacomo.travaglini@arm.com eventq->schedule(postFiqEvent[cpu], when); 94413111Sgiacomo.travaglini@arm.com } 94513111Sgiacomo.travaglini@arm.com} 94613111Sgiacomo.travaglini@arm.com 94713111Sgiacomo.travaglini@arm.comvoid 94813111Sgiacomo.travaglini@arm.comGicV2::postDelayedFiq(uint32_t cpu) 94913111Sgiacomo.travaglini@arm.com{ 95013111Sgiacomo.travaglini@arm.com platform->intrctrl->post(cpu, ArmISA::INT_FIQ, 0); 95113111Sgiacomo.travaglini@arm.com --pendingDelayedInterrupts; 95213111Sgiacomo.travaglini@arm.com assert(pendingDelayedInterrupts >= 0); 95313111Sgiacomo.travaglini@arm.com if (pendingDelayedInterrupts == 0) 95413111Sgiacomo.travaglini@arm.com signalDrainDone(); 95513111Sgiacomo.travaglini@arm.com} 95613111Sgiacomo.travaglini@arm.com 95713014Sciro.santilli@arm.comDrainState 95813014Sciro.santilli@arm.comGicV2::drain() 95913014Sciro.santilli@arm.com{ 96013014Sciro.santilli@arm.com if (pendingDelayedInterrupts == 0) { 96113014Sciro.santilli@arm.com return DrainState::Drained; 96213014Sciro.santilli@arm.com } else { 96313014Sciro.santilli@arm.com return DrainState::Draining; 96413014Sciro.santilli@arm.com } 96513014Sciro.santilli@arm.com} 96613014Sciro.santilli@arm.com 96713014Sciro.santilli@arm.com 96813014Sciro.santilli@arm.comvoid 96913014Sciro.santilli@arm.comGicV2::drainResume() 97013014Sciro.santilli@arm.com{ 97113014Sciro.santilli@arm.com // There may be pending interrupts if checkpointed from Kvm; post them. 97213014Sciro.santilli@arm.com updateIntState(-1); 97313014Sciro.santilli@arm.com} 97413014Sciro.santilli@arm.com 97513014Sciro.santilli@arm.comvoid 97613014Sciro.santilli@arm.comGicV2::serialize(CheckpointOut &cp) const 97713014Sciro.santilli@arm.com{ 97813014Sciro.santilli@arm.com DPRINTF(Checkpoint, "Serializing Arm GIC\n"); 97913014Sciro.santilli@arm.com 98013014Sciro.santilli@arm.com SERIALIZE_SCALAR(enabled); 98113014Sciro.santilli@arm.com SERIALIZE_SCALAR(itLines); 98213014Sciro.santilli@arm.com SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 98313014Sciro.santilli@arm.com SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 98413014Sciro.santilli@arm.com SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 98513110Sgiacomo.travaglini@arm.com SERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); 98613014Sciro.santilli@arm.com SERIALIZE_ARRAY(iccrpr, CPU_MAX); 98713014Sciro.santilli@arm.com SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 98813014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 98913014Sciro.santilli@arm.com SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 99013109Sgiacomo.travaglini@arm.com SERIALIZE_ARRAY(cpuControl, CPU_MAX); 99113014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuPriority, CPU_MAX); 99213014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuBpr, CPU_MAX); 99313014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 99413014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 99513014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 99613014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 99713014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 99813014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 99913014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 100013014Sciro.santilli@arm.com SERIALIZE_SCALAR(gem5ExtensionsEnabled); 100113014Sciro.santilli@arm.com 100213014Sciro.santilli@arm.com for (uint32_t i=0; i < bankedRegs.size(); ++i) { 100313014Sciro.santilli@arm.com if (!bankedRegs[i]) 100413014Sciro.santilli@arm.com continue; 100513014Sciro.santilli@arm.com bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i)); 100613014Sciro.santilli@arm.com } 100713014Sciro.santilli@arm.com} 100813014Sciro.santilli@arm.com 100913014Sciro.santilli@arm.comvoid 101013014Sciro.santilli@arm.comGicV2::BankedRegs::serialize(CheckpointOut &cp) const 101113014Sciro.santilli@arm.com{ 101213014Sciro.santilli@arm.com SERIALIZE_SCALAR(intEnabled); 101313014Sciro.santilli@arm.com SERIALIZE_SCALAR(pendingInt); 101413014Sciro.santilli@arm.com SERIALIZE_SCALAR(activeInt); 101513110Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(intGroup); 101613014Sciro.santilli@arm.com SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 101713014Sciro.santilli@arm.com} 101813014Sciro.santilli@arm.com 101913014Sciro.santilli@arm.comvoid 102013014Sciro.santilli@arm.comGicV2::unserialize(CheckpointIn &cp) 102113014Sciro.santilli@arm.com{ 102213014Sciro.santilli@arm.com DPRINTF(Checkpoint, "Unserializing Arm GIC\n"); 102313014Sciro.santilli@arm.com 102413014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(enabled); 102513014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(itLines); 102613014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 102713014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 102813014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 102913110Sgiacomo.travaglini@arm.com UNSERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); 103013014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(iccrpr, CPU_MAX); 103113014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 103213014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 103313014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 103413109Sgiacomo.travaglini@arm.com UNSERIALIZE_ARRAY(cpuControl, CPU_MAX); 103513014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX); 103613014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX); 103713014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 103813014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 103913014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 104013014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 104113014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 104213014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 104313014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 104413014Sciro.santilli@arm.com 104513014Sciro.santilli@arm.com // Handle checkpoints from before we drained the GIC to prevent 104613014Sciro.santilli@arm.com // in-flight interrupts. 104713014Sciro.santilli@arm.com if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) { 104813014Sciro.santilli@arm.com Tick interrupt_time[CPU_MAX]; 104913014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX); 105013014Sciro.santilli@arm.com 105113014Sciro.santilli@arm.com for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) { 105213014Sciro.santilli@arm.com if (interrupt_time[cpu]) 105313014Sciro.santilli@arm.com schedule(postIntEvent[cpu], interrupt_time[cpu]); 105413014Sciro.santilli@arm.com } 105513014Sciro.santilli@arm.com } 105613014Sciro.santilli@arm.com 105713014Sciro.santilli@arm.com if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled)) 105813014Sciro.santilli@arm.com gem5ExtensionsEnabled = false; 105913014Sciro.santilli@arm.com 106013014Sciro.santilli@arm.com for (uint32_t i=0; i < CPU_MAX; ++i) { 106113014Sciro.santilli@arm.com ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i)); 106213014Sciro.santilli@arm.com if (cp.sectionExists(Serializable::currentSection())) { 106313014Sciro.santilli@arm.com getBankedRegs(i).unserialize(cp); 106413014Sciro.santilli@arm.com } 106513014Sciro.santilli@arm.com } 106613014Sciro.santilli@arm.com} 106713014Sciro.santilli@arm.com 106813014Sciro.santilli@arm.comvoid 106913014Sciro.santilli@arm.comGicV2::BankedRegs::unserialize(CheckpointIn &cp) 107013014Sciro.santilli@arm.com{ 107113014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(intEnabled); 107213014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(pendingInt); 107313014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(activeInt); 107413110Sgiacomo.travaglini@arm.com UNSERIALIZE_SCALAR(intGroup); 107513014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 107613014Sciro.santilli@arm.com} 107713014Sciro.santilli@arm.com 107813014Sciro.santilli@arm.comGicV2 * 107913014Sciro.santilli@arm.comGicV2Params::create() 108013014Sciro.santilli@arm.com{ 108113014Sciro.santilli@arm.com return new GicV2(this); 108213014Sciro.santilli@arm.com} 1083