pmu.hh revision 12973:78a7bbc23c29
1/* 2 * Copyright (c) 2011-2014, 2017-2018 ARM Limited 3 * All rights reserved 4 * 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. 13 * 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. 24 * 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. 36 * 37 * Authors: Dam Sunwoo 38 * Matt Horsnell 39 * Andreas Sandberg 40 */ 41#ifndef __ARCH_ARM_PMU_HH__ 42#define __ARCH_ARM_PMU_HH__ 43 44#include <map> 45#include <memory> 46#include <vector> 47 48#include "arch/arm/isa_device.hh" 49#include "arch/arm/registers.hh" 50#include "arch/arm/system.hh" 51#include "base/cprintf.hh" 52#include "cpu/base.hh" 53#include "debug/PMUVerbose.hh" 54#include "sim/eventq.hh" 55#include "sim/sim_object.hh" 56#include "sim/system.hh" 57 58class ArmPMUParams; 59class Platform; 60class ThreadContext; 61class ArmInterruptPin; 62 63namespace ArmISA { 64 65 66/** 67 * Model of an ARM PMU version 3 68 * 69 * This class implements a subset of the ARM PMU v3 specification as 70 * described in the ARMv8 reference manual. It supports most of the 71 * features of the PMU, however the following features are known to be 72 * missing: 73 * 74 * <ul> 75 * <li>Event filtering (e.g., from different privilege levels). 76 * <li>Access controls (the PMU currently ignores the execution level). 77 * <li>The chain counter (event no. 0x1E) is unimplemented. 78 * </ul> 79 * 80 * The PMU itself does not implement any events, in merely provides an 81 * interface for the configuration scripts to hook up probes that 82 * drive events. Configuration scripts should call addEventProbe() to 83 * configure custom events or high-level methods to configure 84 * architected events. The Python implementation of addEventProbe() 85 * automatically delays event type registration until after 86 * instantiation. 87 * 88 * In order to support CPU switching and some combined counters (e.g., 89 * memory references synthesized from loads and stores), the PMU 90 * allows multiple probes per event type. When creating a system that 91 * switches between CPU models that share the same PMU, PMU events for 92 * all of the CPU models can be registered with the PMU. 93 * 94 * @see The ARM Architecture Refererence Manual (DDI 0487A) 95 * 96 */ 97class PMU : public SimObject, public ArmISA::BaseISADevice { 98 public: 99 PMU(const ArmPMUParams *p); 100 ~PMU(); 101 102 void addEventProbe(unsigned int id, SimObject *obj, const char *name); 103 void addSoftwareIncrementEvent(unsigned int id); 104 105 void registerEvent(uint32_t id); 106 107 public: // SimObject and related interfaces 108 void serialize(CheckpointOut &cp) const override; 109 void unserialize(CheckpointIn &cp) override; 110 111 void drainResume() override; 112 113 void regProbeListeners() override; 114 115 public: // ISA Device interface 116 void setThreadContext(ThreadContext *tc) override; 117 118 /** 119 * Set a register within the PMU. 120 * 121 * @param misc_reg Register number (see miscregs.hh) 122 * @param val Value to store 123 */ 124 void setMiscReg(int misc_reg, MiscReg val) override; 125 /** 126 * Read a register within the PMU. 127 * 128 * @param misc_reg Register number (see miscregs.hh) 129 * @return Register value. 130 */ 131 MiscReg readMiscReg(int misc_reg) override; 132 133 protected: // PMU register types and constants 134 BitUnion32(PMCR_t) 135 // PMU Enable 136 Bitfield<0> e; 137 // Event counter reset 138 Bitfield<1> p; 139 // Cycle counter reset 140 Bitfield<2> c; 141 // Cycle counter divider enable 142 Bitfield<3> d; 143 // Export enable 144 Bitfield<4> x; 145 // Disable PMCCNTR when event counting is prohibited 146 Bitfield<5> dp; 147 // Long Cycle counter enable 148 Bitfield<6> lc; 149 // Number of event counters implemented 150 Bitfield<15, 11> n; 151 // Implementation ID 152 Bitfield<23, 16> idcode; 153 // Implementer code 154 Bitfield<31, 24> imp; 155 EndBitUnion(PMCR_t) 156 157 BitUnion32(PMSELR_t) 158 // Performance counter selector 159 Bitfield<4, 0> sel; 160 EndBitUnion(PMSELR_t) 161 162 BitUnion32(PMEVTYPER_t) 163 Bitfield<15, 0> evtCount; 164 165 // Secure EL3 filtering 166 Bitfield<26> m; 167 // Non-secure EL2 mode filtering 168 Bitfield<27> nsh; 169 // Non-secure EL0 mode filtering 170 Bitfield<28> nsu; 171 // Non-secure EL1 mode filtering 172 Bitfield<29> nsk; 173 // EL0 filtering 174 Bitfield<30> u; 175 // EL1 filtering 176 Bitfield<31> p; 177 EndBitUnion(PMEVTYPER_t) 178 179 /** 180 * Counter ID within the PMU. 181 * 182 * This value is typically used to index into various registers 183 * controlling interrupts and overflows. The value normally in the 184 * [0, 31] range, where 31 refers to the cycle counter. 185 */ 186 typedef unsigned int CounterId; 187 188 /** Cycle Count Register Number */ 189 static const CounterId PMCCNTR = 31; 190 191 /** 192 * Event type ID. 193 * 194 * See the PMU documentation for a list of architected IDs. 195 */ 196 typedef unsigned int EventTypeId; 197 198 protected: /* High-level register and interrupt handling */ 199 MiscReg readMiscRegInt(int misc_reg); 200 201 /** 202 * PMCR write handling 203 * 204 * The PMCR register needs special handling since writing to it 205 * changes PMU-global state (e.g., resets all counters). 206 * 207 * @param val New PMCR value 208 */ 209 void setControlReg(PMCR_t val); 210 211 /** 212 * Reset all event counters excluding the cycle counter to zero. 213 */ 214 void resetEventCounts(); 215 216 /** 217 * Deliver a PMU interrupt to the GIC 218 */ 219 void raiseInterrupt(); 220 221 /** 222 * Get the value of a performance counter. 223 * 224 * This method returns the value of a general purpose performance 225 * counter or the fixed-function cycle counter. Non-existing 226 * counters are treated as constant '0'. 227 * 228 * @return Value of the performance counter, 0 if the counter does 229 * not exist. 230 */ 231 uint64_t getCounterValue(CounterId id) const { 232 return isValidCounter(id) ? getCounter(id).getValue() : 0; 233 } 234 235 /** 236 * Set the value of a performance counter. 237 * 238 * This method sets the value of a general purpose performance 239 * counter or the fixed-function cycle counter. Writes to 240 * non-existing counters are ignored. 241 */ 242 void setCounterValue(CounterId id, uint64_t val); 243 244 /** 245 * Get the type and filter settings of a counter (PMEVTYPER) 246 * 247 * This method implements a read from a PMEVTYPER register. It 248 * returns the type value and filter settings of a general purpose 249 * performance counter or the cycle counter. Non-existing counters 250 * are treated as constant '0'. 251 * 252 * @param id Counter ID within the PMU. 253 * @return Performance counter type ID. 254 */ 255 PMEVTYPER_t getCounterTypeRegister(CounterId id) const; 256 257 /** 258 * Set the type and filter settings of a performance counter 259 * (PMEVTYPER) 260 * 261 * This method implements a write to a PMEVTYPER register. It sets 262 * the type value and filter settings of a general purpose 263 * performance counter or the cycle counter. Writes to 264 * non-existing counters are ignored. The method automatically 265 * updates the probes used by the counter if it is enabled. 266 * 267 * @param id Counter ID within the PMU. 268 * @param type Performance counter type and filter configuration.. 269 */ 270 void setCounterTypeRegister(CounterId id, PMEVTYPER_t type); 271 272 protected: /* Probe handling and counter state */ 273 struct CounterState; 274 275 /** 276 * Event definition base class 277 */ 278 struct PMUEvent { 279 280 PMUEvent() {} 281 282 virtual ~PMUEvent() {} 283 284 /** 285 * attach this event to a given counter 286 * 287 * @param a pointer to the counter where to attach this event 288 */ 289 void attachEvent(PMU::CounterState *user); 290 291 /** 292 * detach this event from a given counter 293 * 294 * @param a pointer to the counter where to detach this event from 295 */ 296 void detachEvent(PMU::CounterState *user); 297 298 /** 299 * notify an event increment of val units, all the attached counters' 300 * value is incremented by val units. 301 * 302 * @param the quantity by which to increment the attached counter 303 * values 304 */ 305 virtual void increment(const uint64_t val); 306 307 /** 308 * Enable the current event 309 */ 310 virtual void enable() = 0; 311 312 /** 313 * Disable the current event 314 */ 315 virtual void disable() = 0; 316 317 /** 318 * Method called immediately before a counter access in order for 319 * the associated event to update its state (if required) 320 */ 321 virtual void updateAttachedCounters() {} 322 323 protected: 324 325 /** set of counters using this event **/ 326 std::set<PMU::CounterState*> userCounters; 327 }; 328 329 struct RegularEvent : public PMUEvent { 330 typedef std::pair<SimObject*, std::string> EventTypeEntry; 331 332 void addMicroarchitectureProbe(SimObject* object, 333 std::string name) { 334 335 panic_if(!object,"malformed probe-point" 336 " definition with name %s\n", name); 337 338 microArchitectureEventSet.emplace(object, name); 339 } 340 341 protected: 342 struct RegularProbe: public ProbeListenerArgBase<uint64_t> 343 { 344 RegularProbe(RegularEvent *parent, SimObject* obj, 345 std::string name) 346 : ProbeListenerArgBase(obj->getProbeManager(), name), 347 parentEvent(parent) {} 348 349 RegularProbe() = delete; 350 351 void notify(const uint64_t &val); 352 353 protected: 354 RegularEvent *parentEvent; 355 }; 356 357 /** The set of events driving the event value **/ 358 std::set<EventTypeEntry> microArchitectureEventSet; 359 360 /** Set of probe listeners tapping onto each of the input micro-arch 361 * events which compose this pmu event 362 */ 363 std::vector<std::unique_ptr<RegularProbe>> attachedProbePointList; 364 365 void enable() override; 366 367 void disable() override; 368 }; 369 370 class SWIncrementEvent : public PMUEvent 371 { 372 void enable() override {} 373 void disable() override {} 374 375 public: 376 377 /** 378 * write on the sw increment register inducing an increment of the 379 * counters with this event selected according to the bitfield written. 380 * 381 * @param the bitfield selecting the counters to increment. 382 */ 383 void write(uint64_t val); 384 }; 385 386 /** 387 * Obtain the event of a given id 388 * 389 * @param the id of the event to obtain 390 * @return a pointer to the event with id eventId 391 */ 392 PMUEvent* getEvent(uint64_t eventId); 393 394 /** State of a counter within the PMU. **/ 395 struct CounterState : public Serializable { 396 CounterState(PMU &pmuReference, uint64_t counter_id) 397 : eventId(0), filter(0), enabled(false), 398 overflow64(false), sourceEvent(nullptr), 399 counterId(counter_id), value(0), resetValue(false), 400 pmu(pmuReference) {} 401 402 void serialize(CheckpointOut &cp) const override; 403 void unserialize(CheckpointIn &cp) override; 404 405 /** 406 * Add an event count to the counter and check for overflow. 407 * 408 * @param delta Number of events to add to the counter. 409 * @return the quantity remaining until a counter overflow occurs. 410 */ 411 uint64_t add(uint64_t delta); 412 413 bool isFiltered() const; 414 415 /** 416 * Detach the counter from its event 417 */ 418 void detach(); 419 420 /** 421 * Attach this counter to an event 422 * 423 * @param the event to attach the counter to 424 */ 425 void attach(PMUEvent* event); 426 427 /** 428 * Obtain the counter id 429 * 430 * @return the pysical counter id 431 */ 432 uint64_t getCounterId() const{ 433 return counterId; 434 } 435 436 /** 437 * rReturn the counter value 438 * 439 * @return the counter value 440 */ 441 uint64_t getValue() const; 442 443 /** 444 * overwrite the value of the counter 445 * 446 * @param the new counter value 447 */ 448 void setValue(uint64_t val); 449 450 public: /* Serializable state */ 451 /** Counter event ID */ 452 EventTypeId eventId; 453 454 /** Filtering settings (evtCount is unused) */ 455 PMEVTYPER_t filter; 456 457 /** Is the counter enabled? */ 458 bool enabled; 459 460 /** Is this a 64-bit counter? */ 461 bool overflow64; 462 463 protected: /* Configuration */ 464 /** PmuEvent currently in use (if any) **/ 465 PMUEvent *sourceEvent; 466 467 /** id of the counter instance **/ 468 uint64_t counterId; 469 470 /** Current value of the counter */ 471 uint64_t value; 472 473 /** Flag keeping track if the counter has been reset **/ 474 bool resetValue; 475 476 PMU &pmu; 477 478 template <typename ...Args> 479 void debugCounter(const char* mainString, Args &...args) const { 480 481 std::string userString = csprintf(mainString, args...); 482 483 warn("[counterId = %d, eventId = %d, sourceEvent = 0x%x] %s", 484 counterId, eventId, sourceEvent, userString.c_str()); 485 486 } 487 }; 488 489 /** 490 * Is this a valid counter ID? 491 * 492 * @param id ID of counter within the PMU. 493 * 494 * @return true if counter is within the allowed range or the 495 * cycle counter, false otherwise. 496 */ 497 bool isValidCounter(CounterId id) const { 498 return id < counters.size() || id == PMCCNTR; 499 } 500 501 /** 502 * Return the state of a counter. 503 * 504 * @param id ID of counter within the PMU. 505 * @return Reference to a CounterState instance representing the 506 * counter. 507 */ 508 CounterState &getCounter(CounterId id) { 509 assert(isValidCounter(id)); 510 return id == PMCCNTR ? cycleCounter : counters[id]; 511 } 512 513 /** 514 * Return the state of a counter. 515 * 516 * @param id ID of counter within the PMU. 517 * @return Reference to a CounterState instance representing the 518 * counter. 519 */ 520 const CounterState &getCounter(CounterId id) const { 521 assert(isValidCounter(id)); 522 return id == PMCCNTR ? cycleCounter : counters[id]; 523 } 524 525 /** 526 * Depending on counter configuration, add or remove the probes 527 * driving the counter. 528 * 529 * Look at the state of a counter and (re-)attach the probes 530 * needed to drive a counter if it is currently active. All probes 531 * for the counter are detached if the counter is inactive. 532 * 533 * @param id ID of counter within the PMU. 534 * @param ctr Reference to the counter's state 535 */ 536 void updateCounter(CounterState &ctr); 537 538 /** 539 * Check if a counter's settings allow it to be counted. 540 * 541 * @param ctr Counter state instance representing this counter. 542 * @return false if the counter is active, true otherwise. 543 */ 544 bool isFiltered(const CounterState &ctr) const; 545 546 /** 547 * Call updateCounter() for each counter in the PMU if the 548 * counter's state has changed.. 549 * 550 * @see updateCounter() 551 */ 552 void updateAllCounters(); 553 554 protected: /* State that needs to be serialized */ 555 /** Performance Monitor Count Enable Register */ 556 MiscReg reg_pmcnten; 557 558 /** Performance Monitor Control Register */ 559 PMCR_t reg_pmcr; 560 561 /** Performance Monitor Selection Register */ 562 PMSELR_t reg_pmselr; 563 564 /** Performance Monitor Interrupt Enable Register */ 565 MiscReg reg_pminten; 566 567 /** Performance Monitor Overflow Status Register */ 568 MiscReg reg_pmovsr; 569 570 /** 571 * Performance counter ID register 572 * 573 * These registers contain a bitmask of available architected 574 * counters. 575 */ 576 uint64_t reg_pmceid0; 577 uint64_t reg_pmceid1; 578 579 /** Remainder part when the clock counter is divided by 64 */ 580 unsigned clock_remainder; 581 582 /** The number of regular event counters **/ 583 uint64_t maximumCounterCount; 584 585 /** State of all general-purpose counters supported by PMU */ 586 std::vector<CounterState> counters; 587 588 /** State of the cycle counter */ 589 CounterState cycleCounter; 590 591 /** The id of the counter hardwired to the cpu cycle counter **/ 592 const uint64_t cycleCounterEventId; 593 594 /** The event that implements the software increment **/ 595 SWIncrementEvent *swIncrementEvent; 596 597 protected: /* Configuration and constants */ 598 /** Constant (configuration-dependent) part of the PMCR */ 599 PMCR_t reg_pmcr_conf; 600 601 /** PMCR write mask when accessed from the guest */ 602 static const MiscReg reg_pmcr_wr_mask; 603 604 /** Performance monitor interrupt number */ 605 ArmInterruptPin *const interrupt; 606 607 /** 608 * List of event types supported by this PMU. 609 */ 610 std::map<EventTypeId, PMUEvent*> eventMap; 611}; 612 613} // namespace ArmISA 614#endif 615