pmu.hh revision 10905:a6ca6831e775
1/*
2 * Copyright (c) 2011-2014 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 "sim/probe/probe.hh"
51#include "sim/sim_object.hh"
52
53class ArmPMUParams;
54class Platform;
55class ThreadContext;
56
57namespace ArmISA {
58
59
60/**
61 * Model of an ARM PMU version 3
62 *
63 * This class implements a subset of the ARM PMU v3 specification as
64 * described in the ARMv8 reference manual. It supports most of the
65 * features of the PMU, however the following features are known to be
66 * missing:
67 *
68 * <ul>
69 *   <li>Event filtering (e.g., from different privilege levels).
70 *   <li>Access controls (the PMU currently ignores the execution level).
71 *   <li>The chain counter (event no. 0x1E) is unimplemented.
72 * </ul>
73 *
74 * The PMU itself does not implement any events, in merely provides an
75 * interface for the configuration scripts to hook up probes that
76 * drive events. Configuration scripts should call addEventProbe() to
77 * configure custom events or high-level methods to configure
78 * architected events. The Python implementation of addEventProbe()
79 * automatically delays event type registration until after
80 * instantiation.
81 *
82 * In order to support CPU switching and some combined counters (e.g.,
83 * memory references synthesized from loads and stores), the PMU
84 * allows multiple probes per event type. When creating a system that
85 * switches between CPU models that share the same PMU, PMU events for
86 * all of the CPU models can be registered with the PMU.
87 *
88 * @see The ARM Architecture Refererence Manual (DDI 0487A)
89 *
90 */
91class PMU : public SimObject, public ArmISA::BaseISADevice {
92  public:
93    PMU(const ArmPMUParams *p);
94    ~PMU();
95
96    void addEventProbe(unsigned int id, SimObject *obj, const char *name);
97
98  public: // SimObject and related interfaces
99    void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
100    void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
101
102    void drainResume() M5_ATTR_OVERRIDE;
103
104
105  public: // ISA Device interface
106    /**
107     * Set a register within the PMU.
108     *
109     * @param misc_reg Register number (see miscregs.hh)
110     * @param val Value to store
111     */
112    void setMiscReg(int misc_reg, MiscReg val) M5_ATTR_OVERRIDE;
113    /**
114     * Read a register within the PMU.
115     *
116     * @param misc_reg Register number (see miscregs.hh)
117     * @return Register value.
118     */
119    MiscReg readMiscReg(int misc_reg) M5_ATTR_OVERRIDE;
120
121  protected: // PMU register types and constants
122    BitUnion32(PMCR_t)
123        // PMU Enable
124        Bitfield<0> e;
125        // Event counter reset
126        Bitfield<1> p;
127        // Cycle counter reset
128        Bitfield<2> c;
129        // Cycle counter divider enable
130        Bitfield<3> d;
131        // Export enable
132        Bitfield<4> x;
133        // Disable PMCCNTR when event counting is prohibited
134        Bitfield<5> dp;
135        // Long Cycle counter enable
136        Bitfield<6> lc;
137        // Number of event counters implemented
138        Bitfield<15, 11> n;
139        // Implementation ID
140        Bitfield<23, 16> idcode;
141        // Implementer code
142        Bitfield<31, 24> imp;
143    EndBitUnion(PMCR_t)
144
145    BitUnion32(PMSELR_t)
146        // Performance counter selector
147        Bitfield<4, 0> sel;
148    EndBitUnion(PMSELR_t)
149
150    BitUnion32(PMEVTYPER_t)
151        Bitfield<9, 0> evtCount;
152
153        // Secure EL3 filtering
154        Bitfield<26> m;
155        // Non-secure EL2 mode filtering
156        Bitfield<27> nsh;
157        // Non-secure EL0 mode filtering
158        Bitfield<28> nsu;
159        // Non-secure EL1 mode filtering
160        Bitfield<29> nsk;
161        // EL0 filtering
162        Bitfield<30> u;
163        // EL1 filtering
164        Bitfield<31> p;
165    EndBitUnion(PMEVTYPER_t)
166
167    /**
168     * Counter ID within the PMU.
169     *
170     * This value is typically used to index into various registers
171     * controlling interrupts and overflows. The value normally in the
172     * [0, 31] range, where 31 refers to the cycle counter.
173     */
174    typedef unsigned int CounterId;
175
176    /** Cycle Count Register Number */
177    static const CounterId PMCCNTR = 31;
178
179    /**
180     * Event type ID.
181     *
182     * See the PMU documentation for a list of architected IDs.
183     */
184    typedef unsigned int EventTypeId;
185
186    /** ID of the software increment event */
187    static const EventTypeId ARCH_EVENT_SW_INCR = 0x00;
188
189  protected: /* High-level register and interrupt handling */
190    MiscReg readMiscRegInt(int misc_reg);
191
192    /**
193     * PMCR write handling
194     *
195     * The PMCR register needs special handling since writing to it
196     * changes PMU-global state (e.g., resets all counters).
197     *
198     * @param val New PMCR value
199     */
200    void setControlReg(PMCR_t val);
201
202    /**
203     * Reset all event counters excluding the cycle counter to zero.
204     */
205    void resetEventCounts();
206
207    /**
208     * Deliver a PMU interrupt to the GIC
209     */
210    void raiseInterrupt();
211
212    /**
213     * Get the value of a performance counter.
214     *
215     * This method returns the value of a general purpose performance
216     * counter or the fixed-function cycle counter. Non-existing
217     * counters are treated as constant '0'.
218     *
219     * @return Value of the performance counter, 0 if the counter does
220     * not exist.
221     */
222    uint64_t getCounterValue(CounterId id) const {
223        return isValidCounter(id) ? getCounter(id).value : 0;
224    }
225
226    /**
227     * Set the value of a performance counter.
228     *
229     * This method sets the value of a general purpose performance
230     * counter or the fixed-function cycle counter. Writes to
231     * non-existing counters are ignored.
232     */
233    void setCounterValue(CounterId id, uint64_t val);
234
235    /**
236     * Get the type and filter settings of a counter (PMEVTYPER)
237     *
238     * This method implements a read from a PMEVTYPER register. It
239     * returns the type value and filter settings of a general purpose
240     * performance counter or the cycle counter. Non-existing counters
241     * are treated as constant '0'.
242     *
243     * @param id Counter ID within the PMU.
244     * @return Performance counter type ID.
245     */
246    PMEVTYPER_t getCounterTypeRegister(CounterId id) const;
247
248    /**
249     * Set the type and filter settings of a performance counter
250     * (PMEVTYPER)
251     *
252     * This method implements a write to a PMEVTYPER register. It sets
253     * the type value and filter settings of a general purpose
254     * performance counter or the cycle counter. Writes to
255     * non-existing counters are ignored. The method automatically
256     * updates the probes used by the counter if it is enabled.
257     *
258     * @param id Counter ID within the PMU.
259     * @param type Performance counter type and filter configuration..
260     */
261    void setCounterTypeRegister(CounterId id, PMEVTYPER_t type);
262
263  protected: /* Probe handling and counter state */
264    class ProbeListener : public ProbeListenerArgBase<uint64_t>
265    {
266      public:
267        ProbeListener(PMU &_pmu, CounterId _id,
268                      ProbeManager *pm, const std::string &name)
269            : ProbeListenerArgBase(pm, name),
270              pmu(_pmu), id(_id) {}
271
272        void notify(const uint64_t &val) M5_ATTR_OVERRIDE
273        {
274            pmu.handleEvent(id, val);
275        }
276
277      protected:
278        PMU &pmu;
279        const CounterId id;
280    };
281    typedef std::unique_ptr<ProbeListener> ProbeListenerUPtr;
282
283    /**
284     * Event type configuration
285     *
286     * The main purpose of this class is to describe how a PMU event
287     * type is sampled. It is implemented as a probe factory that
288     * returns a probe attached to the object the event is mointoring.
289     */
290    struct EventType {
291        /**
292         * @param _obj Target SimObject
293         * @param _name Probe name
294         */
295        EventType(SimObject *_obj, const std::string &_name)
296            : obj(_obj), name(_name) {}
297
298        /**
299         * Create and attach a probe used to drive this event.
300         *
301         * @param pmu PMU owning the probe.
302         * @param CounterID counter ID within the PMU.
303         * @return Pointer to a probe listener.
304         */
305        std::unique_ptr<ProbeListener> create(PMU &pmu, CounterId cid) const
306        {
307            std::unique_ptr<ProbeListener> ptr;
308            ptr.reset(new ProbeListener(pmu, cid,
309                                        obj->getProbeManager(), name));
310            return ptr;
311        }
312
313        /** SimObject being measured by this probe */
314        SimObject *const obj;
315        /** Probe name within obj */
316        const std::string name;
317
318      private:
319        // Disable the default constructor
320        EventType();
321    };
322
323    /** State of a counter within the PMU. */
324    struct CounterState : public Serializable {
325        CounterState()
326            : eventId(0), filter(0), value(0), enabled(false),
327              overflow64(false) {
328
329            listeners.reserve(4);
330        }
331
332        void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
333        void unserialize(CheckpointIn &cp)  M5_ATTR_OVERRIDE;
334
335        /**
336         * Add an event count to the counter and check for overflow.
337         *
338         * @param delta Number of events to add to the counter.
339         * @return true on overflow, false otherwise.
340         */
341        bool add(uint64_t delta);
342
343      public: /* Serializable state */
344        /** Counter event ID */
345        EventTypeId eventId;
346
347        /** Filtering settings (evtCount is unused) */
348        PMEVTYPER_t filter;
349
350        /** Current value of the counter */
351        uint64_t value;
352
353        /** Is the counter enabled? */
354        bool enabled;
355
356        /** Is this a 64-bit counter? */
357        bool overflow64;
358
359      public: /* Configuration */
360        /** Probe listeners driving this counter */
361        std::vector<ProbeListenerUPtr> listeners;
362    };
363
364    /**
365     * Handle an counting event triggered by a probe.
366     *
367     * This method is called by the ProbeListener class whenever an
368     * active probe is triggered. Ths method adds the event count from
369     * the probe to the affected counter, checks for overflows, and
370     * delivers an interrupt if needed.
371     *
372     * @param id Counter ID affected by the probe.
373     * @param delta Counter increment
374     */
375    void handleEvent(CounterId id, uint64_t delta);
376
377    /**
378     * Is this a valid counter ID?
379     *
380     * @param id ID of counter within the PMU.
381     *
382     * @return true if counter is within the allowed range or the
383     * cycle counter, false otherwise.
384     */
385    bool isValidCounter(CounterId id) const {
386        return id < counters.size() || id == PMCCNTR;
387    }
388
389    /**
390     * Return the state of a counter.
391     *
392     * @param id ID of counter within the PMU.
393     * @return Reference to a CounterState instance representing the
394     * counter.
395     */
396    CounterState &getCounter(CounterId id) {
397        assert(isValidCounter(id));
398        return id == PMCCNTR ? cycleCounter : counters[id];
399    }
400
401
402    /**
403     * Return the state of a counter.
404     *
405     * @param id ID of counter within the PMU.
406     * @return Reference to a CounterState instance representing the
407     * counter.
408     */
409    const CounterState &getCounter(CounterId id) const {
410        assert(isValidCounter(id));
411        return id == PMCCNTR ? cycleCounter : counters[id];
412    }
413
414    /**
415     * Depending on counter configuration, add or remove the probes
416     * driving the counter.
417     *
418     * Look at the state of a counter and (re-)attach the probes
419     * needed to drive a counter if it is currently active. All probes
420     * for the counter are detached if the counter is inactive.
421     *
422     * @param id ID of counter within the PMU.
423     * @param ctr Reference to the counter's state
424     */
425    void updateCounter(CounterId id, CounterState &ctr);
426
427    /**
428     * Check if a counter's settings allow it to be counted.
429     *
430     * @param ctr Counter state instance representing this counter.
431     * @return false if the counter is active, true otherwise.
432     */
433    bool isFiltered(const CounterState &ctr) const;
434
435    /**
436     * Call updateCounter() for each counter in the PMU if the
437     * counter's state has changed..
438     *
439     * @see updateCounter()
440     */
441    void updateAllCounters();
442
443  protected: /* State that needs to be serialized */
444    /** Performance Monitor Count Enable Register */
445    MiscReg reg_pmcnten;
446
447    /** Performance Monitor Control Register */
448    PMCR_t reg_pmcr;
449
450    /** Performance Monitor Selection Register */
451    PMSELR_t reg_pmselr;
452
453    /** Performance Monitor Interrupt Enable Register */
454    MiscReg reg_pminten;
455
456    /** Performance Monitor Overflow Status Register */
457    MiscReg reg_pmovsr;
458
459    /**
460     * Performance counter ID register
461     *
462     * This register contains a bitmask of available architected
463     * counters.
464     */
465    uint64_t reg_pmceid;
466
467    /** Remainder part when the clock counter is divided by 64 */
468    unsigned clock_remainder;
469
470    /** State of all general-purpose counters supported by PMU */
471    std::vector<CounterState> counters;
472    /** State of the cycle counter */
473    CounterState cycleCounter;
474
475  protected: /* Configuration and constants */
476    /** Constant (configuration-dependent) part of the PMCR */
477    PMCR_t reg_pmcr_conf;
478    /** PMCR write mask when accessed from the guest */
479    static const MiscReg reg_pmcr_wr_mask;
480
481    /** Performance monitor interrupt number */
482    const unsigned int pmuInterrupt;
483    /** Platform this device belongs to */
484    Platform *const platform;
485
486    /**
487     * Event types supported by this PMU.
488     *
489     * Each event type ID can map to multiple EventType structures,
490     * which enables the PMU to use multiple probes for a single
491     * event. This can be useful in the following cases:
492     * <ul>
493     *   <li>Some events can are increment by multiple different probe
494     *       points (e.g., the CPU memory access counter gets
495     *       incremented for both loads and stores).
496     *
497     *   <li>A system switching between multiple CPU models can
498     *       register events for all models that will execute a thread
499     *       and tehreby ensure that the PMU continues to work.
500     * </ul>
501     */
502    std::multimap<EventTypeId, EventType> pmuEventTypes;
503};
504
505} // namespace ArmISA
506#endif
507