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