gic_v2.cc revision 13108
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; 8313014Sciro.santilli@arm.com cpuEnabled[x] = false; 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"); 9113014Sciro.santilli@arm.com } 9213014Sciro.santilli@arm.com DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0], 9313014Sciro.santilli@arm.com cpuEnabled[1]); 9413014Sciro.santilli@arm.com 9513014Sciro.santilli@arm.com gem5ExtensionsEnabled = false; 9613014Sciro.santilli@arm.com} 9713014Sciro.santilli@arm.com 9813014Sciro.santilli@arm.comGicV2::~GicV2() 9913014Sciro.santilli@arm.com{ 10013014Sciro.santilli@arm.com for (int x = 0; x < CPU_MAX; x++) 10113014Sciro.santilli@arm.com delete postIntEvent[x]; 10213014Sciro.santilli@arm.com} 10313014Sciro.santilli@arm.com 10413014Sciro.santilli@arm.comTick 10513014Sciro.santilli@arm.comGicV2::read(PacketPtr pkt) 10613014Sciro.santilli@arm.com{ 10713014Sciro.santilli@arm.com const Addr addr = pkt->getAddr(); 10813014Sciro.santilli@arm.com 10913014Sciro.santilli@arm.com if (distRange.contains(addr)) 11013014Sciro.santilli@arm.com return readDistributor(pkt); 11113014Sciro.santilli@arm.com else if (cpuRange.contains(addr)) 11213014Sciro.santilli@arm.com return readCpu(pkt); 11313014Sciro.santilli@arm.com else 11413014Sciro.santilli@arm.com panic("Read to unknown address %#x\n", pkt->getAddr()); 11513014Sciro.santilli@arm.com} 11613014Sciro.santilli@arm.com 11713014Sciro.santilli@arm.com 11813014Sciro.santilli@arm.comTick 11913014Sciro.santilli@arm.comGicV2::write(PacketPtr pkt) 12013014Sciro.santilli@arm.com{ 12113014Sciro.santilli@arm.com const Addr addr = pkt->getAddr(); 12213014Sciro.santilli@arm.com 12313014Sciro.santilli@arm.com if (distRange.contains(addr)) 12413014Sciro.santilli@arm.com return writeDistributor(pkt); 12513014Sciro.santilli@arm.com else if (cpuRange.contains(addr)) 12613014Sciro.santilli@arm.com return writeCpu(pkt); 12713014Sciro.santilli@arm.com else 12813014Sciro.santilli@arm.com panic("Write to unknown address %#x\n", pkt->getAddr()); 12913014Sciro.santilli@arm.com} 13013014Sciro.santilli@arm.com 13113014Sciro.santilli@arm.comTick 13213014Sciro.santilli@arm.comGicV2::readDistributor(PacketPtr pkt) 13313014Sciro.santilli@arm.com{ 13413014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - distRange.start(); 13513014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 13613014Sciro.santilli@arm.com 13713014Sciro.santilli@arm.com DPRINTF(GIC, "gic distributor read register %#x\n", daddr); 13813014Sciro.santilli@arm.com 13913014Sciro.santilli@arm.com const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize()); 14013014Sciro.santilli@arm.com 14113014Sciro.santilli@arm.com switch (pkt->getSize()) { 14213014Sciro.santilli@arm.com case 1: 14313014Sciro.santilli@arm.com pkt->set<uint8_t>(resp); 14413014Sciro.santilli@arm.com break; 14513014Sciro.santilli@arm.com case 2: 14613014Sciro.santilli@arm.com pkt->set<uint16_t>(resp); 14713014Sciro.santilli@arm.com break; 14813014Sciro.santilli@arm.com case 4: 14913014Sciro.santilli@arm.com pkt->set<uint32_t>(resp); 15013014Sciro.santilli@arm.com break; 15113014Sciro.santilli@arm.com default: 15213014Sciro.santilli@arm.com panic("Invalid size while reading Distributor regs in GIC: %d\n", 15313014Sciro.santilli@arm.com pkt->getSize()); 15413014Sciro.santilli@arm.com } 15513014Sciro.santilli@arm.com 15613014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 15713014Sciro.santilli@arm.com return distPioDelay; 15813014Sciro.santilli@arm.com} 15913014Sciro.santilli@arm.com 16013014Sciro.santilli@arm.comuint32_t 16113014Sciro.santilli@arm.comGicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz) 16213014Sciro.santilli@arm.com{ 16313014Sciro.santilli@arm.com if (GICD_IGROUPR.contains(daddr)) { 16413014Sciro.santilli@arm.com return 0; // unimplemented; RAZ (read as zero) 16513014Sciro.santilli@arm.com } 16613014Sciro.santilli@arm.com 16713014Sciro.santilli@arm.com if (GICD_ISENABLER.contains(daddr)) { 16813014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 16913014Sciro.santilli@arm.com assert(ix < 32); 17013014Sciro.santilli@arm.com return getIntEnabled(ctx, ix); 17113014Sciro.santilli@arm.com } 17213014Sciro.santilli@arm.com 17313014Sciro.santilli@arm.com if (GICD_ICENABLER.contains(daddr)) { 17413014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 17513014Sciro.santilli@arm.com assert(ix < 32); 17613014Sciro.santilli@arm.com return getIntEnabled(ctx, ix); 17713014Sciro.santilli@arm.com } 17813014Sciro.santilli@arm.com 17913014Sciro.santilli@arm.com if (GICD_ISPENDR.contains(daddr)) { 18013014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 18113014Sciro.santilli@arm.com assert(ix < 32); 18213014Sciro.santilli@arm.com return getPendingInt(ctx, ix); 18313014Sciro.santilli@arm.com } 18413014Sciro.santilli@arm.com 18513014Sciro.santilli@arm.com if (GICD_ICPENDR.contains(daddr)) { 18613014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 18713014Sciro.santilli@arm.com assert(ix < 32); 18813014Sciro.santilli@arm.com return getPendingInt(ctx, ix); 18913014Sciro.santilli@arm.com } 19013014Sciro.santilli@arm.com 19113014Sciro.santilli@arm.com if (GICD_ISACTIVER.contains(daddr)) { 19213014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 19313014Sciro.santilli@arm.com assert(ix < 32); 19413014Sciro.santilli@arm.com return getActiveInt(ctx, ix); 19513014Sciro.santilli@arm.com } 19613014Sciro.santilli@arm.com 19713014Sciro.santilli@arm.com if (GICD_ICACTIVER.contains(daddr)) { 19813014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 19913014Sciro.santilli@arm.com assert(ix < 32); 20013014Sciro.santilli@arm.com return getActiveInt(ctx, ix); 20113014Sciro.santilli@arm.com } 20213014Sciro.santilli@arm.com 20313014Sciro.santilli@arm.com if (GICD_IPRIORITYR.contains(daddr)) { 20413014Sciro.santilli@arm.com Addr int_num = daddr - GICD_IPRIORITYR.start(); 20513014Sciro.santilli@arm.com assert(int_num < INT_LINES_MAX); 20613014Sciro.santilli@arm.com DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n", 20713014Sciro.santilli@arm.com int_num); 20813014Sciro.santilli@arm.com 20913014Sciro.santilli@arm.com switch (resp_sz) { 21013014Sciro.santilli@arm.com default: // will panic() after return to caller anyway 21113014Sciro.santilli@arm.com case 1: 21213014Sciro.santilli@arm.com return getIntPriority(ctx, int_num); 21313014Sciro.santilli@arm.com case 2: 21413014Sciro.santilli@arm.com assert((int_num + 1) < INT_LINES_MAX); 21513014Sciro.santilli@arm.com return (getIntPriority(ctx, int_num) | 21613014Sciro.santilli@arm.com getIntPriority(ctx, int_num+1) << 8); 21713014Sciro.santilli@arm.com case 4: 21813014Sciro.santilli@arm.com assert((int_num + 3) < INT_LINES_MAX); 21913014Sciro.santilli@arm.com return (getIntPriority(ctx, int_num) | 22013014Sciro.santilli@arm.com getIntPriority(ctx, int_num+1) << 8 | 22113014Sciro.santilli@arm.com getIntPriority(ctx, int_num+2) << 16 | 22213014Sciro.santilli@arm.com getIntPriority(ctx, int_num+3) << 24); 22313014Sciro.santilli@arm.com } 22413014Sciro.santilli@arm.com } 22513014Sciro.santilli@arm.com 22613014Sciro.santilli@arm.com if (GICD_ITARGETSR.contains(daddr)) { 22713014Sciro.santilli@arm.com Addr int_num = daddr - GICD_ITARGETSR.start(); 22813014Sciro.santilli@arm.com DPRINTF(GIC, "Reading processor target register for int# %#x \n", 22913014Sciro.santilli@arm.com int_num); 23013014Sciro.santilli@arm.com assert(int_num < INT_LINES_MAX); 23113014Sciro.santilli@arm.com 23213014Sciro.santilli@arm.com if (resp_sz == 1) { 23313014Sciro.santilli@arm.com return getCpuTarget(ctx, int_num); 23413014Sciro.santilli@arm.com } else { 23513014Sciro.santilli@arm.com assert(resp_sz == 4); 23613014Sciro.santilli@arm.com int_num = mbits(int_num, 31, 2); 23713014Sciro.santilli@arm.com return (getCpuTarget(ctx, int_num) | 23813014Sciro.santilli@arm.com getCpuTarget(ctx, int_num+1) << 8 | 23913014Sciro.santilli@arm.com getCpuTarget(ctx, int_num+2) << 16 | 24013014Sciro.santilli@arm.com getCpuTarget(ctx, int_num+3) << 24) ; 24113014Sciro.santilli@arm.com } 24213014Sciro.santilli@arm.com } 24313014Sciro.santilli@arm.com 24413014Sciro.santilli@arm.com if (GICD_ICFGR.contains(daddr)) { 24513014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 24613014Sciro.santilli@arm.com assert(ix < 64); 24713014Sciro.santilli@arm.com /** @todo software generated interrupts and PPIs 24813014Sciro.santilli@arm.com * can't be configured in some ways */ 24913014Sciro.santilli@arm.com return intConfig[ix]; 25013014Sciro.santilli@arm.com } 25113014Sciro.santilli@arm.com 25213014Sciro.santilli@arm.com switch(daddr) { 25313014Sciro.santilli@arm.com case GICD_CTLR: 25413014Sciro.santilli@arm.com return enabled; 25513014Sciro.santilli@arm.com case GICD_TYPER: 25613014Sciro.santilli@arm.com /* The 0x100 is a made-up flag to show that gem5 extensions 25713014Sciro.santilli@arm.com * are available, 25813014Sciro.santilli@arm.com * write 0x200 to this register to enable it. */ 25913014Sciro.santilli@arm.com return (((sys->numRunningContexts() - 1) << 5) | 26013014Sciro.santilli@arm.com (itLines/INT_BITS_MAX -1) | 26113014Sciro.santilli@arm.com (haveGem5Extensions ? 0x100 : 0x0)); 26213014Sciro.santilli@arm.com case GICD_PIDR0: 26313014Sciro.santilli@arm.com //ARM defined DevID 26413014Sciro.santilli@arm.com return (GICD_400_PIDR_VALUE & 0xFF); 26513014Sciro.santilli@arm.com case GICD_PIDR1: 26613014Sciro.santilli@arm.com return ((GICD_400_PIDR_VALUE >> 8) & 0xFF); 26713014Sciro.santilli@arm.com case GICD_PIDR2: 26813014Sciro.santilli@arm.com return ((GICD_400_PIDR_VALUE >> 16) & 0xFF); 26913014Sciro.santilli@arm.com case GICD_PIDR3: 27013014Sciro.santilli@arm.com return ((GICD_400_PIDR_VALUE >> 24) & 0xFF); 27113014Sciro.santilli@arm.com case GICD_IIDR: 27213014Sciro.santilli@arm.com /* revision id is resorted to 1 and variant to 0*/ 27313014Sciro.santilli@arm.com return GICD_400_IIDR_VALUE; 27413014Sciro.santilli@arm.com default: 27513014Sciro.santilli@arm.com panic("Tried to read Gic distributor at offset %#x\n", daddr); 27613014Sciro.santilli@arm.com break; 27713014Sciro.santilli@arm.com } 27813014Sciro.santilli@arm.com} 27913014Sciro.santilli@arm.com 28013014Sciro.santilli@arm.comTick 28113014Sciro.santilli@arm.comGicV2::readCpu(PacketPtr pkt) 28213014Sciro.santilli@arm.com{ 28313014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - cpuRange.start(); 28413014Sciro.santilli@arm.com 28513014Sciro.santilli@arm.com assert(pkt->req->hasContextId()); 28613014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 28713014Sciro.santilli@arm.com assert(ctx < sys->numRunningContexts()); 28813014Sciro.santilli@arm.com 28913014Sciro.santilli@arm.com DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, 29013014Sciro.santilli@arm.com ctx); 29113014Sciro.santilli@arm.com 29213014Sciro.santilli@arm.com pkt->set<uint32_t>(readCpu(ctx, daddr)); 29313014Sciro.santilli@arm.com 29413014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 29513014Sciro.santilli@arm.com return cpuPioDelay; 29613014Sciro.santilli@arm.com} 29713014Sciro.santilli@arm.com 29813014Sciro.santilli@arm.comuint32_t 29913014Sciro.santilli@arm.comGicV2::readCpu(ContextID ctx, Addr daddr) 30013014Sciro.santilli@arm.com{ 30113014Sciro.santilli@arm.com switch(daddr) { 30213014Sciro.santilli@arm.com case GICC_IIDR: 30313014Sciro.santilli@arm.com return GICC_400_IIDR_VALUE; 30413014Sciro.santilli@arm.com case GICC_CTLR: 30513014Sciro.santilli@arm.com return cpuEnabled[ctx]; 30613014Sciro.santilli@arm.com case GICC_PMR: 30713014Sciro.santilli@arm.com return cpuPriority[ctx]; 30813014Sciro.santilli@arm.com case GICC_BPR: 30913014Sciro.santilli@arm.com return cpuBpr[ctx]; 31013014Sciro.santilli@arm.com case GICC_IAR: 31113014Sciro.santilli@arm.com if (enabled && cpuEnabled[ctx]) { 31213014Sciro.santilli@arm.com int active_int = cpuHighestInt[ctx]; 31313014Sciro.santilli@arm.com IAR iar = 0; 31413014Sciro.santilli@arm.com iar.ack_id = active_int; 31513014Sciro.santilli@arm.com iar.cpu_id = 0; 31613014Sciro.santilli@arm.com if (active_int < SGI_MAX) { 31713014Sciro.santilli@arm.com // this is a software interrupt from another CPU 31813014Sciro.santilli@arm.com if (!gem5ExtensionsEnabled) { 31913014Sciro.santilli@arm.com panic_if(!cpuSgiPending[active_int], 32013014Sciro.santilli@arm.com "Interrupt %d active but no CPU generated it?\n", 32113014Sciro.santilli@arm.com active_int); 32213014Sciro.santilli@arm.com for (int x = 0; x < sys->numRunningContexts(); x++) { 32313014Sciro.santilli@arm.com // See which CPU generated the interrupt 32413014Sciro.santilli@arm.com uint8_t cpugen = 32513014Sciro.santilli@arm.com bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x); 32613014Sciro.santilli@arm.com if (cpugen & (1 << ctx)) { 32713014Sciro.santilli@arm.com iar.cpu_id = x; 32813014Sciro.santilli@arm.com break; 32913014Sciro.santilli@arm.com } 33013014Sciro.santilli@arm.com } 33113014Sciro.santilli@arm.com uint64_t sgi_num = ULL(1) << (ctx + 8 * iar.cpu_id); 33213014Sciro.santilli@arm.com cpuSgiActive[iar.ack_id] |= sgi_num; 33313014Sciro.santilli@arm.com cpuSgiPending[iar.ack_id] &= ~sgi_num; 33413014Sciro.santilli@arm.com } else { 33513014Sciro.santilli@arm.com uint64_t sgi_num = ULL(1) << iar.ack_id; 33613014Sciro.santilli@arm.com cpuSgiActiveExt[ctx] |= sgi_num; 33713014Sciro.santilli@arm.com cpuSgiPendingExt[ctx] &= ~sgi_num; 33813014Sciro.santilli@arm.com } 33913014Sciro.santilli@arm.com } else if (active_int < (SGI_MAX + PPI_MAX) ) { 34013014Sciro.santilli@arm.com uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX); 34113014Sciro.santilli@arm.com cpuPpiActive[ctx] |= int_num; 34213014Sciro.santilli@arm.com updateRunPri(); 34313014Sciro.santilli@arm.com cpuPpiPending[ctx] &= ~int_num; 34413014Sciro.santilli@arm.com 34513014Sciro.santilli@arm.com } else { 34613014Sciro.santilli@arm.com uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]); 34713014Sciro.santilli@arm.com getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num; 34813014Sciro.santilli@arm.com updateRunPri(); 34913108Sadrien.pesle@arm.com if (!isLevelSensitive(ctx, active_int)) { 35013108Sadrien.pesle@arm.com getPendingInt(ctx, intNumToWord(cpuHighestInt[ctx])) 35113108Sadrien.pesle@arm.com &= ~int_num; 35213108Sadrien.pesle@arm.com } 35313014Sciro.santilli@arm.com } 35413014Sciro.santilli@arm.com 35513014Sciro.santilli@arm.com DPRINTF(Interrupt, 35613014Sciro.santilli@arm.com "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n", 35713014Sciro.santilli@arm.com ctx, iar.ack_id, iar.cpu_id, iar); 35813014Sciro.santilli@arm.com cpuHighestInt[ctx] = SPURIOUS_INT; 35913014Sciro.santilli@arm.com updateIntState(-1); 36013014Sciro.santilli@arm.com platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0); 36113014Sciro.santilli@arm.com return iar; 36213014Sciro.santilli@arm.com } else { 36313014Sciro.santilli@arm.com return SPURIOUS_INT; 36413014Sciro.santilli@arm.com } 36513014Sciro.santilli@arm.com 36613014Sciro.santilli@arm.com break; 36713014Sciro.santilli@arm.com case GICC_RPR: 36813014Sciro.santilli@arm.com return iccrpr[0]; 36913014Sciro.santilli@arm.com case GICC_HPPIR: 37013014Sciro.santilli@arm.com panic("Need to implement HPIR"); 37113014Sciro.santilli@arm.com break; 37213014Sciro.santilli@arm.com default: 37313014Sciro.santilli@arm.com panic("Tried to read Gic cpu at offset %#x\n", daddr); 37413014Sciro.santilli@arm.com break; 37513014Sciro.santilli@arm.com } 37613014Sciro.santilli@arm.com} 37713014Sciro.santilli@arm.com 37813014Sciro.santilli@arm.comTick 37913014Sciro.santilli@arm.comGicV2::writeDistributor(PacketPtr pkt) 38013014Sciro.santilli@arm.com{ 38113014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - distRange.start(); 38213014Sciro.santilli@arm.com 38313014Sciro.santilli@arm.com assert(pkt->req->hasContextId()); 38413014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 38513014Sciro.santilli@arm.com const size_t data_sz = pkt->getSize(); 38613014Sciro.santilli@arm.com 38713014Sciro.santilli@arm.com uint32_t pkt_data M5_VAR_USED; 38813014Sciro.santilli@arm.com switch (data_sz) 38913014Sciro.santilli@arm.com { 39013014Sciro.santilli@arm.com case 1: 39113014Sciro.santilli@arm.com pkt_data = pkt->get<uint8_t>(); 39213014Sciro.santilli@arm.com break; 39313014Sciro.santilli@arm.com case 2: 39413014Sciro.santilli@arm.com pkt_data = pkt->get<uint16_t>(); 39513014Sciro.santilli@arm.com break; 39613014Sciro.santilli@arm.com case 4: 39713014Sciro.santilli@arm.com pkt_data = pkt->get<uint32_t>(); 39813014Sciro.santilli@arm.com break; 39913014Sciro.santilli@arm.com default: 40013014Sciro.santilli@arm.com panic("Invalid size when writing to priority regs in Gic: %d\n", 40113014Sciro.santilli@arm.com data_sz); 40213014Sciro.santilli@arm.com } 40313014Sciro.santilli@arm.com 40413014Sciro.santilli@arm.com DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n", 40513014Sciro.santilli@arm.com daddr, data_sz, pkt_data); 40613014Sciro.santilli@arm.com 40713014Sciro.santilli@arm.com writeDistributor(ctx, daddr, pkt_data, data_sz); 40813014Sciro.santilli@arm.com 40913014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 41013014Sciro.santilli@arm.com return distPioDelay; 41113014Sciro.santilli@arm.com} 41213014Sciro.santilli@arm.com 41313014Sciro.santilli@arm.comvoid 41413014Sciro.santilli@arm.comGicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data, 41513014Sciro.santilli@arm.com size_t data_sz) 41613014Sciro.santilli@arm.com{ 41713014Sciro.santilli@arm.com if (GICD_IGROUPR.contains(daddr)) { 41813014Sciro.santilli@arm.com return; // unimplemented; WI (writes ignored) 41913014Sciro.santilli@arm.com } 42013014Sciro.santilli@arm.com 42113014Sciro.santilli@arm.com if (GICD_ISENABLER.contains(daddr)) { 42213014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 42313014Sciro.santilli@arm.com assert(ix < 32); 42413014Sciro.santilli@arm.com getIntEnabled(ctx, ix) |= data; 42513014Sciro.santilli@arm.com return; 42613014Sciro.santilli@arm.com } 42713014Sciro.santilli@arm.com 42813014Sciro.santilli@arm.com if (GICD_ICENABLER.contains(daddr)) { 42913014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 43013014Sciro.santilli@arm.com assert(ix < 32); 43113014Sciro.santilli@arm.com getIntEnabled(ctx, ix) &= ~data; 43213014Sciro.santilli@arm.com return; 43313014Sciro.santilli@arm.com } 43413014Sciro.santilli@arm.com 43513014Sciro.santilli@arm.com if (GICD_ISPENDR.contains(daddr)) { 43613014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 43713014Sciro.santilli@arm.com auto mask = data; 43813014Sciro.santilli@arm.com if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 43913014Sciro.santilli@arm.com getPendingInt(ctx, ix) |= mask; 44013014Sciro.santilli@arm.com updateIntState(ix); 44113014Sciro.santilli@arm.com return; 44213014Sciro.santilli@arm.com } 44313014Sciro.santilli@arm.com 44413014Sciro.santilli@arm.com if (GICD_ICPENDR.contains(daddr)) { 44513014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 44613014Sciro.santilli@arm.com auto mask = data; 44713014Sciro.santilli@arm.com if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 44813014Sciro.santilli@arm.com getPendingInt(ctx, ix) &= ~mask; 44913014Sciro.santilli@arm.com updateIntState(ix); 45013014Sciro.santilli@arm.com return; 45113014Sciro.santilli@arm.com } 45213014Sciro.santilli@arm.com 45313014Sciro.santilli@arm.com if (GICD_ISACTIVER.contains(daddr)) { 45413014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 45513014Sciro.santilli@arm.com getActiveInt(ctx, ix) |= data; 45613014Sciro.santilli@arm.com return; 45713014Sciro.santilli@arm.com } 45813014Sciro.santilli@arm.com 45913014Sciro.santilli@arm.com if (GICD_ICACTIVER.contains(daddr)) { 46013014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 46113014Sciro.santilli@arm.com getActiveInt(ctx, ix) &= ~data; 46213014Sciro.santilli@arm.com return; 46313014Sciro.santilli@arm.com } 46413014Sciro.santilli@arm.com 46513014Sciro.santilli@arm.com if (GICD_IPRIORITYR.contains(daddr)) { 46613014Sciro.santilli@arm.com Addr int_num = daddr - GICD_IPRIORITYR.start(); 46713014Sciro.santilli@arm.com switch(data_sz) { 46813014Sciro.santilli@arm.com case 1: 46913014Sciro.santilli@arm.com getIntPriority(ctx, int_num) = data; 47013014Sciro.santilli@arm.com break; 47113014Sciro.santilli@arm.com case 2: { 47213014Sciro.santilli@arm.com getIntPriority(ctx, int_num) = bits(data, 7, 0); 47313014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 47413014Sciro.santilli@arm.com break; 47513014Sciro.santilli@arm.com } 47613014Sciro.santilli@arm.com case 4: { 47713014Sciro.santilli@arm.com getIntPriority(ctx, int_num) = bits(data, 7, 0); 47813014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 47913014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 2) = bits(data, 23, 16); 48013014Sciro.santilli@arm.com getIntPriority(ctx, int_num + 3) = bits(data, 31, 24); 48113014Sciro.santilli@arm.com break; 48213014Sciro.santilli@arm.com } 48313014Sciro.santilli@arm.com default: 48413014Sciro.santilli@arm.com panic("Invalid size when writing to priority regs in Gic: %d\n", 48513014Sciro.santilli@arm.com data_sz); 48613014Sciro.santilli@arm.com } 48713014Sciro.santilli@arm.com 48813014Sciro.santilli@arm.com updateIntState(-1); 48913014Sciro.santilli@arm.com updateRunPri(); 49013014Sciro.santilli@arm.com return; 49113014Sciro.santilli@arm.com } 49213014Sciro.santilli@arm.com 49313014Sciro.santilli@arm.com if (GICD_ITARGETSR.contains(daddr)) { 49413014Sciro.santilli@arm.com Addr int_num = daddr - GICD_ITARGETSR.start(); 49513014Sciro.santilli@arm.com // Interrupts 0-31 are read only 49613014Sciro.santilli@arm.com unsigned offset = SGI_MAX + PPI_MAX; 49713014Sciro.santilli@arm.com if (int_num >= offset) { 49813014Sciro.santilli@arm.com unsigned ix = int_num - offset; // index into cpuTarget array 49913014Sciro.santilli@arm.com if (data_sz == 1) { 50013014Sciro.santilli@arm.com cpuTarget[ix] = data & 0xff; 50113014Sciro.santilli@arm.com } else { 50213014Sciro.santilli@arm.com assert (data_sz == 4); 50313014Sciro.santilli@arm.com cpuTarget[ix] = bits(data, 7, 0); 50413014Sciro.santilli@arm.com cpuTarget[ix+1] = bits(data, 15, 8); 50513014Sciro.santilli@arm.com cpuTarget[ix+2] = bits(data, 23, 16); 50613014Sciro.santilli@arm.com cpuTarget[ix+3] = bits(data, 31, 24); 50713014Sciro.santilli@arm.com } 50813014Sciro.santilli@arm.com updateIntState(int_num >> 2); 50913014Sciro.santilli@arm.com } 51013014Sciro.santilli@arm.com return; 51113014Sciro.santilli@arm.com } 51213014Sciro.santilli@arm.com 51313014Sciro.santilli@arm.com if (GICD_ICFGR.contains(daddr)) { 51413014Sciro.santilli@arm.com uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 51513014Sciro.santilli@arm.com assert(ix < INT_BITS_MAX*2); 51613014Sciro.santilli@arm.com intConfig[ix] = data; 51713014Sciro.santilli@arm.com if (data & NN_CONFIG_MASK) 51813014Sciro.santilli@arm.com warn("GIC N:N mode selected and not supported at this time\n"); 51913014Sciro.santilli@arm.com return; 52013014Sciro.santilli@arm.com } 52113014Sciro.santilli@arm.com 52213014Sciro.santilli@arm.com switch(daddr) { 52313014Sciro.santilli@arm.com case GICD_CTLR: 52413014Sciro.santilli@arm.com enabled = data; 52513014Sciro.santilli@arm.com DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled); 52613014Sciro.santilli@arm.com break; 52713014Sciro.santilli@arm.com case GICD_TYPER: 52813014Sciro.santilli@arm.com /* 0x200 is a made-up flag to enable gem5 extension functionality. 52913014Sciro.santilli@arm.com * This reg is not normally written. 53013014Sciro.santilli@arm.com */ 53113014Sciro.santilli@arm.com gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions; 53213014Sciro.santilli@arm.com DPRINTF(GIC, "gem5 extensions %s\n", 53313014Sciro.santilli@arm.com gem5ExtensionsEnabled ? "enabled" : "disabled"); 53413014Sciro.santilli@arm.com break; 53513014Sciro.santilli@arm.com case GICD_SGIR: 53613014Sciro.santilli@arm.com softInt(ctx, data); 53713014Sciro.santilli@arm.com break; 53813014Sciro.santilli@arm.com default: 53913014Sciro.santilli@arm.com panic("Tried to write Gic distributor at offset %#x\n", daddr); 54013014Sciro.santilli@arm.com break; 54113014Sciro.santilli@arm.com } 54213014Sciro.santilli@arm.com} 54313014Sciro.santilli@arm.com 54413014Sciro.santilli@arm.comTick 54513014Sciro.santilli@arm.comGicV2::writeCpu(PacketPtr pkt) 54613014Sciro.santilli@arm.com{ 54713014Sciro.santilli@arm.com const Addr daddr = pkt->getAddr() - cpuRange.start(); 54813014Sciro.santilli@arm.com 54913014Sciro.santilli@arm.com assert(pkt->req->hasContextId()); 55013014Sciro.santilli@arm.com const ContextID ctx = pkt->req->contextId(); 55113014Sciro.santilli@arm.com const uint32_t data = pkt->get<uint32_t>(); 55213014Sciro.santilli@arm.com 55313014Sciro.santilli@arm.com DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n", 55413014Sciro.santilli@arm.com ctx, daddr, data); 55513014Sciro.santilli@arm.com 55613014Sciro.santilli@arm.com writeCpu(ctx, daddr, data); 55713014Sciro.santilli@arm.com 55813014Sciro.santilli@arm.com pkt->makeAtomicResponse(); 55913014Sciro.santilli@arm.com return cpuPioDelay; 56013014Sciro.santilli@arm.com} 56113014Sciro.santilli@arm.com 56213014Sciro.santilli@arm.comvoid 56313014Sciro.santilli@arm.comGicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data) 56413014Sciro.santilli@arm.com{ 56513014Sciro.santilli@arm.com switch(daddr) { 56613014Sciro.santilli@arm.com case GICC_CTLR: 56713014Sciro.santilli@arm.com cpuEnabled[ctx] = data; 56813014Sciro.santilli@arm.com break; 56913014Sciro.santilli@arm.com case GICC_PMR: 57013014Sciro.santilli@arm.com cpuPriority[ctx] = data; 57113014Sciro.santilli@arm.com break; 57213014Sciro.santilli@arm.com case GICC_BPR: { 57313014Sciro.santilli@arm.com auto bpr = data & 0x7; 57413014Sciro.santilli@arm.com if (bpr < GICC_BPR_MINIMUM) 57513014Sciro.santilli@arm.com bpr = GICC_BPR_MINIMUM; 57613014Sciro.santilli@arm.com cpuBpr[ctx] = bpr; 57713014Sciro.santilli@arm.com break; 57813014Sciro.santilli@arm.com } 57913014Sciro.santilli@arm.com case GICC_EOIR: { 58013014Sciro.santilli@arm.com const IAR iar = data; 58113014Sciro.santilli@arm.com if (iar.ack_id < SGI_MAX) { 58213014Sciro.santilli@arm.com // Clear out the bit that corresponds to the cleared int 58313014Sciro.santilli@arm.com uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id); 58413014Sciro.santilli@arm.com if (!(cpuSgiActive[iar.ack_id] & clr_int) && 58513014Sciro.santilli@arm.com !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id))) 58613014Sciro.santilli@arm.com panic("Done handling a SGI that isn't active?\n"); 58713014Sciro.santilli@arm.com if (gem5ExtensionsEnabled) 58813014Sciro.santilli@arm.com cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id); 58913014Sciro.santilli@arm.com else 59013014Sciro.santilli@arm.com cpuSgiActive[iar.ack_id] &= ~clr_int; 59113014Sciro.santilli@arm.com } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) { 59213014Sciro.santilli@arm.com uint32_t int_num = 1 << (iar.ack_id - SGI_MAX); 59313014Sciro.santilli@arm.com if (!(cpuPpiActive[ctx] & int_num)) 59413014Sciro.santilli@arm.com panic("CPU %d Done handling a PPI interrupt " 59513014Sciro.santilli@arm.com "that isn't active?\n", ctx); 59613014Sciro.santilli@arm.com cpuPpiActive[ctx] &= ~int_num; 59713014Sciro.santilli@arm.com } else { 59813014Sciro.santilli@arm.com uint32_t int_num = 1 << intNumToBit(iar.ack_id); 59913014Sciro.santilli@arm.com if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num)) 60013014Sciro.santilli@arm.com warn("Done handling interrupt that isn't active: %d\n", 60113014Sciro.santilli@arm.com intNumToBit(iar.ack_id)); 60213014Sciro.santilli@arm.com getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num; 60313014Sciro.santilli@arm.com } 60413014Sciro.santilli@arm.com updateRunPri(); 60513014Sciro.santilli@arm.com DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n", 60613014Sciro.santilli@arm.com ctx, iar.ack_id, iar.cpu_id); 60713014Sciro.santilli@arm.com break; 60813014Sciro.santilli@arm.com } 60913014Sciro.santilli@arm.com case GICC_APR0: 61013014Sciro.santilli@arm.com case GICC_APR1: 61113014Sciro.santilli@arm.com case GICC_APR2: 61213014Sciro.santilli@arm.com case GICC_APR3: 61313014Sciro.santilli@arm.com warn("GIC APRn write ignored because not implemented: %#x\n", daddr); 61413014Sciro.santilli@arm.com break; 61513014Sciro.santilli@arm.com default: 61613014Sciro.santilli@arm.com panic("Tried to write Gic cpu at offset %#x\n", daddr); 61713014Sciro.santilli@arm.com break; 61813014Sciro.santilli@arm.com } 61913014Sciro.santilli@arm.com if (cpuEnabled[ctx]) updateIntState(-1); 62013014Sciro.santilli@arm.com} 62113014Sciro.santilli@arm.com 62213014Sciro.santilli@arm.comGicV2::BankedRegs& 62313014Sciro.santilli@arm.comGicV2::getBankedRegs(ContextID ctx) { 62413014Sciro.santilli@arm.com if (bankedRegs.size() <= ctx) 62513014Sciro.santilli@arm.com bankedRegs.resize(ctx + 1); 62613014Sciro.santilli@arm.com 62713014Sciro.santilli@arm.com if (!bankedRegs[ctx]) 62813014Sciro.santilli@arm.com bankedRegs[ctx] = new BankedRegs; 62913014Sciro.santilli@arm.com return *bankedRegs[ctx]; 63013014Sciro.santilli@arm.com} 63113014Sciro.santilli@arm.com 63213014Sciro.santilli@arm.comvoid 63313014Sciro.santilli@arm.comGicV2::softInt(ContextID ctx, SWI swi) 63413014Sciro.santilli@arm.com{ 63513014Sciro.santilli@arm.com if (gem5ExtensionsEnabled) { 63613014Sciro.santilli@arm.com switch (swi.list_type) { 63713014Sciro.santilli@arm.com case 0: { 63813014Sciro.santilli@arm.com // interrupt cpus specified 63913014Sciro.santilli@arm.com int dest = swi.cpu_list; 64013014Sciro.santilli@arm.com DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 64113014Sciro.santilli@arm.com ctx, dest); 64213014Sciro.santilli@arm.com if (cpuEnabled[dest]) { 64313014Sciro.santilli@arm.com cpuSgiPendingExt[dest] |= (1 << swi.sgi_id); 64413014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", dest, 64513014Sciro.santilli@arm.com cpuSgiPendingExt[dest]); 64613014Sciro.santilli@arm.com } 64713014Sciro.santilli@arm.com } break; 64813014Sciro.santilli@arm.com case 1: { 64913014Sciro.santilli@arm.com // interrupt all 65013014Sciro.santilli@arm.com for (int i = 0; i < sys->numContexts(); i++) { 65113014Sciro.santilli@arm.com DPRINTF(IPI, "Processing CPU %d\n", i); 65213014Sciro.santilli@arm.com if (!cpuEnabled[i]) 65313014Sciro.santilli@arm.com continue; 65413014Sciro.santilli@arm.com cpuSgiPendingExt[i] |= 1 << swi.sgi_id; 65513014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 65613014Sciro.santilli@arm.com cpuSgiPendingExt[i]); 65713014Sciro.santilli@arm.com } 65813014Sciro.santilli@arm.com } break; 65913014Sciro.santilli@arm.com case 2: { 66013014Sciro.santilli@arm.com // Interrupt requesting cpu only 66113014Sciro.santilli@arm.com DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 66213014Sciro.santilli@arm.com ctx, ctx); 66313014Sciro.santilli@arm.com if (cpuEnabled[ctx]) { 66413014Sciro.santilli@arm.com cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id); 66513014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", ctx, 66613014Sciro.santilli@arm.com cpuSgiPendingExt[ctx]); 66713014Sciro.santilli@arm.com } 66813014Sciro.santilli@arm.com } break; 66913014Sciro.santilli@arm.com } 67013014Sciro.santilli@arm.com } else { 67113014Sciro.santilli@arm.com switch (swi.list_type) { 67213014Sciro.santilli@arm.com case 1: 67313014Sciro.santilli@arm.com // interrupt all 67413014Sciro.santilli@arm.com uint8_t cpu_list; 67513014Sciro.santilli@arm.com cpu_list = 0; 67613014Sciro.santilli@arm.com for (int x = 0; x < sys->numContexts(); x++) 67713014Sciro.santilli@arm.com cpu_list |= cpuEnabled[x] ? 1 << x : 0; 67813014Sciro.santilli@arm.com swi.cpu_list = cpu_list; 67913014Sciro.santilli@arm.com break; 68013014Sciro.santilli@arm.com case 2: 68113014Sciro.santilli@arm.com // interrupt requesting cpu only 68213014Sciro.santilli@arm.com swi.cpu_list = 1 << ctx; 68313014Sciro.santilli@arm.com break; 68413014Sciro.santilli@arm.com // else interrupt cpus specified 68513014Sciro.santilli@arm.com } 68613014Sciro.santilli@arm.com 68713014Sciro.santilli@arm.com DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx, 68813014Sciro.santilli@arm.com swi.cpu_list); 68913014Sciro.santilli@arm.com for (int i = 0; i < sys->numContexts(); i++) { 69013014Sciro.santilli@arm.com DPRINTF(IPI, "Processing CPU %d\n", i); 69113014Sciro.santilli@arm.com if (!cpuEnabled[i]) 69213014Sciro.santilli@arm.com continue; 69313014Sciro.santilli@arm.com if (swi.cpu_list & (1 << i)) 69413014Sciro.santilli@arm.com cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx); 69513014Sciro.santilli@arm.com DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 69613014Sciro.santilli@arm.com cpuSgiPending[swi.sgi_id]); 69713014Sciro.santilli@arm.com } 69813014Sciro.santilli@arm.com } 69913014Sciro.santilli@arm.com updateIntState(-1); 70013014Sciro.santilli@arm.com} 70113014Sciro.santilli@arm.com 70213014Sciro.santilli@arm.comuint64_t 70313014Sciro.santilli@arm.comGicV2::genSwiMask(int cpu) 70413014Sciro.santilli@arm.com{ 70513014Sciro.santilli@arm.com if (cpu > sys->numContexts()) 70613014Sciro.santilli@arm.com panic("Invalid CPU ID\n"); 70713014Sciro.santilli@arm.com return ULL(0x0101010101010101) << cpu; 70813014Sciro.santilli@arm.com} 70913014Sciro.santilli@arm.com 71013014Sciro.santilli@arm.comuint8_t 71113014Sciro.santilli@arm.comGicV2::getCpuPriority(unsigned cpu) 71213014Sciro.santilli@arm.com{ 71313014Sciro.santilli@arm.com // see Table 3-2 in IHI0048B.b (GICv2) 71413014Sciro.santilli@arm.com // mask some low-order priority bits per BPR value 71513014Sciro.santilli@arm.com // NB: the GIC prioritization scheme is upside down: 71613014Sciro.santilli@arm.com // lower values are higher priority; masking off bits 71713014Sciro.santilli@arm.com // actually creates a higher priority, not lower. 71813014Sciro.santilli@arm.com return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu])); 71913014Sciro.santilli@arm.com} 72013014Sciro.santilli@arm.com 72113014Sciro.santilli@arm.comvoid 72213014Sciro.santilli@arm.comGicV2::updateIntState(int hint) 72313014Sciro.santilli@arm.com{ 72413014Sciro.santilli@arm.com for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 72513014Sciro.santilli@arm.com if (!cpuEnabled[cpu]) 72613014Sciro.santilli@arm.com continue; 72713014Sciro.santilli@arm.com 72813014Sciro.santilli@arm.com /*@todo use hint to do less work. */ 72913014Sciro.santilli@arm.com int highest_int = SPURIOUS_INT; 73013014Sciro.santilli@arm.com // Priorities below that set in GICC_PMR can be ignored 73113014Sciro.santilli@arm.com uint8_t highest_pri = getCpuPriority(cpu); 73213014Sciro.santilli@arm.com 73313014Sciro.santilli@arm.com // Check SGIs 73413014Sciro.santilli@arm.com for (int swi = 0; swi < SGI_MAX; swi++) { 73513014Sciro.santilli@arm.com if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu]) 73613014Sciro.santilli@arm.com continue; 73713014Sciro.santilli@arm.com if ((cpuSgiPending[swi] & genSwiMask(cpu)) || 73813014Sciro.santilli@arm.com (cpuSgiPendingExt[cpu] & (1 << swi))) 73913014Sciro.santilli@arm.com if (highest_pri > getIntPriority(cpu, swi)) { 74013014Sciro.santilli@arm.com highest_pri = getIntPriority(cpu, swi); 74113014Sciro.santilli@arm.com highest_int = swi; 74213014Sciro.santilli@arm.com } 74313014Sciro.santilli@arm.com } 74413014Sciro.santilli@arm.com 74513014Sciro.santilli@arm.com // Check PPIs 74613014Sciro.santilli@arm.com if (cpuPpiPending[cpu]) { 74713105Sgiacomo.travaglini@arm.com for (int ppi_idx = 0, int_num = SGI_MAX; 74813105Sgiacomo.travaglini@arm.com int_num < PPI_MAX + SGI_MAX; 74913105Sgiacomo.travaglini@arm.com ppi_idx++, int_num++) { 75013105Sgiacomo.travaglini@arm.com 75113105Sgiacomo.travaglini@arm.com const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx); 75213105Sgiacomo.travaglini@arm.com const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num); 75313105Sgiacomo.travaglini@arm.com const bool higher_priority = 75413105Sgiacomo.travaglini@arm.com highest_pri > getIntPriority(cpu, int_num); 75513105Sgiacomo.travaglini@arm.com 75613105Sgiacomo.travaglini@arm.com if (ppi_pending && ppi_enabled && higher_priority) { 75713105Sgiacomo.travaglini@arm.com highest_pri = getIntPriority(cpu, int_num); 75813105Sgiacomo.travaglini@arm.com highest_int = int_num; 75913014Sciro.santilli@arm.com } 76013014Sciro.santilli@arm.com } 76113014Sciro.santilli@arm.com } 76213014Sciro.santilli@arm.com 76313014Sciro.santilli@arm.com bool mp_sys = sys->numRunningContexts() > 1; 76413014Sciro.santilli@arm.com // Check other ints 76513014Sciro.santilli@arm.com for (int x = 0; x < (itLines/INT_BITS_MAX); x++) { 76613014Sciro.santilli@arm.com if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) { 76713014Sciro.santilli@arm.com for (int y = 0; y < INT_BITS_MAX; y++) { 76813014Sciro.santilli@arm.com uint32_t int_nm = x * INT_BITS_MAX + y; 76913014Sciro.santilli@arm.com DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm); 77013014Sciro.santilli@arm.com /* Set current pending int as highest int for current cpu 77113014Sciro.santilli@arm.com if the interrupt's priority higher than current priority 77213014Sciro.santilli@arm.com and if current cpu is the target (for mp configs only) 77313014Sciro.santilli@arm.com */ 77413014Sciro.santilli@arm.com if ((bits(getIntEnabled(cpu, x), y) 77513014Sciro.santilli@arm.com &bits(getPendingInt(cpu, x), y)) && 77613014Sciro.santilli@arm.com (getIntPriority(cpu, int_nm) < highest_pri)) 77713014Sciro.santilli@arm.com if ((!mp_sys) || 77813014Sciro.santilli@arm.com (gem5ExtensionsEnabled 77913014Sciro.santilli@arm.com ? (getCpuTarget(cpu, int_nm) == cpu) 78013014Sciro.santilli@arm.com : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) { 78113014Sciro.santilli@arm.com highest_pri = getIntPriority(cpu, int_nm); 78213014Sciro.santilli@arm.com highest_int = int_nm; 78313014Sciro.santilli@arm.com } 78413014Sciro.santilli@arm.com } 78513014Sciro.santilli@arm.com } 78613014Sciro.santilli@arm.com } 78713014Sciro.santilli@arm.com 78813108Sadrien.pesle@arm.com uint32_t prev_highest = cpuHighestInt[cpu]; 78913014Sciro.santilli@arm.com cpuHighestInt[cpu] = highest_int; 79013014Sciro.santilli@arm.com 79113108Sadrien.pesle@arm.com if (highest_int == SPURIOUS_INT) { 79213108Sadrien.pesle@arm.com if (isLevelSensitive(cpu, prev_highest)) { 79313108Sadrien.pesle@arm.com 79413108Sadrien.pesle@arm.com DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu); 79513108Sadrien.pesle@arm.com platform->intrctrl->clear(cpu, ArmISA::INT_IRQ, 0); 79613108Sadrien.pesle@arm.com } 79713014Sciro.santilli@arm.com continue; 79813108Sadrien.pesle@arm.com } 79913014Sciro.santilli@arm.com 80013014Sciro.santilli@arm.com /* @todo make this work for more than one cpu, need to handle 1:N, N:N 80113014Sciro.santilli@arm.com * models */ 80213014Sciro.santilli@arm.com if (enabled && cpuEnabled[cpu] && 80313014Sciro.santilli@arm.com (highest_pri < getCpuPriority(cpu)) && 80413014Sciro.santilli@arm.com !(getActiveInt(cpu, intNumToWord(highest_int)) 80513014Sciro.santilli@arm.com & (1 << intNumToBit(highest_int)))) { 80613014Sciro.santilli@arm.com 80713014Sciro.santilli@arm.com DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int, 80813014Sciro.santilli@arm.com cpu); 80913014Sciro.santilli@arm.com postInt(cpu, curTick() + intLatency); 81013014Sciro.santilli@arm.com } 81113014Sciro.santilli@arm.com } 81213014Sciro.santilli@arm.com} 81313014Sciro.santilli@arm.com 81413014Sciro.santilli@arm.comvoid 81513014Sciro.santilli@arm.comGicV2::updateRunPri() 81613014Sciro.santilli@arm.com{ 81713014Sciro.santilli@arm.com for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 81813014Sciro.santilli@arm.com if (!cpuEnabled[cpu]) 81913014Sciro.santilli@arm.com continue; 82013014Sciro.santilli@arm.com uint8_t maxPriority = 0xff; 82113014Sciro.santilli@arm.com for (int i = 0; i < itLines; i++) { 82213014Sciro.santilli@arm.com if (i < SGI_MAX) { 82313014Sciro.santilli@arm.com if (((cpuSgiActive[i] & genSwiMask(cpu)) || 82413014Sciro.santilli@arm.com (cpuSgiActiveExt[cpu] & (1 << i))) && 82513014Sciro.santilli@arm.com (getIntPriority(cpu, i) < maxPriority)) 82613014Sciro.santilli@arm.com maxPriority = getIntPriority(cpu, i); 82713014Sciro.santilli@arm.com } else if (i < (SGI_MAX + PPI_MAX)) { 82813014Sciro.santilli@arm.com if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) && 82913014Sciro.santilli@arm.com (getIntPriority(cpu, i) < maxPriority)) 83013014Sciro.santilli@arm.com maxPriority = getIntPriority(cpu, i); 83113014Sciro.santilli@arm.com 83213014Sciro.santilli@arm.com } else { 83313014Sciro.santilli@arm.com if (getActiveInt(cpu, intNumToWord(i)) 83413014Sciro.santilli@arm.com & (1 << intNumToBit(i))) 83513014Sciro.santilli@arm.com if (getIntPriority(cpu, i) < maxPriority) 83613014Sciro.santilli@arm.com maxPriority = getIntPriority(cpu, i); 83713014Sciro.santilli@arm.com } 83813014Sciro.santilli@arm.com } 83913014Sciro.santilli@arm.com iccrpr[cpu] = maxPriority; 84013014Sciro.santilli@arm.com } 84113014Sciro.santilli@arm.com} 84213014Sciro.santilli@arm.com 84313014Sciro.santilli@arm.comvoid 84413014Sciro.santilli@arm.comGicV2::sendInt(uint32_t num) 84513014Sciro.santilli@arm.com{ 84613014Sciro.santilli@arm.com uint8_t target = getCpuTarget(0, num); 84713014Sciro.santilli@arm.com DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n", 84813014Sciro.santilli@arm.com num, target); 84913014Sciro.santilli@arm.com if ((target & (target - 1)) && !gem5ExtensionsEnabled) 85013014Sciro.santilli@arm.com panic("Multiple targets for peripheral interrupts is not supported\n"); 85113014Sciro.santilli@arm.com panic_if(num < SGI_MAX + PPI_MAX, 85213014Sciro.santilli@arm.com "sentInt() must only be used for interrupts 32 and higher"); 85313014Sciro.santilli@arm.com getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num); 85413014Sciro.santilli@arm.com updateIntState(intNumToWord(num)); 85513014Sciro.santilli@arm.com} 85613014Sciro.santilli@arm.com 85713014Sciro.santilli@arm.comvoid 85813014Sciro.santilli@arm.comGicV2::sendPPInt(uint32_t num, uint32_t cpu) 85913014Sciro.santilli@arm.com{ 86013014Sciro.santilli@arm.com DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n", 86113014Sciro.santilli@arm.com num, cpu); 86213014Sciro.santilli@arm.com cpuPpiPending[cpu] |= 1 << (num - SGI_MAX); 86313014Sciro.santilli@arm.com updateIntState(intNumToWord(num)); 86413014Sciro.santilli@arm.com} 86513014Sciro.santilli@arm.com 86613014Sciro.santilli@arm.comvoid 86713108Sadrien.pesle@arm.comGicV2::clearInt(uint32_t num) 86813014Sciro.santilli@arm.com{ 86913108Sadrien.pesle@arm.com if (isLevelSensitive(0, num)) { 87013108Sadrien.pesle@arm.com uint8_t target = getCpuTarget(0, num); 87113108Sadrien.pesle@arm.com 87213108Sadrien.pesle@arm.com DPRINTF(Interrupt, 87313108Sadrien.pesle@arm.com "Received Clear interrupt number %d, cpuTarget %#x:\n", 87413108Sadrien.pesle@arm.com num, target); 87513108Sadrien.pesle@arm.com 87613108Sadrien.pesle@arm.com getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num)); 87713108Sadrien.pesle@arm.com updateIntState(intNumToWord(num)); 87813108Sadrien.pesle@arm.com } else { 87913108Sadrien.pesle@arm.com /* Nothing to do : 88013108Sadrien.pesle@arm.com * Edge-triggered interrupt remain pending until software 88113108Sadrien.pesle@arm.com * writes GICD_ICPENDR or reads GICC_IAR */ 88213108Sadrien.pesle@arm.com } 88313014Sciro.santilli@arm.com} 88413014Sciro.santilli@arm.com 88513014Sciro.santilli@arm.comvoid 88613014Sciro.santilli@arm.comGicV2::clearPPInt(uint32_t num, uint32_t cpu) 88713014Sciro.santilli@arm.com{ 88813014Sciro.santilli@arm.com DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n", 88913014Sciro.santilli@arm.com num, cpu); 89013014Sciro.santilli@arm.com cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX)); 89113014Sciro.santilli@arm.com updateIntState(intNumToWord(num)); 89213014Sciro.santilli@arm.com} 89313014Sciro.santilli@arm.com 89413014Sciro.santilli@arm.comvoid 89513014Sciro.santilli@arm.comGicV2::postInt(uint32_t cpu, Tick when) 89613014Sciro.santilli@arm.com{ 89713014Sciro.santilli@arm.com if (!(postIntEvent[cpu]->scheduled())) { 89813014Sciro.santilli@arm.com ++pendingDelayedInterrupts; 89913014Sciro.santilli@arm.com eventq->schedule(postIntEvent[cpu], when); 90013014Sciro.santilli@arm.com } 90113014Sciro.santilli@arm.com} 90213014Sciro.santilli@arm.com 90313014Sciro.santilli@arm.comvoid 90413014Sciro.santilli@arm.comGicV2::postDelayedInt(uint32_t cpu) 90513014Sciro.santilli@arm.com{ 90613014Sciro.santilli@arm.com platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0); 90713014Sciro.santilli@arm.com --pendingDelayedInterrupts; 90813014Sciro.santilli@arm.com assert(pendingDelayedInterrupts >= 0); 90913014Sciro.santilli@arm.com if (pendingDelayedInterrupts == 0) 91013014Sciro.santilli@arm.com signalDrainDone(); 91113014Sciro.santilli@arm.com} 91213014Sciro.santilli@arm.com 91313014Sciro.santilli@arm.comDrainState 91413014Sciro.santilli@arm.comGicV2::drain() 91513014Sciro.santilli@arm.com{ 91613014Sciro.santilli@arm.com if (pendingDelayedInterrupts == 0) { 91713014Sciro.santilli@arm.com return DrainState::Drained; 91813014Sciro.santilli@arm.com } else { 91913014Sciro.santilli@arm.com return DrainState::Draining; 92013014Sciro.santilli@arm.com } 92113014Sciro.santilli@arm.com} 92213014Sciro.santilli@arm.com 92313014Sciro.santilli@arm.com 92413014Sciro.santilli@arm.comvoid 92513014Sciro.santilli@arm.comGicV2::drainResume() 92613014Sciro.santilli@arm.com{ 92713014Sciro.santilli@arm.com // There may be pending interrupts if checkpointed from Kvm; post them. 92813014Sciro.santilli@arm.com updateIntState(-1); 92913014Sciro.santilli@arm.com} 93013014Sciro.santilli@arm.com 93113014Sciro.santilli@arm.comvoid 93213014Sciro.santilli@arm.comGicV2::serialize(CheckpointOut &cp) const 93313014Sciro.santilli@arm.com{ 93413014Sciro.santilli@arm.com DPRINTF(Checkpoint, "Serializing Arm GIC\n"); 93513014Sciro.santilli@arm.com 93613014Sciro.santilli@arm.com SERIALIZE_SCALAR(enabled); 93713014Sciro.santilli@arm.com SERIALIZE_SCALAR(itLines); 93813014Sciro.santilli@arm.com SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 93913014Sciro.santilli@arm.com SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 94013014Sciro.santilli@arm.com SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 94113014Sciro.santilli@arm.com SERIALIZE_ARRAY(iccrpr, CPU_MAX); 94213014Sciro.santilli@arm.com SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 94313014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 94413014Sciro.santilli@arm.com SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 94513014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuEnabled, CPU_MAX); 94613014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuPriority, CPU_MAX); 94713014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuBpr, CPU_MAX); 94813014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 94913014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 95013014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 95113014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 95213014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 95313014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 95413014Sciro.santilli@arm.com SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 95513014Sciro.santilli@arm.com SERIALIZE_SCALAR(gem5ExtensionsEnabled); 95613014Sciro.santilli@arm.com 95713014Sciro.santilli@arm.com for (uint32_t i=0; i < bankedRegs.size(); ++i) { 95813014Sciro.santilli@arm.com if (!bankedRegs[i]) 95913014Sciro.santilli@arm.com continue; 96013014Sciro.santilli@arm.com bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i)); 96113014Sciro.santilli@arm.com } 96213014Sciro.santilli@arm.com} 96313014Sciro.santilli@arm.com 96413014Sciro.santilli@arm.comvoid 96513014Sciro.santilli@arm.comGicV2::BankedRegs::serialize(CheckpointOut &cp) const 96613014Sciro.santilli@arm.com{ 96713014Sciro.santilli@arm.com SERIALIZE_SCALAR(intEnabled); 96813014Sciro.santilli@arm.com SERIALIZE_SCALAR(pendingInt); 96913014Sciro.santilli@arm.com SERIALIZE_SCALAR(activeInt); 97013014Sciro.santilli@arm.com SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 97113014Sciro.santilli@arm.com} 97213014Sciro.santilli@arm.com 97313014Sciro.santilli@arm.comvoid 97413014Sciro.santilli@arm.comGicV2::unserialize(CheckpointIn &cp) 97513014Sciro.santilli@arm.com{ 97613014Sciro.santilli@arm.com DPRINTF(Checkpoint, "Unserializing Arm GIC\n"); 97713014Sciro.santilli@arm.com 97813014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(enabled); 97913014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(itLines); 98013014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 98113014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 98213014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 98313014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(iccrpr, CPU_MAX); 98413014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 98513014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 98613014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 98713014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuEnabled, CPU_MAX); 98813014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX); 98913014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX); 99013014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 99113014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 99213014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 99313014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 99413014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 99513014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 99613014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 99713014Sciro.santilli@arm.com 99813014Sciro.santilli@arm.com // Handle checkpoints from before we drained the GIC to prevent 99913014Sciro.santilli@arm.com // in-flight interrupts. 100013014Sciro.santilli@arm.com if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) { 100113014Sciro.santilli@arm.com Tick interrupt_time[CPU_MAX]; 100213014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX); 100313014Sciro.santilli@arm.com 100413014Sciro.santilli@arm.com for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) { 100513014Sciro.santilli@arm.com if (interrupt_time[cpu]) 100613014Sciro.santilli@arm.com schedule(postIntEvent[cpu], interrupt_time[cpu]); 100713014Sciro.santilli@arm.com } 100813014Sciro.santilli@arm.com } 100913014Sciro.santilli@arm.com 101013014Sciro.santilli@arm.com if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled)) 101113014Sciro.santilli@arm.com gem5ExtensionsEnabled = false; 101213014Sciro.santilli@arm.com 101313014Sciro.santilli@arm.com for (uint32_t i=0; i < CPU_MAX; ++i) { 101413014Sciro.santilli@arm.com ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i)); 101513014Sciro.santilli@arm.com if (cp.sectionExists(Serializable::currentSection())) { 101613014Sciro.santilli@arm.com getBankedRegs(i).unserialize(cp); 101713014Sciro.santilli@arm.com } 101813014Sciro.santilli@arm.com } 101913014Sciro.santilli@arm.com} 102013014Sciro.santilli@arm.com 102113014Sciro.santilli@arm.comvoid 102213014Sciro.santilli@arm.comGicV2::BankedRegs::unserialize(CheckpointIn &cp) 102313014Sciro.santilli@arm.com{ 102413014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(intEnabled); 102513014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(pendingInt); 102613014Sciro.santilli@arm.com UNSERIALIZE_SCALAR(activeInt); 102713014Sciro.santilli@arm.com UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 102813014Sciro.santilli@arm.com} 102913014Sciro.santilli@arm.com 103013014Sciro.santilli@arm.comGicV2 * 103113014Sciro.santilli@arm.comGicV2Params::create() 103213014Sciro.santilli@arm.com{ 103313014Sciro.santilli@arm.com return new GicV2(this); 103413014Sciro.santilli@arm.com} 1035