2 * Copyright (c) 2011-2014 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 #include "arch/arm/pmu.hh"
44 #include "arch/arm/isa.hh"
45 #include "arch/arm/utility.hh"
46 #include "base/trace.hh"
47 #include "cpu/base.hh"
48 #include "debug/Checkpoint.hh"
49 #include "debug/PMUVerbose.hh"
50 #include "dev/arm/base_gic.hh"
51 #include "dev/arm/realview.hh"
52 #include "params/ArmPMU.hh"
56 const MiscReg
PMU::reg_pmcr_wr_mask
= 0x39;
58 PMU::PMU(const ArmPMUParams
*p
)
59 : SimObject(p
), BaseISADevice(),
60 reg_pmcnten(0), reg_pmcr(0),
61 reg_pmselr(0), reg_pminten(0), reg_pmovsr(0),
64 counters(p
->eventCounters
),
66 pmuInterrupt(p
->pmuInterrupt
),
69 DPRINTF(PMUVerbose
, "Initializing the PMU.\n");
71 if (p
->eventCounters
> 31) {
72 fatal("The PMU can only accept 31 counters, %d counters requested.\n",
76 /* Setup the performance counter ID registers */
77 reg_pmcr_conf
.imp
= 0x41; // ARM Ltd.
78 reg_pmcr_conf
.idcode
= 0x00;
79 reg_pmcr_conf
.n
= p
->eventCounters
;
81 // Setup the hard-coded cycle counter, which is equivalent to
82 // architected counter event type 0x11.
83 cycleCounter
.eventId
= 0x11;
91 PMU::addEventProbe(unsigned int id
, SimObject
*obj
, const char *probe_name
)
93 DPRINTF(PMUVerbose
, "PMU: Adding event type '0x%x' as probe %s:%s\n",
94 id
, obj
->name(), probe_name
);
95 pmuEventTypes
.insert(std::make_pair(id
, EventType(obj
, probe_name
)));
97 // Flag the event as available in the PMCEID register if it is an
100 reg_pmceid
|= (ULL(1) << id
);
106 // Re-attach enabled counters after a resume in case they changed.
111 PMU::setMiscReg(int misc_reg
, MiscReg val
)
113 DPRINTF(PMUVerbose
, "setMiscReg(%s, 0x%x)\n",
114 miscRegName
[unflattenMiscReg(misc_reg
)], val
);
116 switch (unflattenMiscReg(misc_reg
)) {
117 case MISCREG_PMCR_EL0
:
122 case MISCREG_PMCNTENSET_EL0
:
123 case MISCREG_PMCNTENSET
:
128 case MISCREG_PMCNTENCLR_EL0
:
129 case MISCREG_PMCNTENCLR
:
134 case MISCREG_PMOVSCLR_EL0
:
139 case MISCREG_PMSWINC_EL0
:
140 case MISCREG_PMSWINC
:
141 for (int i
= 0; i
< counters
.size(); ++i
) {
142 CounterState
&ctr(getCounter(i
));
143 if (ctr
.enabled
&& (val
& (1 << i
)))
148 case MISCREG_PMCCNTR_EL0
:
149 case MISCREG_PMCCNTR
:
150 cycleCounter
.value
= val
;
153 case MISCREG_PMSELR_EL0
:
158 case MISCREG_PMCEID0_EL0
:
159 case MISCREG_PMCEID0
:
160 case MISCREG_PMCEID1_EL0
:
161 case MISCREG_PMCEID1
:
165 case MISCREG_PMEVTYPER0_EL0
...MISCREG_PMEVTYPER5_EL0
:
166 setCounterTypeRegister(misc_reg
- MISCREG_PMEVCNTR0_EL0
, val
);
169 case MISCREG_PMCCFILTR
:
170 case MISCREG_PMCCFILTR_EL0
:
171 DPRINTF(PMUVerbose
, "Setting PMCCFILTR: 0x%x\n", val
);
172 setCounterTypeRegister(PMCCNTR
, val
);
175 case MISCREG_PMXEVTYPER_PMCCFILTR
:
176 case MISCREG_PMXEVTYPER_EL0
:
177 case MISCREG_PMXEVTYPER
:
178 DPRINTF(PMUVerbose
, "Setting counter type: "
179 "[PMSELR: 0x%x, PMSELER.sel: 0x%x, EVTYPER: 0x%x]\n",
180 reg_pmselr
, reg_pmselr
.sel
, val
);
181 setCounterTypeRegister(reg_pmselr
.sel
, val
);
184 case MISCREG_PMEVCNTR0_EL0
...MISCREG_PMEVCNTR5_EL0
:
185 setCounterValue(misc_reg
- MISCREG_PMEVCNTR0_EL0
, val
);
188 case MISCREG_PMXEVCNTR_EL0
:
189 case MISCREG_PMXEVCNTR
:
190 setCounterValue(reg_pmselr
.sel
, val
);
193 case MISCREG_PMUSERENR_EL0
:
194 case MISCREG_PMUSERENR
:
198 case MISCREG_PMINTENSET_EL1
:
199 case MISCREG_PMINTENSET
:
203 case MISCREG_PMINTENCLR_EL1
:
204 case MISCREG_PMINTENCLR
:
208 case MISCREG_PMOVSSET_EL0
:
209 case MISCREG_PMOVSSET
:
214 panic("Unexpected PMU register: %i\n", miscRegName
[misc_reg
]);
217 warn("Not doing anything for write to miscreg %s\n",
218 miscRegName
[misc_reg
]);
222 PMU::readMiscReg(int misc_reg
)
224 MiscReg
val(readMiscRegInt(misc_reg
));
225 DPRINTF(PMUVerbose
, "readMiscReg(%s): 0x%x\n",
226 miscRegName
[unflattenMiscReg(misc_reg
)], val
);
231 PMU::readMiscRegInt(int misc_reg
)
233 misc_reg
= unflattenMiscReg(misc_reg
);
235 case MISCREG_PMCR_EL0
:
237 return reg_pmcr_conf
| (reg_pmcr
& reg_pmcr_wr_mask
);
239 case MISCREG_PMCNTENSET_EL0
:
240 case MISCREG_PMCNTENCLR_EL0
:
241 case MISCREG_PMCNTENSET
:
242 case MISCREG_PMCNTENCLR
:
245 case MISCREG_PMOVSCLR_EL0
:
246 case MISCREG_PMOVSSET_EL0
:
247 case MISCREG_PMOVSR
: // Overflow Status Register
248 case MISCREG_PMOVSSET
:
251 case MISCREG_PMSWINC_EL0
:
252 case MISCREG_PMSWINC
: // Software Increment Register (RAZ)
258 case MISCREG_PMCEID0_EL0
:
259 case MISCREG_PMCEID0
: // Common Event ID register
260 return reg_pmceid
& 0xFFFFFFFF;
262 case MISCREG_PMCEID1_EL0
:
263 case MISCREG_PMCEID1
: // Common Event ID register
264 return (reg_pmceid
>> 32) & 0xFFFFFFFF;
266 case MISCREG_PMCCNTR_EL0
:
267 return cycleCounter
.value
;
269 case MISCREG_PMCCNTR
:
270 return cycleCounter
.value
& 0xFFFFFFFF;
272 case MISCREG_PMEVTYPER0_EL0
...MISCREG_PMEVTYPER5_EL0
:
273 return getCounterTypeRegister(misc_reg
- MISCREG_PMEVTYPER0_EL0
);
275 case MISCREG_PMCCFILTR
:
276 case MISCREG_PMCCFILTR_EL0
:
277 return getCounterTypeRegister(PMCCNTR
);
279 case MISCREG_PMXEVTYPER_PMCCFILTR
:
280 case MISCREG_PMXEVTYPER_EL0
:
281 case MISCREG_PMXEVTYPER
:
282 return getCounterTypeRegister(reg_pmselr
.sel
);
284 case MISCREG_PMEVCNTR0_EL0
...MISCREG_PMEVCNTR5_EL0
:
285 return getCounterValue(misc_reg
- MISCREG_PMEVCNTR0_EL0
) & 0xFFFFFFFF;
287 case MISCREG_PMXEVCNTR_EL0
:
288 case MISCREG_PMXEVCNTR
:
289 return getCounterValue(reg_pmselr
.sel
) & 0xFFFFFFFF;
291 case MISCREG_PMUSERENR_EL0
:
292 case MISCREG_PMUSERENR
:
296 case MISCREG_PMINTENSET_EL1
:
297 case MISCREG_PMINTENCLR_EL1
:
298 case MISCREG_PMINTENSET
:
299 case MISCREG_PMINTENCLR
:
303 panic("Unexpected PMU register: %i\n", miscRegName
[misc_reg
]);
306 warn("Not doing anything for read from miscreg %s\n",
307 miscRegName
[misc_reg
]);
312 PMU::setControlReg(PMCR_t val
)
314 DPRINTF(PMUVerbose
, "Set Control Reg 0x%08x.\n", val
);
317 DPRINTF(PMUVerbose
, "PMU reset all events to zero.\n");
322 DPRINTF(PMUVerbose
, "PMU reset cycle counter to zero.\n");
323 cycleCounter
.value
= 0;
326 // Reset the clock remainder if divide by 64-mode is toggled.
327 if (reg_pmcr
.d
!= val
.d
)
330 reg_pmcr
= val
& reg_pmcr_wr_mask
;
335 PMU::updateAllCounters()
337 const bool global_enable(reg_pmcr
.e
);
339 for (int i
= 0; i
< counters
.size(); ++i
) {
340 CounterState
&ctr(counters
[i
]);
341 const bool enable(global_enable
&& (reg_pmcnten
& (1 << i
)));
342 if (ctr
.enabled
!= enable
) {
343 ctr
.enabled
= enable
;
344 updateCounter(i
, ctr
);
348 const bool ccntr_enable(global_enable
&& (reg_pmcnten
& (1 << PMCCNTR
)));
349 if (cycleCounter
.enabled
!= ccntr_enable
) {
350 cycleCounter
.enabled
= ccntr_enable
;
351 updateCounter(PMCCNTR
, cycleCounter
);
356 PMU::isFiltered(const CounterState
&ctr
) const
360 const PMEVTYPER_t
filter(ctr
.filter
);
361 const SCR
scr(isa
->readMiscRegNoEffect(MISCREG_SCR
));
362 const CPSR
cpsr(isa
->readMiscRegNoEffect(MISCREG_CPSR
));
363 const ExceptionLevel
el(opModeToEL((OperatingMode
)(uint8_t)cpsr
.mode
));
364 const bool secure(inSecureState(scr
, cpsr
));
368 return secure
? filter
.u
: (filter
.u
!= filter
.nsu
);
371 return secure
? filter
.p
: (filter
.p
!= filter
.nsk
);
377 return filter
.p
!= filter
.m
;
380 panic("Unexpected execution level in PMU::isFiltered.\n");
385 PMU::handleEvent(CounterId id
, uint64_t delta
)
387 CounterState
&ctr(getCounter(id
));
388 const bool overflowed(reg_pmovsr
& (1 << id
));
393 // Handle the "count every 64 cycles" mode
394 if (id
== PMCCNTR
&& reg_pmcr
.d
) {
395 clock_remainder
+= delta
;
396 delta
= (clock_remainder
>> 6);
397 clock_remainder
&= 63;
400 // Add delta and handle (new) overflows
401 if (ctr
.add(delta
) && !overflowed
) {
402 DPRINTF(PMUVerbose
, "PMU counter '%i' overflowed.\n", id
);
403 reg_pmovsr
|= (1 << id
);
404 // Deliver a PMU interrupt if interrupt delivery is enabled
406 if (reg_pminten
& (1 << id
))
412 PMU::updateCounter(CounterId id
, CounterState
&ctr
)
415 if (!ctr
.listeners
.empty()) {
416 DPRINTF(PMUVerbose
, "updateCounter(%i): Disabling counter\n", id
);
417 ctr
.listeners
.clear();
420 DPRINTF(PMUVerbose
, "updateCounter(%i): Enable event id 0x%x\n",
423 // Attach all probes belonging to this event
424 auto range(pmuEventTypes
.equal_range(ctr
.eventId
));
425 for (auto it
= range
.first
; it
!= range
.second
; ++it
) {
426 const EventType
&et(it
->second
);
428 DPRINTF(PMUVerbose
, "\tProbe: %s:%s\n", et
.obj
->name(), et
.name
);
429 ctr
.listeners
.emplace_back(et
.create(*this, id
));
432 /* The SW_INCR event type is a special case which doesn't need
433 * any probes since it is controlled by software and the PMU
436 if (ctr
.listeners
.empty() && ctr
.eventId
!= ARCH_EVENT_SW_INCR
) {
437 warn("Can't enable PMU counter of type '0x%x': "
438 "No such event type.\n", ctr
.eventId
);
445 PMU::resetEventCounts()
447 for (CounterState
&ctr
: counters
)
452 PMU::setCounterValue(CounterId id
, uint64_t val
)
454 if (!isValidCounter(id
)) {
455 warn_once("Can't change counter value: Counter %i does not exist.\n",
460 CounterState
&ctr(getCounter(id
));
465 PMU::getCounterTypeRegister(CounterId id
) const
467 if (!isValidCounter(id
))
470 const CounterState
&cs(getCounter(id
));
471 PMEVTYPER_t
type(cs
.filter
);
473 type
.evtCount
= cs
.eventId
;
479 PMU::setCounterTypeRegister(CounterId id
, PMEVTYPER_t val
)
481 DPRINTF(PMUVerbose
, "Set Event [%d] = 0x%08x\n", id
, val
);
482 if (!isValidCounter(id
)) {
483 warn_once("Can't change counter type: Counter %i does not exist.\n",
488 CounterState
&ctr(getCounter(id
));
489 const EventTypeId
old_event_id(ctr
.eventId
);
493 // If PMCCNTR Register, do not change event type. PMCCNTR can
494 // count processor cycles only. If we change the event type, we
495 // need to update the probes the counter is using.
496 if (id
!= PMCCNTR
&& old_event_id
!= val
.evtCount
) {
497 ctr
.eventId
= val
.evtCount
;
498 updateCounter(reg_pmselr
.sel
, ctr
);
503 PMU::raiseInterrupt()
505 RealView
*rv(dynamic_cast<RealView
*>(platform
));
506 if (!rv
|| !rv
->gic
) {
507 warn_once("ARM PMU: GIC missing, can't raise interrupt.\n");
511 DPRINTF(PMUVerbose
, "Delivering PMU interrupt.\n");
512 rv
->gic
->sendInt(pmuInterrupt
);
516 PMU::serialize(CheckpointOut
&cp
) const
518 DPRINTF(Checkpoint
, "Serializing Arm PMU\n");
520 SERIALIZE_SCALAR(reg_pmcr
);
521 SERIALIZE_SCALAR(reg_pmcnten
);
522 SERIALIZE_SCALAR(reg_pmselr
);
523 SERIALIZE_SCALAR(reg_pminten
);
524 SERIALIZE_SCALAR(reg_pmovsr
);
525 SERIALIZE_SCALAR(reg_pmceid
);
526 SERIALIZE_SCALAR(clock_remainder
);
528 for (size_t i
= 0; i
< counters
.size(); ++i
)
529 counters
[i
].serializeSection(cp
, csprintf("counters.%i", i
));
531 cycleCounter
.serializeSection(cp
, "cycleCounter");
535 PMU::unserialize(CheckpointIn
&cp
)
537 DPRINTF(Checkpoint
, "Unserializing Arm PMU\n");
539 UNSERIALIZE_SCALAR(reg_pmcr
);
540 UNSERIALIZE_SCALAR(reg_pmcnten
);
541 UNSERIALIZE_SCALAR(reg_pmselr
);
542 UNSERIALIZE_SCALAR(reg_pminten
);
543 UNSERIALIZE_SCALAR(reg_pmovsr
);
544 UNSERIALIZE_SCALAR(reg_pmceid
);
545 UNSERIALIZE_SCALAR(clock_remainder
);
547 for (size_t i
= 0; i
< counters
.size(); ++i
)
548 counters
[i
].unserializeSection(cp
, csprintf("counters.%i", i
));
550 cycleCounter
.unserializeSection(cp
, "cycleCounter");
554 PMU::CounterState::serialize(CheckpointOut
&cp
) const
556 SERIALIZE_SCALAR(eventId
);
557 SERIALIZE_SCALAR(value
);
558 SERIALIZE_SCALAR(enabled
);
559 SERIALIZE_SCALAR(overflow64
);
563 PMU::CounterState::unserialize(CheckpointIn
&cp
)
565 UNSERIALIZE_SCALAR(eventId
);
566 UNSERIALIZE_SCALAR(value
);
567 UNSERIALIZE_SCALAR(enabled
);
568 UNSERIALIZE_SCALAR(overflow64
);
572 PMU::CounterState::add(uint64_t delta
)
574 const uint64_t msb(1ULL << (overflow64
? 63 : 31));
575 const uint64_t old_value(value
);
581 // Overflow if the msb goes from 1 to 0
582 return (old_value
& msb
) && !(value
& msb
);
585 } // namespace ArmISA
588 ArmPMUParams::create()
590 return new ArmISA::PMU(this);