pmu.cc revision 12973
110461SAndreas.Sandberg@ARM.com/* 212973Sandreas.sandberg@arm.com * Copyright (c) 2011-2014, 2017-2018 ARM Limited 310461SAndreas.Sandberg@ARM.com * All rights reserved 410461SAndreas.Sandberg@ARM.com * 510461SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 610461SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 710461SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 810461SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 910461SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 1010461SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 1110461SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 1210461SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 1310461SAndreas.Sandberg@ARM.com * 1410461SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 1510461SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 1610461SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 1710461SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 1810461SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 1910461SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 2010461SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 2110461SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 2210461SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 2310461SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 2410461SAndreas.Sandberg@ARM.com * 2510461SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610461SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710461SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810461SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910461SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010461SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110461SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210461SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310461SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410461SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510461SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610461SAndreas.Sandberg@ARM.com * 3710461SAndreas.Sandberg@ARM.com * Authors: Dam Sunwoo 3810461SAndreas.Sandberg@ARM.com * Matt Horsnell 3910461SAndreas.Sandberg@ARM.com * Andreas Sandberg 4012286Sjose.marinho@arm.com * Jose Marinho 4110461SAndreas.Sandberg@ARM.com */ 4210461SAndreas.Sandberg@ARM.com 4310461SAndreas.Sandberg@ARM.com#include "arch/arm/pmu.hh" 4410461SAndreas.Sandberg@ARM.com 4510609Sandreas.sandberg@arm.com#include "arch/arm/isa.hh" 4610609Sandreas.sandberg@arm.com#include "arch/arm/utility.hh" 4710461SAndreas.Sandberg@ARM.com#include "base/trace.hh" 4810461SAndreas.Sandberg@ARM.com#include "cpu/base.hh" 4910461SAndreas.Sandberg@ARM.com#include "debug/Checkpoint.hh" 5010461SAndreas.Sandberg@ARM.com#include "debug/PMUVerbose.hh" 5110461SAndreas.Sandberg@ARM.com#include "dev/arm/base_gic.hh" 5212286Sjose.marinho@arm.com#include "dev/arm/generic_timer.hh" 5310461SAndreas.Sandberg@ARM.com#include "params/ArmPMU.hh" 5410461SAndreas.Sandberg@ARM.com 5510461SAndreas.Sandberg@ARM.comnamespace ArmISA { 5610461SAndreas.Sandberg@ARM.com 5710461SAndreas.Sandberg@ARM.comconst MiscReg PMU::reg_pmcr_wr_mask = 0x39; 5810461SAndreas.Sandberg@ARM.com 5910461SAndreas.Sandberg@ARM.comPMU::PMU(const ArmPMUParams *p) 6010461SAndreas.Sandberg@ARM.com : SimObject(p), BaseISADevice(), 6110461SAndreas.Sandberg@ARM.com reg_pmcnten(0), reg_pmcr(0), 6210461SAndreas.Sandberg@ARM.com reg_pmselr(0), reg_pminten(0), reg_pmovsr(0), 6312117Sjose.marinho@arm.com reg_pmceid0(0),reg_pmceid1(0), 6410461SAndreas.Sandberg@ARM.com clock_remainder(0), 6512286Sjose.marinho@arm.com maximumCounterCount(p->eventCounters), 6612286Sjose.marinho@arm.com cycleCounter(*this, maximumCounterCount), 6712286Sjose.marinho@arm.com cycleCounterEventId(p->cycleEventId), 6812286Sjose.marinho@arm.com swIncrementEvent(nullptr), 6910461SAndreas.Sandberg@ARM.com reg_pmcr_conf(0), 7012973Sandreas.sandberg@arm.com interrupt(p->interrupt) 7110461SAndreas.Sandberg@ARM.com{ 7210461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "Initializing the PMU.\n"); 7310461SAndreas.Sandberg@ARM.com 7412286Sjose.marinho@arm.com if (maximumCounterCount > 31) { 7510461SAndreas.Sandberg@ARM.com fatal("The PMU can only accept 31 counters, %d counters requested.\n", 7612286Sjose.marinho@arm.com maximumCounterCount); 7710461SAndreas.Sandberg@ARM.com } 7810461SAndreas.Sandberg@ARM.com 7912973Sandreas.sandberg@arm.com warn_if(!interrupt, "ARM PMU: No interrupt specified, interrupt " \ 8012973Sandreas.sandberg@arm.com "delivery disabled.\n"); 8112973Sandreas.sandberg@arm.com 8210461SAndreas.Sandberg@ARM.com /* Setup the performance counter ID registers */ 8310461SAndreas.Sandberg@ARM.com reg_pmcr_conf.imp = 0x41; // ARM Ltd. 8410461SAndreas.Sandberg@ARM.com reg_pmcr_conf.idcode = 0x00; 8510461SAndreas.Sandberg@ARM.com reg_pmcr_conf.n = p->eventCounters; 8610461SAndreas.Sandberg@ARM.com 8710461SAndreas.Sandberg@ARM.com // Setup the hard-coded cycle counter, which is equivalent to 8810461SAndreas.Sandberg@ARM.com // architected counter event type 0x11. 8910461SAndreas.Sandberg@ARM.com cycleCounter.eventId = 0x11; 9010461SAndreas.Sandberg@ARM.com} 9110461SAndreas.Sandberg@ARM.com 9210461SAndreas.Sandberg@ARM.comPMU::~PMU() 9310461SAndreas.Sandberg@ARM.com{ 9410461SAndreas.Sandberg@ARM.com} 9510461SAndreas.Sandberg@ARM.com 9610461SAndreas.Sandberg@ARM.comvoid 9712973Sandreas.sandberg@arm.comPMU::setThreadContext(ThreadContext *tc) 9812973Sandreas.sandberg@arm.com{ 9912973Sandreas.sandberg@arm.com DPRINTF(PMUVerbose, "Assigning PMU to ContextID %i.\n", tc->contextId()); 10012973Sandreas.sandberg@arm.com if (interrupt) 10112973Sandreas.sandberg@arm.com interrupt->setThreadContext(tc); 10212973Sandreas.sandberg@arm.com} 10312973Sandreas.sandberg@arm.com 10412973Sandreas.sandberg@arm.comvoid 10512286Sjose.marinho@arm.comPMU::addSoftwareIncrementEvent(unsigned int id) 10612286Sjose.marinho@arm.com{ 10712286Sjose.marinho@arm.com auto old_event = eventMap.find(id); 10812286Sjose.marinho@arm.com DPRINTF(PMUVerbose, "PMU: Adding SW increment event with id '0x%x'\n", id); 10912286Sjose.marinho@arm.com 11012286Sjose.marinho@arm.com if (swIncrementEvent) { 11112286Sjose.marinho@arm.com fatal_if(old_event == eventMap.end() || 11212286Sjose.marinho@arm.com old_event->second != swIncrementEvent, 11312286Sjose.marinho@arm.com "Trying to add a software increment event with multiple" 11412286Sjose.marinho@arm.com "IDs. This is not supported.\n"); 11512286Sjose.marinho@arm.com return; 11612286Sjose.marinho@arm.com } 11712286Sjose.marinho@arm.com 11812286Sjose.marinho@arm.com fatal_if(old_event != eventMap.end(), "An event with id %d has " 11912286Sjose.marinho@arm.com "been previously defined\n", id); 12012286Sjose.marinho@arm.com 12112286Sjose.marinho@arm.com swIncrementEvent = new SWIncrementEvent(); 12212286Sjose.marinho@arm.com eventMap[id] = swIncrementEvent; 12312286Sjose.marinho@arm.com registerEvent(id); 12412286Sjose.marinho@arm.com} 12512286Sjose.marinho@arm.com 12612286Sjose.marinho@arm.comvoid 12710461SAndreas.Sandberg@ARM.comPMU::addEventProbe(unsigned int id, SimObject *obj, const char *probe_name) 12810461SAndreas.Sandberg@ARM.com{ 12910461SAndreas.Sandberg@ARM.com 13012286Sjose.marinho@arm.com DPRINTF(PMUVerbose, "PMU: Adding Probe Driven event with id '0x%x'" 13112286Sjose.marinho@arm.com "as probe %s:%s\n",id, obj->name(), probe_name); 13212286Sjose.marinho@arm.com 13312286Sjose.marinho@arm.com RegularEvent *event = nullptr; 13412286Sjose.marinho@arm.com auto event_entry = eventMap.find(id); 13512286Sjose.marinho@arm.com if (event_entry == eventMap.end()) { 13612286Sjose.marinho@arm.com 13712286Sjose.marinho@arm.com event = new RegularEvent(); 13812286Sjose.marinho@arm.com eventMap[id] = event; 13912286Sjose.marinho@arm.com 14012286Sjose.marinho@arm.com } else { 14112286Sjose.marinho@arm.com event = dynamic_cast<RegularEvent*>(event_entry->second); 14212286Sjose.marinho@arm.com if (!event) { 14312286Sjose.marinho@arm.com fatal("Event with id %d is not probe driven\n", id); 14412286Sjose.marinho@arm.com } 14512286Sjose.marinho@arm.com } 14612286Sjose.marinho@arm.com event->addMicroarchitectureProbe(obj, probe_name); 14712286Sjose.marinho@arm.com 14812286Sjose.marinho@arm.com registerEvent(id); 14912286Sjose.marinho@arm.com 15012286Sjose.marinho@arm.com} 15112286Sjose.marinho@arm.com 15212286Sjose.marinho@arm.comvoid 15312286Sjose.marinho@arm.comPMU::registerEvent(uint32_t id) 15412286Sjose.marinho@arm.com{ 15512117Sjose.marinho@arm.com // Flag the event as available in the corresponding PMCEID register if it 15612117Sjose.marinho@arm.com // is an architected event. 15712117Sjose.marinho@arm.com if (id < 0x20) { 15812117Sjose.marinho@arm.com reg_pmceid0 |= ((uint64_t)1) << id; 15912117Sjose.marinho@arm.com } else if (id > 0x20 && id < 0x40) { 16012117Sjose.marinho@arm.com reg_pmceid1 |= ((uint64_t)1) << (id - 0x20); 16112117Sjose.marinho@arm.com } else if (id >= 0x4000 && id < 0x4020) { 16212117Sjose.marinho@arm.com reg_pmceid0 |= ((uint64_t)1) << (id - 0x4000 + 32); 16312117Sjose.marinho@arm.com } else if (id >= 0x4020 && id < 0x4040) { 16412117Sjose.marinho@arm.com reg_pmceid1 |= ((uint64_t)1) << (id - 0x4020 + 32); 16512117Sjose.marinho@arm.com } 16610461SAndreas.Sandberg@ARM.com} 16710461SAndreas.Sandberg@ARM.com 16810461SAndreas.Sandberg@ARM.comvoid 16910461SAndreas.Sandberg@ARM.comPMU::drainResume() 17010461SAndreas.Sandberg@ARM.com{ 17110461SAndreas.Sandberg@ARM.com // Re-attach enabled counters after a resume in case they changed. 17210461SAndreas.Sandberg@ARM.com updateAllCounters(); 17310461SAndreas.Sandberg@ARM.com} 17410461SAndreas.Sandberg@ARM.com 17510461SAndreas.Sandberg@ARM.comvoid 17612286Sjose.marinho@arm.comPMU::regProbeListeners() 17712286Sjose.marinho@arm.com{ 17812286Sjose.marinho@arm.com 17912286Sjose.marinho@arm.com // at this stage all probe configurations are done 18012286Sjose.marinho@arm.com // counters can be configured 18112286Sjose.marinho@arm.com for (uint32_t index = 0; index < maximumCounterCount-1; index++) { 18212286Sjose.marinho@arm.com counters.emplace_back(*this, index); 18312286Sjose.marinho@arm.com } 18412286Sjose.marinho@arm.com 18512286Sjose.marinho@arm.com PMUEvent *event = getEvent(cycleCounterEventId); 18612286Sjose.marinho@arm.com panic_if(!event, "core cycle event is not present\n"); 18712286Sjose.marinho@arm.com cycleCounter.enabled = true; 18812286Sjose.marinho@arm.com cycleCounter.attach(event); 18912286Sjose.marinho@arm.com} 19012286Sjose.marinho@arm.com 19112286Sjose.marinho@arm.comvoid 19210461SAndreas.Sandberg@ARM.comPMU::setMiscReg(int misc_reg, MiscReg val) 19310461SAndreas.Sandberg@ARM.com{ 19410461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "setMiscReg(%s, 0x%x)\n", 19510461SAndreas.Sandberg@ARM.com miscRegName[unflattenMiscReg(misc_reg)], val); 19610461SAndreas.Sandberg@ARM.com 19710461SAndreas.Sandberg@ARM.com switch (unflattenMiscReg(misc_reg)) { 19810461SAndreas.Sandberg@ARM.com case MISCREG_PMCR_EL0: 19910461SAndreas.Sandberg@ARM.com case MISCREG_PMCR: 20010461SAndreas.Sandberg@ARM.com setControlReg(val); 20110461SAndreas.Sandberg@ARM.com return; 20210461SAndreas.Sandberg@ARM.com 20310461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENSET_EL0: 20410461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENSET: 20510461SAndreas.Sandberg@ARM.com reg_pmcnten |= val; 20610461SAndreas.Sandberg@ARM.com updateAllCounters(); 20710461SAndreas.Sandberg@ARM.com return; 20810461SAndreas.Sandberg@ARM.com 20910461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENCLR_EL0: 21010461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENCLR: 21110461SAndreas.Sandberg@ARM.com reg_pmcnten &= ~val; 21210461SAndreas.Sandberg@ARM.com updateAllCounters(); 21310461SAndreas.Sandberg@ARM.com return; 21410461SAndreas.Sandberg@ARM.com 21510461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSCLR_EL0: 21610461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSR: 21710461SAndreas.Sandberg@ARM.com reg_pmovsr &= ~val; 21810461SAndreas.Sandberg@ARM.com return; 21910461SAndreas.Sandberg@ARM.com 22010461SAndreas.Sandberg@ARM.com case MISCREG_PMSWINC_EL0: 22110461SAndreas.Sandberg@ARM.com case MISCREG_PMSWINC: 22212286Sjose.marinho@arm.com if (swIncrementEvent) { 22312286Sjose.marinho@arm.com swIncrementEvent->write(val); 22410461SAndreas.Sandberg@ARM.com } 22512286Sjose.marinho@arm.com return; 22610461SAndreas.Sandberg@ARM.com 22710461SAndreas.Sandberg@ARM.com case MISCREG_PMCCNTR_EL0: 22810461SAndreas.Sandberg@ARM.com case MISCREG_PMCCNTR: 22912286Sjose.marinho@arm.com cycleCounter.setValue(val); 23010461SAndreas.Sandberg@ARM.com return; 23110461SAndreas.Sandberg@ARM.com 23210461SAndreas.Sandberg@ARM.com case MISCREG_PMSELR_EL0: 23310461SAndreas.Sandberg@ARM.com case MISCREG_PMSELR: 23410461SAndreas.Sandberg@ARM.com reg_pmselr = val; 23510461SAndreas.Sandberg@ARM.com return; 23612117Sjose.marinho@arm.com //TODO: implement MISCREF_PMCEID{2,3} 23710461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID0_EL0: 23810461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID0: 23910461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID1_EL0: 24010461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID1: 24110461SAndreas.Sandberg@ARM.com // Ignore writes 24210461SAndreas.Sandberg@ARM.com return; 24310461SAndreas.Sandberg@ARM.com 24410461SAndreas.Sandberg@ARM.com case MISCREG_PMEVTYPER0_EL0...MISCREG_PMEVTYPER5_EL0: 24512042Sandreas.sandberg@arm.com setCounterTypeRegister(misc_reg - MISCREG_PMEVTYPER0_EL0, val); 24610461SAndreas.Sandberg@ARM.com return; 24710461SAndreas.Sandberg@ARM.com 24810461SAndreas.Sandberg@ARM.com case MISCREG_PMCCFILTR: 24910461SAndreas.Sandberg@ARM.com case MISCREG_PMCCFILTR_EL0: 25010461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "Setting PMCCFILTR: 0x%x\n", val); 25110461SAndreas.Sandberg@ARM.com setCounterTypeRegister(PMCCNTR, val); 25210461SAndreas.Sandberg@ARM.com return; 25310461SAndreas.Sandberg@ARM.com 25410461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVTYPER_PMCCFILTR: 25510461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVTYPER_EL0: 25610461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVTYPER: 25710461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "Setting counter type: " 25810461SAndreas.Sandberg@ARM.com "[PMSELR: 0x%x, PMSELER.sel: 0x%x, EVTYPER: 0x%x]\n", 25910461SAndreas.Sandberg@ARM.com reg_pmselr, reg_pmselr.sel, val); 26010461SAndreas.Sandberg@ARM.com setCounterTypeRegister(reg_pmselr.sel, val); 26110461SAndreas.Sandberg@ARM.com return; 26210461SAndreas.Sandberg@ARM.com 26310461SAndreas.Sandberg@ARM.com case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0: 26410461SAndreas.Sandberg@ARM.com setCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0, val); 26510461SAndreas.Sandberg@ARM.com return; 26610461SAndreas.Sandberg@ARM.com 26710461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVCNTR_EL0: 26810461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVCNTR: 26910461SAndreas.Sandberg@ARM.com setCounterValue(reg_pmselr.sel, val); 27010461SAndreas.Sandberg@ARM.com return; 27110461SAndreas.Sandberg@ARM.com 27210461SAndreas.Sandberg@ARM.com case MISCREG_PMUSERENR_EL0: 27310461SAndreas.Sandberg@ARM.com case MISCREG_PMUSERENR: 27410461SAndreas.Sandberg@ARM.com // TODO 27510461SAndreas.Sandberg@ARM.com break; 27610461SAndreas.Sandberg@ARM.com 27710461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENSET_EL1: 27810461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENSET: 27910461SAndreas.Sandberg@ARM.com reg_pminten |= val; 28010461SAndreas.Sandberg@ARM.com return; 28110461SAndreas.Sandberg@ARM.com 28210461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENCLR_EL1: 28310461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENCLR: 28410461SAndreas.Sandberg@ARM.com reg_pminten &= ~val; 28510461SAndreas.Sandberg@ARM.com return; 28610461SAndreas.Sandberg@ARM.com 28710461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSSET_EL0: 28810461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSSET: 28910461SAndreas.Sandberg@ARM.com reg_pmovsr |= val; 29010461SAndreas.Sandberg@ARM.com return; 29110461SAndreas.Sandberg@ARM.com 29210461SAndreas.Sandberg@ARM.com default: 29310461SAndreas.Sandberg@ARM.com panic("Unexpected PMU register: %i\n", miscRegName[misc_reg]); 29410461SAndreas.Sandberg@ARM.com } 29510461SAndreas.Sandberg@ARM.com 29610461SAndreas.Sandberg@ARM.com warn("Not doing anything for write to miscreg %s\n", 29710461SAndreas.Sandberg@ARM.com miscRegName[misc_reg]); 29810461SAndreas.Sandberg@ARM.com} 29910461SAndreas.Sandberg@ARM.com 30010461SAndreas.Sandberg@ARM.comMiscReg 30110461SAndreas.Sandberg@ARM.comPMU::readMiscReg(int misc_reg) 30210461SAndreas.Sandberg@ARM.com{ 30310461SAndreas.Sandberg@ARM.com MiscReg val(readMiscRegInt(misc_reg)); 30410461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "readMiscReg(%s): 0x%x\n", 30510461SAndreas.Sandberg@ARM.com miscRegName[unflattenMiscReg(misc_reg)], val); 30610461SAndreas.Sandberg@ARM.com return val; 30710461SAndreas.Sandberg@ARM.com} 30810461SAndreas.Sandberg@ARM.com 30910461SAndreas.Sandberg@ARM.comMiscReg 31010461SAndreas.Sandberg@ARM.comPMU::readMiscRegInt(int misc_reg) 31110461SAndreas.Sandberg@ARM.com{ 31210461SAndreas.Sandberg@ARM.com misc_reg = unflattenMiscReg(misc_reg); 31310461SAndreas.Sandberg@ARM.com switch (misc_reg) { 31410461SAndreas.Sandberg@ARM.com case MISCREG_PMCR_EL0: 31510461SAndreas.Sandberg@ARM.com case MISCREG_PMCR: 31610461SAndreas.Sandberg@ARM.com return reg_pmcr_conf | (reg_pmcr & reg_pmcr_wr_mask); 31710461SAndreas.Sandberg@ARM.com 31810461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENSET_EL0: 31910461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENCLR_EL0: 32010461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENSET: 32110461SAndreas.Sandberg@ARM.com case MISCREG_PMCNTENCLR: 32210461SAndreas.Sandberg@ARM.com return reg_pmcnten; 32310461SAndreas.Sandberg@ARM.com 32410461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSCLR_EL0: 32510461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSSET_EL0: 32610461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSR: // Overflow Status Register 32710461SAndreas.Sandberg@ARM.com case MISCREG_PMOVSSET: 32810461SAndreas.Sandberg@ARM.com return reg_pmovsr; 32910461SAndreas.Sandberg@ARM.com 33010461SAndreas.Sandberg@ARM.com case MISCREG_PMSWINC_EL0: 33110461SAndreas.Sandberg@ARM.com case MISCREG_PMSWINC: // Software Increment Register (RAZ) 33210461SAndreas.Sandberg@ARM.com return 0; 33310461SAndreas.Sandberg@ARM.com 33410461SAndreas.Sandberg@ARM.com case MISCREG_PMSELR: 33510461SAndreas.Sandberg@ARM.com return reg_pmselr; 33610461SAndreas.Sandberg@ARM.com 33710461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID0_EL0: 33812117Sjose.marinho@arm.com return reg_pmceid0; 33910461SAndreas.Sandberg@ARM.com 34010461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID1_EL0: 34112117Sjose.marinho@arm.com return reg_pmceid1; 34212117Sjose.marinho@arm.com 34312117Sjose.marinho@arm.com //TODO: implement MISCREF_PMCEID{2,3} 34412117Sjose.marinho@arm.com case MISCREG_PMCEID0: // Common Event ID register 34512117Sjose.marinho@arm.com return reg_pmceid0 & 0xFFFFFFFF; 34612117Sjose.marinho@arm.com 34710461SAndreas.Sandberg@ARM.com case MISCREG_PMCEID1: // Common Event ID register 34812117Sjose.marinho@arm.com return reg_pmceid1 & 0xFFFFFFFF; 34910461SAndreas.Sandberg@ARM.com 35010461SAndreas.Sandberg@ARM.com case MISCREG_PMCCNTR_EL0: 35112286Sjose.marinho@arm.com return cycleCounter.getValue(); 35210461SAndreas.Sandberg@ARM.com 35310461SAndreas.Sandberg@ARM.com case MISCREG_PMCCNTR: 35412286Sjose.marinho@arm.com return cycleCounter.getValue() & 0xFFFFFFFF; 35510461SAndreas.Sandberg@ARM.com 35610461SAndreas.Sandberg@ARM.com case MISCREG_PMEVTYPER0_EL0...MISCREG_PMEVTYPER5_EL0: 35710461SAndreas.Sandberg@ARM.com return getCounterTypeRegister(misc_reg - MISCREG_PMEVTYPER0_EL0); 35810461SAndreas.Sandberg@ARM.com 35910461SAndreas.Sandberg@ARM.com case MISCREG_PMCCFILTR: 36010461SAndreas.Sandberg@ARM.com case MISCREG_PMCCFILTR_EL0: 36110461SAndreas.Sandberg@ARM.com return getCounterTypeRegister(PMCCNTR); 36210461SAndreas.Sandberg@ARM.com 36310461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVTYPER_PMCCFILTR: 36410461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVTYPER_EL0: 36510461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVTYPER: 36610461SAndreas.Sandberg@ARM.com return getCounterTypeRegister(reg_pmselr.sel); 36710461SAndreas.Sandberg@ARM.com 36812286Sjose.marinho@arm.com case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0: { 36912286Sjose.marinho@arm.com return getCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0) & 37012286Sjose.marinho@arm.com 0xFFFFFFFF; 37112286Sjose.marinho@arm.com 37212286Sjose.marinho@arm.com } 37310461SAndreas.Sandberg@ARM.com 37410461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVCNTR_EL0: 37510461SAndreas.Sandberg@ARM.com case MISCREG_PMXEVCNTR: 37610461SAndreas.Sandberg@ARM.com return getCounterValue(reg_pmselr.sel) & 0xFFFFFFFF; 37710461SAndreas.Sandberg@ARM.com 37810461SAndreas.Sandberg@ARM.com case MISCREG_PMUSERENR_EL0: 37910461SAndreas.Sandberg@ARM.com case MISCREG_PMUSERENR: 38010461SAndreas.Sandberg@ARM.com // TODO 38110461SAndreas.Sandberg@ARM.com return 0; 38210461SAndreas.Sandberg@ARM.com 38310461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENSET_EL1: 38410461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENCLR_EL1: 38510461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENSET: 38610461SAndreas.Sandberg@ARM.com case MISCREG_PMINTENCLR: 38710461SAndreas.Sandberg@ARM.com return reg_pminten; 38810461SAndreas.Sandberg@ARM.com 38910461SAndreas.Sandberg@ARM.com default: 39010461SAndreas.Sandberg@ARM.com panic("Unexpected PMU register: %i\n", miscRegName[misc_reg]); 39110461SAndreas.Sandberg@ARM.com } 39210461SAndreas.Sandberg@ARM.com 39310461SAndreas.Sandberg@ARM.com warn("Not doing anything for read from miscreg %s\n", 39410461SAndreas.Sandberg@ARM.com miscRegName[misc_reg]); 39510461SAndreas.Sandberg@ARM.com return 0; 39610461SAndreas.Sandberg@ARM.com} 39710461SAndreas.Sandberg@ARM.com 39810461SAndreas.Sandberg@ARM.comvoid 39910461SAndreas.Sandberg@ARM.comPMU::setControlReg(PMCR_t val) 40010461SAndreas.Sandberg@ARM.com{ 40110461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "Set Control Reg 0x%08x.\n", val); 40210461SAndreas.Sandberg@ARM.com 40310461SAndreas.Sandberg@ARM.com if (val.p) { 40410461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "PMU reset all events to zero.\n"); 40510461SAndreas.Sandberg@ARM.com resetEventCounts(); 40610461SAndreas.Sandberg@ARM.com } 40710461SAndreas.Sandberg@ARM.com 40810461SAndreas.Sandberg@ARM.com if (val.c) { 40910461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "PMU reset cycle counter to zero.\n"); 41012286Sjose.marinho@arm.com cycleCounter.setValue(0); 41110461SAndreas.Sandberg@ARM.com } 41210461SAndreas.Sandberg@ARM.com 41310461SAndreas.Sandberg@ARM.com // Reset the clock remainder if divide by 64-mode is toggled. 41410461SAndreas.Sandberg@ARM.com if (reg_pmcr.d != val.d) 41510461SAndreas.Sandberg@ARM.com clock_remainder = 0; 41610461SAndreas.Sandberg@ARM.com 41710461SAndreas.Sandberg@ARM.com reg_pmcr = val & reg_pmcr_wr_mask; 41810461SAndreas.Sandberg@ARM.com updateAllCounters(); 41910461SAndreas.Sandberg@ARM.com} 42010461SAndreas.Sandberg@ARM.com 42110461SAndreas.Sandberg@ARM.comvoid 42210461SAndreas.Sandberg@ARM.comPMU::updateAllCounters() 42310461SAndreas.Sandberg@ARM.com{ 42410461SAndreas.Sandberg@ARM.com const bool global_enable(reg_pmcr.e); 42510461SAndreas.Sandberg@ARM.com 42610461SAndreas.Sandberg@ARM.com for (int i = 0; i < counters.size(); ++i) { 42710461SAndreas.Sandberg@ARM.com CounterState &ctr(counters[i]); 42810461SAndreas.Sandberg@ARM.com const bool enable(global_enable && (reg_pmcnten & (1 << i))); 42910461SAndreas.Sandberg@ARM.com if (ctr.enabled != enable) { 43010461SAndreas.Sandberg@ARM.com ctr.enabled = enable; 43112286Sjose.marinho@arm.com updateCounter(ctr); 43210461SAndreas.Sandberg@ARM.com } 43310461SAndreas.Sandberg@ARM.com } 43410461SAndreas.Sandberg@ARM.com 43510461SAndreas.Sandberg@ARM.com const bool ccntr_enable(global_enable && (reg_pmcnten & (1 << PMCCNTR))); 43610461SAndreas.Sandberg@ARM.com if (cycleCounter.enabled != ccntr_enable) { 43710461SAndreas.Sandberg@ARM.com cycleCounter.enabled = ccntr_enable; 43812286Sjose.marinho@arm.com updateCounter(cycleCounter); 43910461SAndreas.Sandberg@ARM.com } 44010461SAndreas.Sandberg@ARM.com} 44110461SAndreas.Sandberg@ARM.com 44212286Sjose.marinho@arm.comvoid 44312286Sjose.marinho@arm.comPMU::PMUEvent::attachEvent(PMU::CounterState *user) 44412286Sjose.marinho@arm.com{ 44512286Sjose.marinho@arm.com if (userCounters.empty()) { 44612286Sjose.marinho@arm.com enable(); 44712286Sjose.marinho@arm.com } 44812286Sjose.marinho@arm.com userCounters.insert(user); 44912286Sjose.marinho@arm.com updateAttachedCounters(); 45012286Sjose.marinho@arm.com} 45112286Sjose.marinho@arm.com 45212286Sjose.marinho@arm.comvoid 45312286Sjose.marinho@arm.comPMU::PMUEvent::increment(const uint64_t val) 45412286Sjose.marinho@arm.com{ 45512286Sjose.marinho@arm.com for (auto& counter: userCounters) { 45612286Sjose.marinho@arm.com counter->add(val); 45712286Sjose.marinho@arm.com } 45812286Sjose.marinho@arm.com} 45912286Sjose.marinho@arm.com 46012286Sjose.marinho@arm.comvoid 46112286Sjose.marinho@arm.comPMU::PMUEvent::detachEvent(PMU::CounterState *user) 46212286Sjose.marinho@arm.com{ 46312286Sjose.marinho@arm.com userCounters.erase(user); 46412286Sjose.marinho@arm.com 46512286Sjose.marinho@arm.com if (userCounters.empty()) { 46612286Sjose.marinho@arm.com disable(); 46712286Sjose.marinho@arm.com } 46812286Sjose.marinho@arm.com} 46912286Sjose.marinho@arm.com 47012286Sjose.marinho@arm.comvoid 47112286Sjose.marinho@arm.comPMU::RegularEvent::RegularProbe::notify(const uint64_t &val) 47212286Sjose.marinho@arm.com{ 47312286Sjose.marinho@arm.com parentEvent->increment(val); 47412286Sjose.marinho@arm.com} 47512286Sjose.marinho@arm.com 47612286Sjose.marinho@arm.comvoid 47712286Sjose.marinho@arm.comPMU::RegularEvent::enable() 47812286Sjose.marinho@arm.com{ 47912286Sjose.marinho@arm.com for (auto& subEvents: microArchitectureEventSet) { 48012286Sjose.marinho@arm.com attachedProbePointList.emplace_back( 48112286Sjose.marinho@arm.com new RegularProbe(this, subEvents.first, subEvents.second)); 48212286Sjose.marinho@arm.com } 48312286Sjose.marinho@arm.com} 48412286Sjose.marinho@arm.com 48512286Sjose.marinho@arm.comvoid 48612286Sjose.marinho@arm.comPMU::RegularEvent::disable() 48712286Sjose.marinho@arm.com{ 48812286Sjose.marinho@arm.com attachedProbePointList.clear(); 48912286Sjose.marinho@arm.com} 49012286Sjose.marinho@arm.com 49110609Sandreas.sandberg@arm.combool 49212286Sjose.marinho@arm.comPMU::CounterState::isFiltered() const 49310609Sandreas.sandberg@arm.com{ 49412286Sjose.marinho@arm.com assert(pmu.isa); 49510609Sandreas.sandberg@arm.com 49612286Sjose.marinho@arm.com const PMEVTYPER_t filter(this->filter); 49712286Sjose.marinho@arm.com const SCR scr(pmu.isa->readMiscRegNoEffect(MISCREG_SCR)); 49812286Sjose.marinho@arm.com const CPSR cpsr(pmu.isa->readMiscRegNoEffect(MISCREG_CPSR)); 49910609Sandreas.sandberg@arm.com const ExceptionLevel el(opModeToEL((OperatingMode)(uint8_t)cpsr.mode)); 50010609Sandreas.sandberg@arm.com const bool secure(inSecureState(scr, cpsr)); 50110609Sandreas.sandberg@arm.com 50210609Sandreas.sandberg@arm.com switch (el) { 50310609Sandreas.sandberg@arm.com case EL0: 50410609Sandreas.sandberg@arm.com return secure ? filter.u : (filter.u != filter.nsu); 50510609Sandreas.sandberg@arm.com 50610609Sandreas.sandberg@arm.com case EL1: 50710609Sandreas.sandberg@arm.com return secure ? filter.p : (filter.p != filter.nsk); 50810609Sandreas.sandberg@arm.com 50910609Sandreas.sandberg@arm.com case EL2: 51010609Sandreas.sandberg@arm.com return !filter.nsh; 51110609Sandreas.sandberg@arm.com 51210609Sandreas.sandberg@arm.com case EL3: 51310609Sandreas.sandberg@arm.com return filter.p != filter.m; 51410609Sandreas.sandberg@arm.com 51510609Sandreas.sandberg@arm.com default: 51610609Sandreas.sandberg@arm.com panic("Unexpected execution level in PMU::isFiltered.\n"); 51710609Sandreas.sandberg@arm.com } 51810609Sandreas.sandberg@arm.com} 51910609Sandreas.sandberg@arm.com 52010461SAndreas.Sandberg@ARM.comvoid 52112286Sjose.marinho@arm.comPMU::CounterState::detach() 52210461SAndreas.Sandberg@ARM.com{ 52312286Sjose.marinho@arm.com if (sourceEvent) { 52412286Sjose.marinho@arm.com sourceEvent->detachEvent(this); 52512286Sjose.marinho@arm.com sourceEvent = nullptr; 52612286Sjose.marinho@arm.com } else { 52712286Sjose.marinho@arm.com debugCounter("detaching event not currently attached" 52812286Sjose.marinho@arm.com " to any event\n"); 52910461SAndreas.Sandberg@ARM.com } 53010461SAndreas.Sandberg@ARM.com} 53110461SAndreas.Sandberg@ARM.com 53210461SAndreas.Sandberg@ARM.comvoid 53312286Sjose.marinho@arm.comPMU::CounterState::attach(PMUEvent* event) 53412286Sjose.marinho@arm.com{ 53512286Sjose.marinho@arm.com value = 0; 53612286Sjose.marinho@arm.com sourceEvent = event; 53712286Sjose.marinho@arm.com sourceEvent->attachEvent(this); 53812286Sjose.marinho@arm.com} 53912286Sjose.marinho@arm.com 54012286Sjose.marinho@arm.comuint64_t 54112286Sjose.marinho@arm.comPMU::CounterState::getValue() const 54212286Sjose.marinho@arm.com{ 54312286Sjose.marinho@arm.com if (sourceEvent) { 54412286Sjose.marinho@arm.com sourceEvent->updateAttachedCounters(); 54512286Sjose.marinho@arm.com } else { 54612286Sjose.marinho@arm.com debugCounter("attempted to get value from a counter without" 54712286Sjose.marinho@arm.com " an associated event\n"); 54812286Sjose.marinho@arm.com } 54912286Sjose.marinho@arm.com return value; 55012286Sjose.marinho@arm.com} 55112286Sjose.marinho@arm.com 55212286Sjose.marinho@arm.comvoid 55312286Sjose.marinho@arm.comPMU::CounterState::setValue(uint64_t val) 55412286Sjose.marinho@arm.com{ 55512286Sjose.marinho@arm.com value = val; 55612286Sjose.marinho@arm.com resetValue = true; 55712286Sjose.marinho@arm.com 55812286Sjose.marinho@arm.com if (sourceEvent) { 55912286Sjose.marinho@arm.com sourceEvent->updateAttachedCounters(); 56012286Sjose.marinho@arm.com } else { 56112286Sjose.marinho@arm.com debugCounter("attempted to set value from a counter without" 56212286Sjose.marinho@arm.com " an associated event\n"); 56312286Sjose.marinho@arm.com } 56412286Sjose.marinho@arm.com} 56512286Sjose.marinho@arm.com 56612286Sjose.marinho@arm.comvoid 56712286Sjose.marinho@arm.comPMU::updateCounter(CounterState &ctr) 56810461SAndreas.Sandberg@ARM.com{ 56910461SAndreas.Sandberg@ARM.com if (!ctr.enabled) { 57012286Sjose.marinho@arm.com DPRINTF(PMUVerbose, "updateCounter(%i): Disabling counter\n", 57112286Sjose.marinho@arm.com ctr.getCounterId()); 57212286Sjose.marinho@arm.com ctr.detach(); 57312286Sjose.marinho@arm.com 57410461SAndreas.Sandberg@ARM.com } else { 57510461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "updateCounter(%i): Enable event id 0x%x\n", 57612286Sjose.marinho@arm.com ctr.getCounterId(), ctr.eventId); 57710461SAndreas.Sandberg@ARM.com 57812286Sjose.marinho@arm.com auto sourceEvent = eventMap.find(ctr.eventId); 57912286Sjose.marinho@arm.com if (sourceEvent == eventMap.end()) { 58010461SAndreas.Sandberg@ARM.com warn("Can't enable PMU counter of type '0x%x': " 58110461SAndreas.Sandberg@ARM.com "No such event type.\n", ctr.eventId); 58212286Sjose.marinho@arm.com } else { 58312286Sjose.marinho@arm.com ctr.attach(sourceEvent->second); 58410461SAndreas.Sandberg@ARM.com } 58510461SAndreas.Sandberg@ARM.com } 58610461SAndreas.Sandberg@ARM.com} 58710461SAndreas.Sandberg@ARM.com 58810461SAndreas.Sandberg@ARM.com 58910461SAndreas.Sandberg@ARM.comvoid 59010461SAndreas.Sandberg@ARM.comPMU::resetEventCounts() 59110461SAndreas.Sandberg@ARM.com{ 59210461SAndreas.Sandberg@ARM.com for (CounterState &ctr : counters) 59312286Sjose.marinho@arm.com ctr.setValue(0); 59410461SAndreas.Sandberg@ARM.com} 59510461SAndreas.Sandberg@ARM.com 59610461SAndreas.Sandberg@ARM.comvoid 59710461SAndreas.Sandberg@ARM.comPMU::setCounterValue(CounterId id, uint64_t val) 59810461SAndreas.Sandberg@ARM.com{ 59910461SAndreas.Sandberg@ARM.com if (!isValidCounter(id)) { 60010461SAndreas.Sandberg@ARM.com warn_once("Can't change counter value: Counter %i does not exist.\n", 60110461SAndreas.Sandberg@ARM.com id); 60210461SAndreas.Sandberg@ARM.com return; 60310461SAndreas.Sandberg@ARM.com } 60410461SAndreas.Sandberg@ARM.com 60510461SAndreas.Sandberg@ARM.com CounterState &ctr(getCounter(id)); 60612286Sjose.marinho@arm.com ctr.setValue(val); 60710461SAndreas.Sandberg@ARM.com} 60810461SAndreas.Sandberg@ARM.com 60910461SAndreas.Sandberg@ARM.comPMU::PMEVTYPER_t 61010461SAndreas.Sandberg@ARM.comPMU::getCounterTypeRegister(CounterId id) const 61110461SAndreas.Sandberg@ARM.com{ 61210461SAndreas.Sandberg@ARM.com if (!isValidCounter(id)) 61310461SAndreas.Sandberg@ARM.com return 0; 61410461SAndreas.Sandberg@ARM.com 61510461SAndreas.Sandberg@ARM.com const CounterState &cs(getCounter(id)); 61610609Sandreas.sandberg@arm.com PMEVTYPER_t type(cs.filter); 61710461SAndreas.Sandberg@ARM.com 61810461SAndreas.Sandberg@ARM.com type.evtCount = cs.eventId; 61910461SAndreas.Sandberg@ARM.com 62010461SAndreas.Sandberg@ARM.com return type; 62110461SAndreas.Sandberg@ARM.com} 62210461SAndreas.Sandberg@ARM.com 62310461SAndreas.Sandberg@ARM.comvoid 62410461SAndreas.Sandberg@ARM.comPMU::setCounterTypeRegister(CounterId id, PMEVTYPER_t val) 62510461SAndreas.Sandberg@ARM.com{ 62610461SAndreas.Sandberg@ARM.com DPRINTF(PMUVerbose, "Set Event [%d] = 0x%08x\n", id, val); 62710461SAndreas.Sandberg@ARM.com if (!isValidCounter(id)) { 62810461SAndreas.Sandberg@ARM.com warn_once("Can't change counter type: Counter %i does not exist.\n", 62910461SAndreas.Sandberg@ARM.com id); 63010461SAndreas.Sandberg@ARM.com return; 63110461SAndreas.Sandberg@ARM.com } 63210461SAndreas.Sandberg@ARM.com 63310461SAndreas.Sandberg@ARM.com CounterState &ctr(getCounter(id)); 63410609Sandreas.sandberg@arm.com const EventTypeId old_event_id(ctr.eventId); 63510461SAndreas.Sandberg@ARM.com 63610609Sandreas.sandberg@arm.com ctr.filter = val; 63710609Sandreas.sandberg@arm.com 63810609Sandreas.sandberg@arm.com // If PMCCNTR Register, do not change event type. PMCCNTR can 63910609Sandreas.sandberg@arm.com // count processor cycles only. If we change the event type, we 64010609Sandreas.sandberg@arm.com // need to update the probes the counter is using. 64110609Sandreas.sandberg@arm.com if (id != PMCCNTR && old_event_id != val.evtCount) { 64210461SAndreas.Sandberg@ARM.com ctr.eventId = val.evtCount; 64312286Sjose.marinho@arm.com updateCounter(ctr); 64410461SAndreas.Sandberg@ARM.com } 64510461SAndreas.Sandberg@ARM.com} 64610461SAndreas.Sandberg@ARM.com 64710461SAndreas.Sandberg@ARM.comvoid 64810461SAndreas.Sandberg@ARM.comPMU::raiseInterrupt() 64910461SAndreas.Sandberg@ARM.com{ 65012973Sandreas.sandberg@arm.com if (interrupt) { 65112973Sandreas.sandberg@arm.com DPRINTF(PMUVerbose, "Delivering PMU interrupt.\n"); 65212973Sandreas.sandberg@arm.com interrupt->raise(); 65312973Sandreas.sandberg@arm.com } else { 65412973Sandreas.sandberg@arm.com warn_once("Dropping PMU interrupt as no interrupt has " 65512973Sandreas.sandberg@arm.com "been specified\n"); 65610461SAndreas.Sandberg@ARM.com } 65710461SAndreas.Sandberg@ARM.com} 65810461SAndreas.Sandberg@ARM.com 65910461SAndreas.Sandberg@ARM.comvoid 66010905Sandreas.sandberg@arm.comPMU::serialize(CheckpointOut &cp) const 66110461SAndreas.Sandberg@ARM.com{ 66210461SAndreas.Sandberg@ARM.com DPRINTF(Checkpoint, "Serializing Arm PMU\n"); 66310461SAndreas.Sandberg@ARM.com 66410461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(reg_pmcr); 66510461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(reg_pmcnten); 66610461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(reg_pmselr); 66710461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(reg_pminten); 66810461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(reg_pmovsr); 66912117Sjose.marinho@arm.com SERIALIZE_SCALAR(reg_pmceid0); 67012117Sjose.marinho@arm.com SERIALIZE_SCALAR(reg_pmceid1); 67110461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(clock_remainder); 67210461SAndreas.Sandberg@ARM.com 67310905Sandreas.sandberg@arm.com for (size_t i = 0; i < counters.size(); ++i) 67410905Sandreas.sandberg@arm.com counters[i].serializeSection(cp, csprintf("counters.%i", i)); 67510461SAndreas.Sandberg@ARM.com 67610905Sandreas.sandberg@arm.com cycleCounter.serializeSection(cp, "cycleCounter"); 67710461SAndreas.Sandberg@ARM.com} 67810461SAndreas.Sandberg@ARM.com 67910461SAndreas.Sandberg@ARM.comvoid 68010905Sandreas.sandberg@arm.comPMU::unserialize(CheckpointIn &cp) 68110461SAndreas.Sandberg@ARM.com{ 68210461SAndreas.Sandberg@ARM.com DPRINTF(Checkpoint, "Unserializing Arm PMU\n"); 68310461SAndreas.Sandberg@ARM.com 68410461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(reg_pmcr); 68510461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(reg_pmcnten); 68610461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(reg_pmselr); 68710461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(reg_pminten); 68810461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(reg_pmovsr); 68912117Sjose.marinho@arm.com 69012117Sjose.marinho@arm.com // Old checkpoints used to store the entire PMCEID value in a 69112117Sjose.marinho@arm.com // single 64-bit entry (reg_pmceid). The register was extended in 69212117Sjose.marinho@arm.com // ARMv8.1, so we now need to store it as two 64-bit registers. 69312117Sjose.marinho@arm.com if (!UNSERIALIZE_OPT_SCALAR(reg_pmceid0)) 69412117Sjose.marinho@arm.com paramIn(cp, "reg_pmceid", reg_pmceid0); 69512117Sjose.marinho@arm.com 69612117Sjose.marinho@arm.com if (!UNSERIALIZE_OPT_SCALAR(reg_pmceid1)) 69712117Sjose.marinho@arm.com reg_pmceid1 = 0; 69812117Sjose.marinho@arm.com 69910461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(clock_remainder); 70010461SAndreas.Sandberg@ARM.com 70110461SAndreas.Sandberg@ARM.com for (size_t i = 0; i < counters.size(); ++i) 70210905Sandreas.sandberg@arm.com counters[i].unserializeSection(cp, csprintf("counters.%i", i)); 70310461SAndreas.Sandberg@ARM.com 70410905Sandreas.sandberg@arm.com cycleCounter.unserializeSection(cp, "cycleCounter"); 70510461SAndreas.Sandberg@ARM.com} 70610461SAndreas.Sandberg@ARM.com 70712286Sjose.marinho@arm.comPMU::PMUEvent* 70812286Sjose.marinho@arm.comPMU::getEvent(uint64_t eventId) 70912286Sjose.marinho@arm.com{ 71012286Sjose.marinho@arm.com auto entry = eventMap.find(eventId); 71112286Sjose.marinho@arm.com 71212286Sjose.marinho@arm.com if (entry == eventMap.end()) { 71312286Sjose.marinho@arm.com warn("event %d does not exist\n", eventId); 71412286Sjose.marinho@arm.com return nullptr; 71512286Sjose.marinho@arm.com } else { 71612286Sjose.marinho@arm.com return entry->second; 71712286Sjose.marinho@arm.com } 71812286Sjose.marinho@arm.com} 71912286Sjose.marinho@arm.com 72010461SAndreas.Sandberg@ARM.comvoid 72110905Sandreas.sandberg@arm.comPMU::CounterState::serialize(CheckpointOut &cp) const 72210461SAndreas.Sandberg@ARM.com{ 72310461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(eventId); 72410461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(value); 72510461SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(overflow64); 72610461SAndreas.Sandberg@ARM.com} 72710461SAndreas.Sandberg@ARM.com 72810461SAndreas.Sandberg@ARM.comvoid 72910905Sandreas.sandberg@arm.comPMU::CounterState::unserialize(CheckpointIn &cp) 73010461SAndreas.Sandberg@ARM.com{ 73110461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(eventId); 73210461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(value); 73310461SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(overflow64); 73410461SAndreas.Sandberg@ARM.com} 73510461SAndreas.Sandberg@ARM.com 73612286Sjose.marinho@arm.comuint64_t 73710461SAndreas.Sandberg@ARM.comPMU::CounterState::add(uint64_t delta) 73810461SAndreas.Sandberg@ARM.com{ 73912286Sjose.marinho@arm.com uint64_t value_until_overflow; 74012286Sjose.marinho@arm.com if (overflow64) { 74112286Sjose.marinho@arm.com value_until_overflow = UINT64_MAX - value; 74212286Sjose.marinho@arm.com } else { 74312286Sjose.marinho@arm.com value_until_overflow = UINT32_MAX - (uint32_t)value; 74412286Sjose.marinho@arm.com } 74510461SAndreas.Sandberg@ARM.com 74612286Sjose.marinho@arm.com if (isFiltered()) 74712286Sjose.marinho@arm.com return value_until_overflow; 74810461SAndreas.Sandberg@ARM.com 74912286Sjose.marinho@arm.com if (resetValue) { 75012286Sjose.marinho@arm.com delta = 0; 75112286Sjose.marinho@arm.com resetValue = false; 75212286Sjose.marinho@arm.com } else { 75312286Sjose.marinho@arm.com value += delta; 75412286Sjose.marinho@arm.com } 75512286Sjose.marinho@arm.com 75612286Sjose.marinho@arm.com if (delta > value_until_overflow) { 75712286Sjose.marinho@arm.com 75812286Sjose.marinho@arm.com // overflow situation detected 75912286Sjose.marinho@arm.com // flag the overflow occurence 76012286Sjose.marinho@arm.com pmu.reg_pmovsr |= (1 << counterId); 76112286Sjose.marinho@arm.com 76212286Sjose.marinho@arm.com // Deliver a PMU interrupt if interrupt delivery is enabled 76312286Sjose.marinho@arm.com // for this counter. 76412286Sjose.marinho@arm.com if (pmu.reg_pminten & (1 << counterId)) { 76512286Sjose.marinho@arm.com pmu.raiseInterrupt(); 76612286Sjose.marinho@arm.com } 76712286Sjose.marinho@arm.com return overflow64 ? UINT64_MAX : UINT32_MAX; 76812286Sjose.marinho@arm.com } 76912286Sjose.marinho@arm.com return value_until_overflow - delta + 1; 77012286Sjose.marinho@arm.com} 77112286Sjose.marinho@arm.com 77212286Sjose.marinho@arm.comvoid 77312286Sjose.marinho@arm.comPMU::SWIncrementEvent::write(uint64_t val) 77412286Sjose.marinho@arm.com{ 77512286Sjose.marinho@arm.com for (auto& counter: userCounters) { 77612286Sjose.marinho@arm.com if (val & (0x1 << counter->getCounterId())) { 77712286Sjose.marinho@arm.com counter->add(1); 77812286Sjose.marinho@arm.com } 77912286Sjose.marinho@arm.com } 78010461SAndreas.Sandberg@ARM.com} 78110461SAndreas.Sandberg@ARM.com 78210461SAndreas.Sandberg@ARM.com} // namespace ArmISA 78310461SAndreas.Sandberg@ARM.com 78410461SAndreas.Sandberg@ARM.comArmISA::PMU * 78510461SAndreas.Sandberg@ARM.comArmPMUParams::create() 78610461SAndreas.Sandberg@ARM.com{ 78710461SAndreas.Sandberg@ARM.com return new ArmISA::PMU(this); 78810461SAndreas.Sandberg@ARM.com} 789