pmu.hh revision 12286:fb69c03c88e1
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