gic_v2.cc revision 13505
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