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