pmu.cc revision 12117
110461SAndreas.Sandberg@ARM.com/*
212117Sjose.marinho@arm.com * Copyright (c) 2011-2014, 2017 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
4010461SAndreas.Sandberg@ARM.com */
4110461SAndreas.Sandberg@ARM.com
4210461SAndreas.Sandberg@ARM.com#include "arch/arm/pmu.hh"
4310461SAndreas.Sandberg@ARM.com
4410609Sandreas.sandberg@arm.com#include "arch/arm/isa.hh"
4510609Sandreas.sandberg@arm.com#include "arch/arm/utility.hh"
4610461SAndreas.Sandberg@ARM.com#include "base/trace.hh"
4710461SAndreas.Sandberg@ARM.com#include "cpu/base.hh"
4810461SAndreas.Sandberg@ARM.com#include "debug/Checkpoint.hh"
4910461SAndreas.Sandberg@ARM.com#include "debug/PMUVerbose.hh"
5010461SAndreas.Sandberg@ARM.com#include "dev/arm/base_gic.hh"
5110461SAndreas.Sandberg@ARM.com#include "dev/arm/realview.hh"
5210461SAndreas.Sandberg@ARM.com#include "params/ArmPMU.hh"
5310461SAndreas.Sandberg@ARM.com
5410461SAndreas.Sandberg@ARM.comnamespace ArmISA {
5510461SAndreas.Sandberg@ARM.com
5610461SAndreas.Sandberg@ARM.comconst MiscReg PMU::reg_pmcr_wr_mask = 0x39;
5710461SAndreas.Sandberg@ARM.com
5810461SAndreas.Sandberg@ARM.comPMU::PMU(const ArmPMUParams *p)
5910461SAndreas.Sandberg@ARM.com    : SimObject(p), BaseISADevice(),
6010461SAndreas.Sandberg@ARM.com      reg_pmcnten(0), reg_pmcr(0),
6110461SAndreas.Sandberg@ARM.com      reg_pmselr(0), reg_pminten(0), reg_pmovsr(0),
6212117Sjose.marinho@arm.com      reg_pmceid0(0),reg_pmceid1(0),
6310461SAndreas.Sandberg@ARM.com      clock_remainder(0),
6410461SAndreas.Sandberg@ARM.com      counters(p->eventCounters),
6510461SAndreas.Sandberg@ARM.com      reg_pmcr_conf(0),
6610461SAndreas.Sandberg@ARM.com      pmuInterrupt(p->pmuInterrupt),
6710461SAndreas.Sandberg@ARM.com      platform(p->platform)
6810461SAndreas.Sandberg@ARM.com{
6910461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "Initializing the PMU.\n");
7010461SAndreas.Sandberg@ARM.com
7110461SAndreas.Sandberg@ARM.com    if (p->eventCounters > 31) {
7210461SAndreas.Sandberg@ARM.com        fatal("The PMU can only accept 31 counters, %d counters requested.\n",
7310461SAndreas.Sandberg@ARM.com              p->eventCounters);
7410461SAndreas.Sandberg@ARM.com    }
7510461SAndreas.Sandberg@ARM.com
7610461SAndreas.Sandberg@ARM.com    /* Setup the performance counter ID registers */
7710461SAndreas.Sandberg@ARM.com    reg_pmcr_conf.imp = 0x41;    // ARM Ltd.
7810461SAndreas.Sandberg@ARM.com    reg_pmcr_conf.idcode = 0x00;
7910461SAndreas.Sandberg@ARM.com    reg_pmcr_conf.n = p->eventCounters;
8010461SAndreas.Sandberg@ARM.com
8110461SAndreas.Sandberg@ARM.com    // Setup the hard-coded cycle counter, which is equivalent to
8210461SAndreas.Sandberg@ARM.com    // architected counter event type 0x11.
8310461SAndreas.Sandberg@ARM.com    cycleCounter.eventId = 0x11;
8410461SAndreas.Sandberg@ARM.com}
8510461SAndreas.Sandberg@ARM.com
8610461SAndreas.Sandberg@ARM.comPMU::~PMU()
8710461SAndreas.Sandberg@ARM.com{
8810461SAndreas.Sandberg@ARM.com}
8910461SAndreas.Sandberg@ARM.com
9010461SAndreas.Sandberg@ARM.comvoid
9110461SAndreas.Sandberg@ARM.comPMU::addEventProbe(unsigned int id, SimObject *obj, const char *probe_name)
9210461SAndreas.Sandberg@ARM.com{
9310461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "PMU: Adding event type '0x%x' as probe %s:%s\n",
9410461SAndreas.Sandberg@ARM.com            id, obj->name(), probe_name);
9510461SAndreas.Sandberg@ARM.com    pmuEventTypes.insert(std::make_pair(id, EventType(obj, probe_name)));
9610461SAndreas.Sandberg@ARM.com
9712117Sjose.marinho@arm.com    // Flag the event as available in the corresponding PMCEID register if it
9812117Sjose.marinho@arm.com    // is an architected event.
9912117Sjose.marinho@arm.com    if (id < 0x20) {
10012117Sjose.marinho@arm.com        reg_pmceid0 |= ((uint64_t)1) << id;
10112117Sjose.marinho@arm.com    } else if (id > 0x20 && id < 0x40) {
10212117Sjose.marinho@arm.com        reg_pmceid1 |= ((uint64_t)1) << (id - 0x20);
10312117Sjose.marinho@arm.com    } else if (id >= 0x4000 && id < 0x4020) {
10412117Sjose.marinho@arm.com        reg_pmceid0 |= ((uint64_t)1) << (id - 0x4000 + 32);
10512117Sjose.marinho@arm.com    } else if (id >= 0x4020 && id < 0x4040) {
10612117Sjose.marinho@arm.com        reg_pmceid1 |= ((uint64_t)1) << (id - 0x4020 + 32);
10712117Sjose.marinho@arm.com    }
10810461SAndreas.Sandberg@ARM.com}
10910461SAndreas.Sandberg@ARM.com
11010461SAndreas.Sandberg@ARM.comvoid
11110461SAndreas.Sandberg@ARM.comPMU::drainResume()
11210461SAndreas.Sandberg@ARM.com{
11310461SAndreas.Sandberg@ARM.com    // Re-attach enabled counters after a resume in case they changed.
11410461SAndreas.Sandberg@ARM.com    updateAllCounters();
11510461SAndreas.Sandberg@ARM.com}
11610461SAndreas.Sandberg@ARM.com
11710461SAndreas.Sandberg@ARM.comvoid
11810461SAndreas.Sandberg@ARM.comPMU::setMiscReg(int misc_reg, MiscReg val)
11910461SAndreas.Sandberg@ARM.com{
12010461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "setMiscReg(%s, 0x%x)\n",
12110461SAndreas.Sandberg@ARM.com            miscRegName[unflattenMiscReg(misc_reg)], val);
12210461SAndreas.Sandberg@ARM.com
12310461SAndreas.Sandberg@ARM.com    switch (unflattenMiscReg(misc_reg)) {
12410461SAndreas.Sandberg@ARM.com      case MISCREG_PMCR_EL0:
12510461SAndreas.Sandberg@ARM.com      case MISCREG_PMCR:
12610461SAndreas.Sandberg@ARM.com        setControlReg(val);
12710461SAndreas.Sandberg@ARM.com        return;
12810461SAndreas.Sandberg@ARM.com
12910461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENSET_EL0:
13010461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENSET:
13110461SAndreas.Sandberg@ARM.com        reg_pmcnten |= val;
13210461SAndreas.Sandberg@ARM.com        updateAllCounters();
13310461SAndreas.Sandberg@ARM.com        return;
13410461SAndreas.Sandberg@ARM.com
13510461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENCLR_EL0:
13610461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENCLR:
13710461SAndreas.Sandberg@ARM.com        reg_pmcnten &= ~val;
13810461SAndreas.Sandberg@ARM.com        updateAllCounters();
13910461SAndreas.Sandberg@ARM.com        return;
14010461SAndreas.Sandberg@ARM.com
14110461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSCLR_EL0:
14210461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSR:
14310461SAndreas.Sandberg@ARM.com        reg_pmovsr &= ~val;
14410461SAndreas.Sandberg@ARM.com        return;
14510461SAndreas.Sandberg@ARM.com
14610461SAndreas.Sandberg@ARM.com      case MISCREG_PMSWINC_EL0:
14710461SAndreas.Sandberg@ARM.com      case MISCREG_PMSWINC:
14810461SAndreas.Sandberg@ARM.com        for (int i = 0; i < counters.size(); ++i) {
14910461SAndreas.Sandberg@ARM.com            CounterState &ctr(getCounter(i));
15010461SAndreas.Sandberg@ARM.com            if (ctr.enabled && (val & (1 << i)))
15110461SAndreas.Sandberg@ARM.com                ++ctr.value;
15210461SAndreas.Sandberg@ARM.com        }
15310461SAndreas.Sandberg@ARM.com        break;
15410461SAndreas.Sandberg@ARM.com
15510461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCNTR_EL0:
15610461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCNTR:
15710461SAndreas.Sandberg@ARM.com        cycleCounter.value = val;
15810461SAndreas.Sandberg@ARM.com        return;
15910461SAndreas.Sandberg@ARM.com
16010461SAndreas.Sandberg@ARM.com      case MISCREG_PMSELR_EL0:
16110461SAndreas.Sandberg@ARM.com      case MISCREG_PMSELR:
16210461SAndreas.Sandberg@ARM.com        reg_pmselr = val;
16310461SAndreas.Sandberg@ARM.com        return;
16412117Sjose.marinho@arm.com      //TODO: implement MISCREF_PMCEID{2,3}
16510461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID0_EL0:
16610461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID0:
16710461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID1_EL0:
16810461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID1:
16910461SAndreas.Sandberg@ARM.com        // Ignore writes
17010461SAndreas.Sandberg@ARM.com        return;
17110461SAndreas.Sandberg@ARM.com
17210461SAndreas.Sandberg@ARM.com      case MISCREG_PMEVTYPER0_EL0...MISCREG_PMEVTYPER5_EL0:
17312042Sandreas.sandberg@arm.com        setCounterTypeRegister(misc_reg - MISCREG_PMEVTYPER0_EL0, val);
17410461SAndreas.Sandberg@ARM.com        return;
17510461SAndreas.Sandberg@ARM.com
17610461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCFILTR:
17710461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCFILTR_EL0:
17810461SAndreas.Sandberg@ARM.com        DPRINTF(PMUVerbose, "Setting PMCCFILTR: 0x%x\n", val);
17910461SAndreas.Sandberg@ARM.com        setCounterTypeRegister(PMCCNTR, val);
18010461SAndreas.Sandberg@ARM.com        return;
18110461SAndreas.Sandberg@ARM.com
18210461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVTYPER_PMCCFILTR:
18310461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVTYPER_EL0:
18410461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVTYPER:
18510461SAndreas.Sandberg@ARM.com        DPRINTF(PMUVerbose, "Setting counter type: "
18610461SAndreas.Sandberg@ARM.com                "[PMSELR: 0x%x, PMSELER.sel: 0x%x, EVTYPER: 0x%x]\n",
18710461SAndreas.Sandberg@ARM.com                reg_pmselr, reg_pmselr.sel, val);
18810461SAndreas.Sandberg@ARM.com        setCounterTypeRegister(reg_pmselr.sel, val);
18910461SAndreas.Sandberg@ARM.com        return;
19010461SAndreas.Sandberg@ARM.com
19110461SAndreas.Sandberg@ARM.com      case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0:
19210461SAndreas.Sandberg@ARM.com        setCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0, val);
19310461SAndreas.Sandberg@ARM.com        return;
19410461SAndreas.Sandberg@ARM.com
19510461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVCNTR_EL0:
19610461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVCNTR:
19710461SAndreas.Sandberg@ARM.com        setCounterValue(reg_pmselr.sel, val);
19810461SAndreas.Sandberg@ARM.com        return;
19910461SAndreas.Sandberg@ARM.com
20010461SAndreas.Sandberg@ARM.com      case MISCREG_PMUSERENR_EL0:
20110461SAndreas.Sandberg@ARM.com      case MISCREG_PMUSERENR:
20210461SAndreas.Sandberg@ARM.com        // TODO
20310461SAndreas.Sandberg@ARM.com        break;
20410461SAndreas.Sandberg@ARM.com
20510461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENSET_EL1:
20610461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENSET:
20710461SAndreas.Sandberg@ARM.com        reg_pminten |= val;
20810461SAndreas.Sandberg@ARM.com        return;
20910461SAndreas.Sandberg@ARM.com
21010461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENCLR_EL1:
21110461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENCLR:
21210461SAndreas.Sandberg@ARM.com        reg_pminten &= ~val;
21310461SAndreas.Sandberg@ARM.com        return;
21410461SAndreas.Sandberg@ARM.com
21510461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSSET_EL0:
21610461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSSET:
21710461SAndreas.Sandberg@ARM.com        reg_pmovsr |= val;
21810461SAndreas.Sandberg@ARM.com        return;
21910461SAndreas.Sandberg@ARM.com
22010461SAndreas.Sandberg@ARM.com      default:
22110461SAndreas.Sandberg@ARM.com        panic("Unexpected PMU register: %i\n", miscRegName[misc_reg]);
22210461SAndreas.Sandberg@ARM.com    }
22310461SAndreas.Sandberg@ARM.com
22410461SAndreas.Sandberg@ARM.com    warn("Not doing anything for write to miscreg %s\n",
22510461SAndreas.Sandberg@ARM.com         miscRegName[misc_reg]);
22610461SAndreas.Sandberg@ARM.com}
22710461SAndreas.Sandberg@ARM.com
22810461SAndreas.Sandberg@ARM.comMiscReg
22910461SAndreas.Sandberg@ARM.comPMU::readMiscReg(int misc_reg)
23010461SAndreas.Sandberg@ARM.com{
23110461SAndreas.Sandberg@ARM.com    MiscReg val(readMiscRegInt(misc_reg));
23210461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "readMiscReg(%s): 0x%x\n",
23310461SAndreas.Sandberg@ARM.com            miscRegName[unflattenMiscReg(misc_reg)], val);
23410461SAndreas.Sandberg@ARM.com    return val;
23510461SAndreas.Sandberg@ARM.com}
23610461SAndreas.Sandberg@ARM.com
23710461SAndreas.Sandberg@ARM.comMiscReg
23810461SAndreas.Sandberg@ARM.comPMU::readMiscRegInt(int misc_reg)
23910461SAndreas.Sandberg@ARM.com{
24010461SAndreas.Sandberg@ARM.com    misc_reg = unflattenMiscReg(misc_reg);
24110461SAndreas.Sandberg@ARM.com    switch (misc_reg) {
24210461SAndreas.Sandberg@ARM.com      case MISCREG_PMCR_EL0:
24310461SAndreas.Sandberg@ARM.com      case MISCREG_PMCR:
24410461SAndreas.Sandberg@ARM.com        return reg_pmcr_conf | (reg_pmcr & reg_pmcr_wr_mask);
24510461SAndreas.Sandberg@ARM.com
24610461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENSET_EL0:
24710461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENCLR_EL0:
24810461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENSET:
24910461SAndreas.Sandberg@ARM.com      case MISCREG_PMCNTENCLR:
25010461SAndreas.Sandberg@ARM.com        return reg_pmcnten;
25110461SAndreas.Sandberg@ARM.com
25210461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSCLR_EL0:
25310461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSSET_EL0:
25410461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSR:  // Overflow Status Register
25510461SAndreas.Sandberg@ARM.com      case MISCREG_PMOVSSET:
25610461SAndreas.Sandberg@ARM.com        return reg_pmovsr;
25710461SAndreas.Sandberg@ARM.com
25810461SAndreas.Sandberg@ARM.com      case MISCREG_PMSWINC_EL0:
25910461SAndreas.Sandberg@ARM.com      case MISCREG_PMSWINC: // Software Increment Register (RAZ)
26010461SAndreas.Sandberg@ARM.com        return 0;
26110461SAndreas.Sandberg@ARM.com
26210461SAndreas.Sandberg@ARM.com      case MISCREG_PMSELR:
26310461SAndreas.Sandberg@ARM.com        return reg_pmselr;
26410461SAndreas.Sandberg@ARM.com
26510461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID0_EL0:
26612117Sjose.marinho@arm.com        return reg_pmceid0;
26710461SAndreas.Sandberg@ARM.com
26810461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID1_EL0:
26912117Sjose.marinho@arm.com        return reg_pmceid1;
27012117Sjose.marinho@arm.com
27112117Sjose.marinho@arm.com      //TODO: implement MISCREF_PMCEID{2,3}
27212117Sjose.marinho@arm.com      case MISCREG_PMCEID0: // Common Event ID register
27312117Sjose.marinho@arm.com        return reg_pmceid0 & 0xFFFFFFFF;
27412117Sjose.marinho@arm.com
27510461SAndreas.Sandberg@ARM.com      case MISCREG_PMCEID1: // Common Event ID register
27612117Sjose.marinho@arm.com        return reg_pmceid1 & 0xFFFFFFFF;
27710461SAndreas.Sandberg@ARM.com
27810461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCNTR_EL0:
27910461SAndreas.Sandberg@ARM.com        return cycleCounter.value;
28010461SAndreas.Sandberg@ARM.com
28110461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCNTR:
28210461SAndreas.Sandberg@ARM.com        return cycleCounter.value & 0xFFFFFFFF;
28310461SAndreas.Sandberg@ARM.com
28410461SAndreas.Sandberg@ARM.com      case MISCREG_PMEVTYPER0_EL0...MISCREG_PMEVTYPER5_EL0:
28510461SAndreas.Sandberg@ARM.com        return getCounterTypeRegister(misc_reg - MISCREG_PMEVTYPER0_EL0);
28610461SAndreas.Sandberg@ARM.com
28710461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCFILTR:
28810461SAndreas.Sandberg@ARM.com      case MISCREG_PMCCFILTR_EL0:
28910461SAndreas.Sandberg@ARM.com        return getCounterTypeRegister(PMCCNTR);
29010461SAndreas.Sandberg@ARM.com
29110461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVTYPER_PMCCFILTR:
29210461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVTYPER_EL0:
29310461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVTYPER:
29410461SAndreas.Sandberg@ARM.com        return getCounterTypeRegister(reg_pmselr.sel);
29510461SAndreas.Sandberg@ARM.com
29610461SAndreas.Sandberg@ARM.com      case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0:
29710461SAndreas.Sandberg@ARM.com        return getCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0) & 0xFFFFFFFF;
29810461SAndreas.Sandberg@ARM.com
29910461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVCNTR_EL0:
30010461SAndreas.Sandberg@ARM.com      case MISCREG_PMXEVCNTR:
30110461SAndreas.Sandberg@ARM.com        return getCounterValue(reg_pmselr.sel) & 0xFFFFFFFF;
30210461SAndreas.Sandberg@ARM.com
30310461SAndreas.Sandberg@ARM.com      case MISCREG_PMUSERENR_EL0:
30410461SAndreas.Sandberg@ARM.com      case MISCREG_PMUSERENR:
30510461SAndreas.Sandberg@ARM.com        // TODO
30610461SAndreas.Sandberg@ARM.com        return 0;
30710461SAndreas.Sandberg@ARM.com
30810461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENSET_EL1:
30910461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENCLR_EL1:
31010461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENSET:
31110461SAndreas.Sandberg@ARM.com      case MISCREG_PMINTENCLR:
31210461SAndreas.Sandberg@ARM.com        return reg_pminten;
31310461SAndreas.Sandberg@ARM.com
31410461SAndreas.Sandberg@ARM.com      default:
31510461SAndreas.Sandberg@ARM.com        panic("Unexpected PMU register: %i\n", miscRegName[misc_reg]);
31610461SAndreas.Sandberg@ARM.com    }
31710461SAndreas.Sandberg@ARM.com
31810461SAndreas.Sandberg@ARM.com    warn("Not doing anything for read from miscreg %s\n",
31910461SAndreas.Sandberg@ARM.com         miscRegName[misc_reg]);
32010461SAndreas.Sandberg@ARM.com    return 0;
32110461SAndreas.Sandberg@ARM.com}
32210461SAndreas.Sandberg@ARM.com
32310461SAndreas.Sandberg@ARM.comvoid
32410461SAndreas.Sandberg@ARM.comPMU::setControlReg(PMCR_t val)
32510461SAndreas.Sandberg@ARM.com{
32610461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "Set Control Reg 0x%08x.\n", val);
32710461SAndreas.Sandberg@ARM.com
32810461SAndreas.Sandberg@ARM.com    if (val.p) {
32910461SAndreas.Sandberg@ARM.com        DPRINTF(PMUVerbose, "PMU reset all events to zero.\n");
33010461SAndreas.Sandberg@ARM.com        resetEventCounts();
33110461SAndreas.Sandberg@ARM.com    }
33210461SAndreas.Sandberg@ARM.com
33310461SAndreas.Sandberg@ARM.com    if (val.c) {
33410461SAndreas.Sandberg@ARM.com        DPRINTF(PMUVerbose, "PMU reset cycle counter to zero.\n");
33510461SAndreas.Sandberg@ARM.com        cycleCounter.value = 0;
33610461SAndreas.Sandberg@ARM.com    }
33710461SAndreas.Sandberg@ARM.com
33810461SAndreas.Sandberg@ARM.com    // Reset the clock remainder if divide by 64-mode is toggled.
33910461SAndreas.Sandberg@ARM.com    if (reg_pmcr.d != val.d)
34010461SAndreas.Sandberg@ARM.com        clock_remainder = 0;
34110461SAndreas.Sandberg@ARM.com
34210461SAndreas.Sandberg@ARM.com    reg_pmcr = val & reg_pmcr_wr_mask;
34310461SAndreas.Sandberg@ARM.com    updateAllCounters();
34410461SAndreas.Sandberg@ARM.com}
34510461SAndreas.Sandberg@ARM.com
34610461SAndreas.Sandberg@ARM.comvoid
34710461SAndreas.Sandberg@ARM.comPMU::updateAllCounters()
34810461SAndreas.Sandberg@ARM.com{
34910461SAndreas.Sandberg@ARM.com    const bool global_enable(reg_pmcr.e);
35010461SAndreas.Sandberg@ARM.com
35110461SAndreas.Sandberg@ARM.com    for (int i = 0; i < counters.size(); ++i) {
35210461SAndreas.Sandberg@ARM.com        CounterState &ctr(counters[i]);
35310461SAndreas.Sandberg@ARM.com        const bool enable(global_enable && (reg_pmcnten & (1 << i)));
35410461SAndreas.Sandberg@ARM.com        if (ctr.enabled != enable) {
35510461SAndreas.Sandberg@ARM.com            ctr.enabled = enable;
35610461SAndreas.Sandberg@ARM.com            updateCounter(i, ctr);
35710461SAndreas.Sandberg@ARM.com        }
35810461SAndreas.Sandberg@ARM.com    }
35910461SAndreas.Sandberg@ARM.com
36010461SAndreas.Sandberg@ARM.com    const bool ccntr_enable(global_enable && (reg_pmcnten & (1 << PMCCNTR)));
36110461SAndreas.Sandberg@ARM.com    if (cycleCounter.enabled != ccntr_enable) {
36210461SAndreas.Sandberg@ARM.com        cycleCounter.enabled = ccntr_enable;
36310461SAndreas.Sandberg@ARM.com        updateCounter(PMCCNTR, cycleCounter);
36410461SAndreas.Sandberg@ARM.com    }
36510461SAndreas.Sandberg@ARM.com}
36610461SAndreas.Sandberg@ARM.com
36710609Sandreas.sandberg@arm.combool
36810609Sandreas.sandberg@arm.comPMU::isFiltered(const CounterState &ctr) const
36910609Sandreas.sandberg@arm.com{
37010609Sandreas.sandberg@arm.com    assert(isa);
37110609Sandreas.sandberg@arm.com
37210609Sandreas.sandberg@arm.com    const PMEVTYPER_t filter(ctr.filter);
37310609Sandreas.sandberg@arm.com    const SCR scr(isa->readMiscRegNoEffect(MISCREG_SCR));
37410609Sandreas.sandberg@arm.com    const CPSR cpsr(isa->readMiscRegNoEffect(MISCREG_CPSR));
37510609Sandreas.sandberg@arm.com    const ExceptionLevel el(opModeToEL((OperatingMode)(uint8_t)cpsr.mode));
37610609Sandreas.sandberg@arm.com    const bool secure(inSecureState(scr, cpsr));
37710609Sandreas.sandberg@arm.com
37810609Sandreas.sandberg@arm.com    switch (el) {
37910609Sandreas.sandberg@arm.com      case EL0:
38010609Sandreas.sandberg@arm.com        return secure ? filter.u : (filter.u != filter.nsu);
38110609Sandreas.sandberg@arm.com
38210609Sandreas.sandberg@arm.com      case EL1:
38310609Sandreas.sandberg@arm.com        return secure ? filter.p : (filter.p != filter.nsk);
38410609Sandreas.sandberg@arm.com
38510609Sandreas.sandberg@arm.com      case EL2:
38610609Sandreas.sandberg@arm.com        return !filter.nsh;
38710609Sandreas.sandberg@arm.com
38810609Sandreas.sandberg@arm.com      case EL3:
38910609Sandreas.sandberg@arm.com        return filter.p != filter.m;
39010609Sandreas.sandberg@arm.com
39110609Sandreas.sandberg@arm.com      default:
39210609Sandreas.sandberg@arm.com        panic("Unexpected execution level in PMU::isFiltered.\n");
39310609Sandreas.sandberg@arm.com    }
39410609Sandreas.sandberg@arm.com}
39510609Sandreas.sandberg@arm.com
39610461SAndreas.Sandberg@ARM.comvoid
39710461SAndreas.Sandberg@ARM.comPMU::handleEvent(CounterId id, uint64_t delta)
39810461SAndreas.Sandberg@ARM.com{
39910461SAndreas.Sandberg@ARM.com    CounterState &ctr(getCounter(id));
40010461SAndreas.Sandberg@ARM.com    const bool overflowed(reg_pmovsr & (1 << id));
40110461SAndreas.Sandberg@ARM.com
40210609Sandreas.sandberg@arm.com    if (isFiltered(ctr))
40310609Sandreas.sandberg@arm.com        return;
40410609Sandreas.sandberg@arm.com
40510461SAndreas.Sandberg@ARM.com    // Handle the "count every 64 cycles" mode
40610461SAndreas.Sandberg@ARM.com    if (id == PMCCNTR && reg_pmcr.d) {
40710461SAndreas.Sandberg@ARM.com        clock_remainder += delta;
40810461SAndreas.Sandberg@ARM.com        delta = (clock_remainder >> 6);
40910461SAndreas.Sandberg@ARM.com        clock_remainder &= 63;
41010461SAndreas.Sandberg@ARM.com    }
41110461SAndreas.Sandberg@ARM.com
41210461SAndreas.Sandberg@ARM.com    // Add delta and handle (new) overflows
41310461SAndreas.Sandberg@ARM.com    if (ctr.add(delta) && !overflowed) {
41410461SAndreas.Sandberg@ARM.com        DPRINTF(PMUVerbose, "PMU counter '%i' overflowed.\n", id);
41510461SAndreas.Sandberg@ARM.com        reg_pmovsr |= (1 << id);
41610461SAndreas.Sandberg@ARM.com        // Deliver a PMU interrupt if interrupt delivery is enabled
41710461SAndreas.Sandberg@ARM.com        // for this counter.
41810461SAndreas.Sandberg@ARM.com        if (reg_pminten  & (1 << id))
41910461SAndreas.Sandberg@ARM.com            raiseInterrupt();
42010461SAndreas.Sandberg@ARM.com    }
42110461SAndreas.Sandberg@ARM.com}
42210461SAndreas.Sandberg@ARM.com
42310461SAndreas.Sandberg@ARM.comvoid
42410461SAndreas.Sandberg@ARM.comPMU::updateCounter(CounterId id, CounterState &ctr)
42510461SAndreas.Sandberg@ARM.com{
42610461SAndreas.Sandberg@ARM.com    if (!ctr.enabled) {
42710461SAndreas.Sandberg@ARM.com        if (!ctr.listeners.empty()) {
42810461SAndreas.Sandberg@ARM.com            DPRINTF(PMUVerbose, "updateCounter(%i): Disabling counter\n", id);
42910461SAndreas.Sandberg@ARM.com            ctr.listeners.clear();
43010461SAndreas.Sandberg@ARM.com        }
43110461SAndreas.Sandberg@ARM.com    } else {
43210461SAndreas.Sandberg@ARM.com        DPRINTF(PMUVerbose, "updateCounter(%i): Enable event id 0x%x\n",
43310461SAndreas.Sandberg@ARM.com                id, ctr.eventId);
43410461SAndreas.Sandberg@ARM.com
43510461SAndreas.Sandberg@ARM.com        // Attach all probes belonging to this event
43610461SAndreas.Sandberg@ARM.com        auto range(pmuEventTypes.equal_range(ctr.eventId));
43710461SAndreas.Sandberg@ARM.com        for (auto it = range.first; it != range.second; ++it) {
43810461SAndreas.Sandberg@ARM.com            const EventType &et(it->second);
43910461SAndreas.Sandberg@ARM.com
44010461SAndreas.Sandberg@ARM.com            DPRINTF(PMUVerbose, "\tProbe: %s:%s\n", et.obj->name(), et.name);
44110461SAndreas.Sandberg@ARM.com            ctr.listeners.emplace_back(et.create(*this, id));
44210461SAndreas.Sandberg@ARM.com        }
44310461SAndreas.Sandberg@ARM.com
44410461SAndreas.Sandberg@ARM.com        /* The SW_INCR event type is a special case which doesn't need
44510461SAndreas.Sandberg@ARM.com         * any probes since it is controlled by software and the PMU
44610461SAndreas.Sandberg@ARM.com         * itself.
44710461SAndreas.Sandberg@ARM.com         */
44810461SAndreas.Sandberg@ARM.com        if (ctr.listeners.empty() && ctr.eventId != ARCH_EVENT_SW_INCR) {
44910461SAndreas.Sandberg@ARM.com            warn("Can't enable PMU counter of type '0x%x': "
45010461SAndreas.Sandberg@ARM.com                 "No such event type.\n", ctr.eventId);
45110461SAndreas.Sandberg@ARM.com        }
45210461SAndreas.Sandberg@ARM.com    }
45310461SAndreas.Sandberg@ARM.com}
45410461SAndreas.Sandberg@ARM.com
45510461SAndreas.Sandberg@ARM.com
45610461SAndreas.Sandberg@ARM.comvoid
45710461SAndreas.Sandberg@ARM.comPMU::resetEventCounts()
45810461SAndreas.Sandberg@ARM.com{
45910461SAndreas.Sandberg@ARM.com    for (CounterState &ctr : counters)
46010461SAndreas.Sandberg@ARM.com        ctr.value = 0;
46110461SAndreas.Sandberg@ARM.com}
46210461SAndreas.Sandberg@ARM.com
46310461SAndreas.Sandberg@ARM.comvoid
46410461SAndreas.Sandberg@ARM.comPMU::setCounterValue(CounterId id, uint64_t val)
46510461SAndreas.Sandberg@ARM.com{
46610461SAndreas.Sandberg@ARM.com    if (!isValidCounter(id)) {
46710461SAndreas.Sandberg@ARM.com        warn_once("Can't change counter value: Counter %i does not exist.\n",
46810461SAndreas.Sandberg@ARM.com                  id);
46910461SAndreas.Sandberg@ARM.com        return;
47010461SAndreas.Sandberg@ARM.com    }
47110461SAndreas.Sandberg@ARM.com
47210461SAndreas.Sandberg@ARM.com    CounterState &ctr(getCounter(id));
47310461SAndreas.Sandberg@ARM.com    ctr.value = val;
47410461SAndreas.Sandberg@ARM.com}
47510461SAndreas.Sandberg@ARM.com
47610461SAndreas.Sandberg@ARM.comPMU::PMEVTYPER_t
47710461SAndreas.Sandberg@ARM.comPMU::getCounterTypeRegister(CounterId id) const
47810461SAndreas.Sandberg@ARM.com{
47910461SAndreas.Sandberg@ARM.com    if (!isValidCounter(id))
48010461SAndreas.Sandberg@ARM.com        return 0;
48110461SAndreas.Sandberg@ARM.com
48210461SAndreas.Sandberg@ARM.com    const CounterState &cs(getCounter(id));
48310609Sandreas.sandberg@arm.com    PMEVTYPER_t type(cs.filter);
48410461SAndreas.Sandberg@ARM.com
48510461SAndreas.Sandberg@ARM.com    type.evtCount = cs.eventId;
48610461SAndreas.Sandberg@ARM.com
48710461SAndreas.Sandberg@ARM.com    return type;
48810461SAndreas.Sandberg@ARM.com}
48910461SAndreas.Sandberg@ARM.com
49010461SAndreas.Sandberg@ARM.comvoid
49110461SAndreas.Sandberg@ARM.comPMU::setCounterTypeRegister(CounterId id, PMEVTYPER_t val)
49210461SAndreas.Sandberg@ARM.com{
49310461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "Set Event [%d] = 0x%08x\n", id, val);
49410461SAndreas.Sandberg@ARM.com    if (!isValidCounter(id)) {
49510461SAndreas.Sandberg@ARM.com        warn_once("Can't change counter type: Counter %i does not exist.\n",
49610461SAndreas.Sandberg@ARM.com                  id);
49710461SAndreas.Sandberg@ARM.com        return;
49810461SAndreas.Sandberg@ARM.com    }
49910461SAndreas.Sandberg@ARM.com
50010461SAndreas.Sandberg@ARM.com    CounterState &ctr(getCounter(id));
50110609Sandreas.sandberg@arm.com    const EventTypeId old_event_id(ctr.eventId);
50210461SAndreas.Sandberg@ARM.com
50310609Sandreas.sandberg@arm.com    ctr.filter = val;
50410609Sandreas.sandberg@arm.com
50510609Sandreas.sandberg@arm.com    // If PMCCNTR Register, do not change event type. PMCCNTR can
50610609Sandreas.sandberg@arm.com    // count processor cycles only. If we change the event type, we
50710609Sandreas.sandberg@arm.com    // need to update the probes the counter is using.
50810609Sandreas.sandberg@arm.com    if (id != PMCCNTR && old_event_id != val.evtCount) {
50910461SAndreas.Sandberg@ARM.com        ctr.eventId = val.evtCount;
51010461SAndreas.Sandberg@ARM.com        updateCounter(reg_pmselr.sel, ctr);
51110461SAndreas.Sandberg@ARM.com    }
51210461SAndreas.Sandberg@ARM.com}
51310461SAndreas.Sandberg@ARM.com
51410461SAndreas.Sandberg@ARM.comvoid
51510461SAndreas.Sandberg@ARM.comPMU::raiseInterrupt()
51610461SAndreas.Sandberg@ARM.com{
51710461SAndreas.Sandberg@ARM.com    RealView *rv(dynamic_cast<RealView *>(platform));
51810461SAndreas.Sandberg@ARM.com    if (!rv || !rv->gic) {
51910461SAndreas.Sandberg@ARM.com        warn_once("ARM PMU: GIC missing, can't raise interrupt.\n");
52010461SAndreas.Sandberg@ARM.com        return;
52110461SAndreas.Sandberg@ARM.com    }
52210461SAndreas.Sandberg@ARM.com
52310461SAndreas.Sandberg@ARM.com    DPRINTF(PMUVerbose, "Delivering PMU interrupt.\n");
52410461SAndreas.Sandberg@ARM.com    rv->gic->sendInt(pmuInterrupt);
52510461SAndreas.Sandberg@ARM.com}
52610461SAndreas.Sandberg@ARM.com
52710461SAndreas.Sandberg@ARM.comvoid
52810905Sandreas.sandberg@arm.comPMU::serialize(CheckpointOut &cp) const
52910461SAndreas.Sandberg@ARM.com{
53010461SAndreas.Sandberg@ARM.com    DPRINTF(Checkpoint, "Serializing Arm PMU\n");
53110461SAndreas.Sandberg@ARM.com
53210461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(reg_pmcr);
53310461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(reg_pmcnten);
53410461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(reg_pmselr);
53510461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(reg_pminten);
53610461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(reg_pmovsr);
53712117Sjose.marinho@arm.com    SERIALIZE_SCALAR(reg_pmceid0);
53812117Sjose.marinho@arm.com    SERIALIZE_SCALAR(reg_pmceid1);
53910461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(clock_remainder);
54010461SAndreas.Sandberg@ARM.com
54110905Sandreas.sandberg@arm.com    for (size_t i = 0; i < counters.size(); ++i)
54210905Sandreas.sandberg@arm.com        counters[i].serializeSection(cp, csprintf("counters.%i", i));
54310461SAndreas.Sandberg@ARM.com
54410905Sandreas.sandberg@arm.com    cycleCounter.serializeSection(cp, "cycleCounter");
54510461SAndreas.Sandberg@ARM.com}
54610461SAndreas.Sandberg@ARM.com
54710461SAndreas.Sandberg@ARM.comvoid
54810905Sandreas.sandberg@arm.comPMU::unserialize(CheckpointIn &cp)
54910461SAndreas.Sandberg@ARM.com{
55010461SAndreas.Sandberg@ARM.com    DPRINTF(Checkpoint, "Unserializing Arm PMU\n");
55110461SAndreas.Sandberg@ARM.com
55210461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(reg_pmcr);
55310461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(reg_pmcnten);
55410461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(reg_pmselr);
55510461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(reg_pminten);
55610461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(reg_pmovsr);
55712117Sjose.marinho@arm.com
55812117Sjose.marinho@arm.com    // Old checkpoints used to store the entire PMCEID value in a
55912117Sjose.marinho@arm.com    // single 64-bit entry (reg_pmceid). The register was extended in
56012117Sjose.marinho@arm.com    // ARMv8.1, so we now need to store it as two 64-bit registers.
56112117Sjose.marinho@arm.com    if (!UNSERIALIZE_OPT_SCALAR(reg_pmceid0))
56212117Sjose.marinho@arm.com        paramIn(cp, "reg_pmceid", reg_pmceid0);
56312117Sjose.marinho@arm.com
56412117Sjose.marinho@arm.com    if (!UNSERIALIZE_OPT_SCALAR(reg_pmceid1))
56512117Sjose.marinho@arm.com        reg_pmceid1 = 0;
56612117Sjose.marinho@arm.com
56710461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(clock_remainder);
56810461SAndreas.Sandberg@ARM.com
56910461SAndreas.Sandberg@ARM.com    for (size_t i = 0; i < counters.size(); ++i)
57010905Sandreas.sandberg@arm.com        counters[i].unserializeSection(cp, csprintf("counters.%i", i));
57110461SAndreas.Sandberg@ARM.com
57210905Sandreas.sandberg@arm.com    cycleCounter.unserializeSection(cp, "cycleCounter");
57310461SAndreas.Sandberg@ARM.com}
57410461SAndreas.Sandberg@ARM.com
57510461SAndreas.Sandberg@ARM.comvoid
57610905Sandreas.sandberg@arm.comPMU::CounterState::serialize(CheckpointOut &cp) const
57710461SAndreas.Sandberg@ARM.com{
57810461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(eventId);
57910461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(value);
58010461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(enabled);
58110461SAndreas.Sandberg@ARM.com    SERIALIZE_SCALAR(overflow64);
58210461SAndreas.Sandberg@ARM.com}
58310461SAndreas.Sandberg@ARM.com
58410461SAndreas.Sandberg@ARM.comvoid
58510905Sandreas.sandberg@arm.comPMU::CounterState::unserialize(CheckpointIn &cp)
58610461SAndreas.Sandberg@ARM.com{
58710461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(eventId);
58810461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(value);
58910461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(enabled);
59010461SAndreas.Sandberg@ARM.com    UNSERIALIZE_SCALAR(overflow64);
59110461SAndreas.Sandberg@ARM.com}
59210461SAndreas.Sandberg@ARM.com
59310461SAndreas.Sandberg@ARM.combool
59410461SAndreas.Sandberg@ARM.comPMU::CounterState::add(uint64_t delta)
59510461SAndreas.Sandberg@ARM.com{
59610461SAndreas.Sandberg@ARM.com    const uint64_t msb(1ULL << (overflow64 ? 63 : 31));
59710461SAndreas.Sandberg@ARM.com    const uint64_t old_value(value);
59810461SAndreas.Sandberg@ARM.com
59910461SAndreas.Sandberg@ARM.com    value += delta;
60010461SAndreas.Sandberg@ARM.com
60110461SAndreas.Sandberg@ARM.com    // Overflow if the msb goes from 1 to 0
60210461SAndreas.Sandberg@ARM.com    return (old_value & msb) && !(value & msb);
60310461SAndreas.Sandberg@ARM.com}
60410461SAndreas.Sandberg@ARM.com
60510461SAndreas.Sandberg@ARM.com} // namespace ArmISA
60610461SAndreas.Sandberg@ARM.com
60710461SAndreas.Sandberg@ARM.comArmISA::PMU *
60810461SAndreas.Sandberg@ARM.comArmPMUParams::create()
60910461SAndreas.Sandberg@ARM.com{
61010461SAndreas.Sandberg@ARM.com    return new ArmISA::PMU(this);
61110461SAndreas.Sandberg@ARM.com}
612