perfevent.hh revision 9986
12SN/A/*
210298Salexandru.dutu@amd.com * Copyright (c) 2012 ARM Limited
31762SN/A * All rights reserved
42SN/A *
52SN/A * The license below extends only to copyright in the software and shall
62SN/A * not be construed as granting a license to any other intellectual
72SN/A * property including but not limited to intellectual property relating
82SN/A * to a hardware implementation of the functionality of the software
92SN/A * licensed hereunder.  You may use the software subject to the license
102SN/A * terms below provided that you ensure that this notice is replicated
112SN/A * unmodified and in its entirety in all distributions of the software,
122SN/A * modified or unmodified, in source code or in binary form.
132SN/A *
142SN/A * Redistribution and use in source and binary forms, with or without
152SN/A * modification, are permitted provided that the following conditions are
162SN/A * met: redistributions of source code must retain the above copyright
172SN/A * notice, this list of conditions and the following disclaimer;
182SN/A * redistributions in binary form must reproduce the above copyright
192SN/A * notice, this list of conditions and the following disclaimer in the
202SN/A * documentation and/or other materials provided with the distribution;
212SN/A * neither the name of the copyright holders nor the names of its
222SN/A * contributors may be used to endorse or promote products derived from
232SN/A * this software without specific prior written permission.
242SN/A *
252SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302665Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610930Sbrandon.potter@amd.com *
374117Sgblack@eecs.umich.edu * Authors: Andreas Sandberg
38180SN/A */
392SN/A
406329Sgblack@eecs.umich.edu#ifndef __CPU_KVM_PERFEVENT_HH__
412378SN/A#define __CPU_KVM_PERFEVENT_HH__
426214Snate@binkert.org
436658Snate@binkert.org#include <linux/perf_event.h>
448852Sandreas.hansson@arm.com#include <sys/types.h>
4510930Sbrandon.potter@amd.com
4656SN/A#include <inttypes.h>
475958Sgblack@eecs.umich.edu
482SN/A#include "config/have_perf_attr_exclude_host.hh"
495154Sgblack@eecs.umich.edu
508737Skoansin.tan@gmail.com/**
518737Skoansin.tan@gmail.com * PerfEvent counter configuration.
525154Sgblack@eecs.umich.edu */
535154Sgblack@eecs.umich.educlass PerfKvmCounterConfig
542680Sktlim@umich.edu{
5510496Ssteve.reinhardt@amd.com  public:
562378SN/A    /**
575758Shsul@eecs.umich.edu     * Initialize PerfEvent counter configuration structure
585771Shsul@eecs.umich.edu     *
595758Shsul@eecs.umich.edu     * PerfEvent has the concept of counter types, which is a way to
605758Shsul@eecs.umich.edu     * abstract hardware performance counters or access software
615771Shsul@eecs.umich.edu     * events. The type field in the configuration specifies what type
625758Shsul@eecs.umich.edu     * of counter this is. For hardware performance counters, it's
635771Shsul@eecs.umich.edu     * typically PERF_TYPE_HARDWARE, PERF_TYPE_HW_CACHE, or
645758Shsul@eecs.umich.edu     * PERF_TYPE_RAW.
655758Shsul@eecs.umich.edu     *
665771Shsul@eecs.umich.edu     * The 'config' field has different meanings depending on the type
675758Shsul@eecs.umich.edu     * of counter. Possible values are listed in perf_event.h in the
685758Shsul@eecs.umich.edu     * kernel headers. When using raw counters, the value is the raw
692SN/A     * value written to the performance counter configuration register
702SN/A     * (some bits dealing with sampling and similar features are
712SN/A     * usually masked).
722SN/A     *
732378SN/A     * @param type Counter type.
742378SN/A     * @param config Counter configuration
752378SN/A     */
762378SN/A    PerfKvmCounterConfig(uint32_t type, uint64_t config);
772680Sktlim@umich.edu    ~PerfKvmCounterConfig();
7811005Sandreas.sandberg@arm.com
79180SN/A    /**
80180SN/A     * Set the initial sample period (overflow count) of an event. If
815713Shsul@eecs.umich.edu     * this is set to 0, the event acts as a normal counting event and
822SN/A     * does not trigger overflows.
832SN/A     *
842SN/A     * @param period Number of counter events before the counter
852SN/A     * overflows
862SN/A     */
872680Sktlim@umich.edu    PerfKvmCounterConfig &samplePeriod(uint64_t period) {
882SN/A        attr.freq = 0;
892680Sktlim@umich.edu        attr.sample_period = period;
902SN/A        return *this;
915543Ssaidi@eecs.umich.edu    }
922SN/A
932SN/A    /**
942SN/A     * Set the number of samples that need to be triggered before
952SN/A     * reporting data as being available on the perf event
962SN/A     * FD. Defaults to 0, which disables overflow reporting.
975543Ssaidi@eecs.umich.edu     *
982SN/A     * @param events Number of overflows before signaling a wake up
995543Ssaidi@eecs.umich.edu     */
1005543Ssaidi@eecs.umich.edu    PerfKvmCounterConfig &wakeupEvents(uint32_t events) {
1015543Ssaidi@eecs.umich.edu        attr.watermark = 0;
1022SN/A        attr.wakeup_events = events;
1035154Sgblack@eecs.umich.edu        return *this;
1045154Sgblack@eecs.umich.edu    }
1055154Sgblack@eecs.umich.edu
1062SN/A    /**
1072SN/A     * Don't start the performance counter automatically when
1082SN/A     * attaching it.
109360SN/A     *
1101408SN/A     * @param val true to disable, false to enable the counter
1111408SN/A     */
112360SN/A    PerfKvmCounterConfig &disabled(bool val) {
1131514SN/A        attr.disabled = val;
1141514SN/A        return *this;
1151514SN/A    }
1161514SN/A
1175999Snate@binkert.org    /**
1182SN/A     * Force the group to be on the active all the time (i.e.,
1192SN/A     * disallow multiplexing).
1202SN/A     *
1218325Ssteve.reinhardt@amd.com     * Only applies to group leaders.
1222SN/A     *
1237532Ssteve.reinhardt@amd.com     * @param val true to pin the counter
1242SN/A     */
12510913Sandreas.sandberg@arm.com    PerfKvmCounterConfig &pinned(bool val) {
12610905Sandreas.sandberg@arm.com        attr.pinned = val;
1272378SN/A        return *this;
1282SN/A    }
1294997Sgblack@eecs.umich.edu
1304997Sgblack@eecs.umich.edu    /**
1314997Sgblack@eecs.umich.edu     * Exclude the events from the host (i.e., only include events
1324997Sgblack@eecs.umich.edu     * from the guest system).
13310299Salexandru.dutu@amd.com     *
13410299Salexandru.dutu@amd.com     * Intel CPUs seem to support this attribute from Linux 3.2 and
13510554Salexandru.dutu@amd.com     * onwards. Non-x86 architectures currently ignore this attribute
13610554Salexandru.dutu@amd.com     * (Linux 3.12-rc5).
13710554Salexandru.dutu@amd.com     *
13810298Salexandru.dutu@amd.com     * @warn This attribute is ignored if it isn't present in the
1398852Sandreas.hansson@arm.com     * kernel headers or if the kernel doesn't support it.
1408852Sandreas.hansson@arm.com     *
1418852Sandreas.hansson@arm.com     * @param val true to exclude host events
1428852Sandreas.hansson@arm.com     */
1438852Sandreas.hansson@arm.com    PerfKvmCounterConfig &exclude_host(bool val) {
1442SN/A#if HAVE_PERF_ATTR_EXCLUDE_HOST == 1
14510929Sbrandon.potter@amd.com        attr.exclude_host = val;
1465282Srstrong@cs.ucsd.edu#endif
14710929Sbrandon.potter@amd.com        return *this;
14810930Sbrandon.potter@amd.com    }
14910930Sbrandon.potter@amd.com
15010930Sbrandon.potter@amd.com    /**
15110930Sbrandon.potter@amd.com     * Exclude the hyper visor (i.e., only include events from the
15210930Sbrandon.potter@amd.com     * guest system).
1532SN/A     *
1542SN/A     * @warn This is attribute only seems to be ignored on Intel.
15510930Sbrandon.potter@amd.com     *
15610932Sbrandon.potter@amd.com     * @param val true to exclude host events
1572SN/A     */
1582SN/A    PerfKvmCounterConfig &exclude_hv(bool val) {
1592SN/A        attr.exclude_hv = val;
1602SN/A        return *this;
1615713Shsul@eecs.umich.edu    }
1625713Shsul@eecs.umich.edu
16311005Sandreas.sandberg@arm.com    /** Underlying perf_event_attr structure describing the counter */
1645713Shsul@eecs.umich.edu    struct perf_event_attr attr;
1655713Shsul@eecs.umich.edu};
1665713Shsul@eecs.umich.edu
167180SN/A/**
1685713Shsul@eecs.umich.edu * An instance of a performance counter.
1698325Ssteve.reinhardt@amd.com */
1702SN/Aclass PerfKvmCounter
1719144Ssteve.reinhardt@amd.com{
1729144Ssteve.reinhardt@amd.compublic:
1739144Ssteve.reinhardt@amd.com    /**
1742SN/A     * Create and attach a new counter group.
17510932Sbrandon.potter@amd.com     *
17610932Sbrandon.potter@amd.com     * @param config Counter configuration
1771970SN/A     * @param tid Thread to sample (0 indicates current thread)
17810929Sbrandon.potter@amd.com     */
17910932Sbrandon.potter@amd.com    PerfKvmCounter(PerfKvmCounterConfig &config, pid_t tid);
1802SN/A    /**
1812SN/A     * Create and attach a new counter and make it a member of an
18210932Sbrandon.potter@amd.com     * exist counter group.
1832SN/A     *
18410930Sbrandon.potter@amd.com     * @param config Counter configuration
18510932Sbrandon.potter@amd.com     * @param tid Thread to sample (0 indicates current thread)
1865282Srstrong@cs.ucsd.edu     * @param parent Group leader
18710929Sbrandon.potter@amd.com     */
18810929Sbrandon.potter@amd.com    PerfKvmCounter(PerfKvmCounterConfig &config,
18910929Sbrandon.potter@amd.com                pid_t tid, const PerfKvmCounter &parent);
19010929Sbrandon.potter@amd.com    /**
19110929Sbrandon.potter@amd.com     * Create a new counter, but don't attach it.
19210932Sbrandon.potter@amd.com     */
19310929Sbrandon.potter@amd.com    PerfKvmCounter();
1945282Srstrong@cs.ucsd.edu    ~PerfKvmCounter();
19510932Sbrandon.potter@amd.com
1965282Srstrong@cs.ucsd.edu
1975282Srstrong@cs.ucsd.edu    /**
19810932Sbrandon.potter@amd.com     * Attach a counter.
1995282Srstrong@cs.ucsd.edu     *
2005282Srstrong@cs.ucsd.edu     * @note This operation is only supported if the counter isn't
2015282Srstrong@cs.ucsd.edu     * already attached.
2025282Srstrong@cs.ucsd.edu     *
2032680Sktlim@umich.edu     * @param config Counter configuration
2043311Ssaidi@eecs.umich.edu     * @param tid Thread to sample (0 indicates current thread)
2058601Ssteve.reinhardt@amd.com     */
2068601Ssteve.reinhardt@amd.com    void attach(PerfKvmCounterConfig &config, pid_t tid) {
2078539Sgblack@eecs.umich.edu        attach(config, tid, -1);
2088539Sgblack@eecs.umich.edu    }
2098539Sgblack@eecs.umich.edu
2104434Ssaidi@eecs.umich.edu    /**
2119110Ssteve.reinhardt@amd.com     * Attach a counter and make it a member of an existing counter
21210558Salexandru.dutu@amd.com     * group.
2139110Ssteve.reinhardt@amd.com     *
21410558Salexandru.dutu@amd.com     * @note This operation is only supported if the counter isn't
21510558Salexandru.dutu@amd.com     * already attached.
2169110Ssteve.reinhardt@amd.com     *
2179110Ssteve.reinhardt@amd.com     * @param config Counter configuration
2189110Ssteve.reinhardt@amd.com     * @param tid Thread to sample (0 indicates current thread)
2199110Ssteve.reinhardt@amd.com     * @param parent Group leader
22010558Salexandru.dutu@amd.com     */
2219110Ssteve.reinhardt@amd.com    void attach(PerfKvmCounterConfig &config,
2229110Ssteve.reinhardt@amd.com                pid_t tid, const PerfKvmCounter &parent) {
2239110Ssteve.reinhardt@amd.com        attach(config, tid, parent.fd);
22410558Salexandru.dutu@amd.com    }
2259110Ssteve.reinhardt@amd.com
22610905Sandreas.sandberg@arm.com    /** Detach a counter from PerfEvent. */
22710905Sandreas.sandberg@arm.com    void detach();
2282SN/A
2292SN/A    /** Check if a counter is attached. */
2302SN/A    bool attached() const { return fd != -1; }
2312SN/A
2322SN/A    /**
233360SN/A     * Start counting.
2342SN/A     *
2352SN/A     * @note If this counter is a group leader, it will start the
236360SN/A     * entire group.
2372378SN/A     */
2382378SN/A    void start();
2392378SN/A
2403669Sbinkertn@umich.edu    /**
24111140Sjthestness@gmail.com     * Stop counting.
2422378SN/A     *
2438325Ssteve.reinhardt@amd.com     * @note If this counter is a group leader, it will stop the
2442SN/A     * entire group.
2453114Sgblack@eecs.umich.edu     */
2463114Sgblack@eecs.umich.edu    void stop();
2473114Sgblack@eecs.umich.edu
2483114Sgblack@eecs.umich.edu    /**
2493114Sgblack@eecs.umich.edu     * Update the period of an overflow counter.
2503114Sgblack@eecs.umich.edu     *
2513114Sgblack@eecs.umich.edu     * @warning This ioctl has some pretty bizarre semantics. It seems
2523114Sgblack@eecs.umich.edu     * like the new period isn't effective until after the next
2533114Sgblack@eecs.umich.edu     * counter overflow. If you use this method to change the sample
2543114Sgblack@eecs.umich.edu     * period, you will see one sample with the old period and then
25510496Ssteve.reinhardt@amd.com     * start sampling with the new period. This problem was fixed for
25610496Ssteve.reinhardt@amd.com     * ARM in version 3.7 of the kernel.
25710496Ssteve.reinhardt@amd.com     *
258360SN/A     * @warning This method doesn't work at all on some 2.6.3x kernels
2593114Sgblack@eecs.umich.edu     * since it has inverted check for the return value when copying
2604793Sgblack@eecs.umich.edu     * parameters from userspace.
2614793Sgblack@eecs.umich.edu     *
2624793Sgblack@eecs.umich.edu     * @param period Overflow period in events
2634793Sgblack@eecs.umich.edu     */
2644793Sgblack@eecs.umich.edu    void period(uint64_t period);
2654793Sgblack@eecs.umich.edu
2664793Sgblack@eecs.umich.edu    /**
2674793Sgblack@eecs.umich.edu     * Enable a counter for a fixed number of events.
2684793Sgblack@eecs.umich.edu     *
2694793Sgblack@eecs.umich.edu     * When this method is called, perf event enables the counter if
2704793Sgblack@eecs.umich.edu     * it was disabled. It then leaves the counter enabled until it
2714793Sgblack@eecs.umich.edu     * has overflowed a refresh times.
2724793Sgblack@eecs.umich.edu     *
2734793Sgblack@eecs.umich.edu     * @note This does not update the period of the counter.
2744793Sgblack@eecs.umich.edu     *
2754793Sgblack@eecs.umich.edu     * @param refresh Number of overflows before disabling the
2764793Sgblack@eecs.umich.edu     * counter.
2774793Sgblack@eecs.umich.edu     */
2784793Sgblack@eecs.umich.edu    void refresh(int refresh);
2794793Sgblack@eecs.umich.edu
2804793Sgblack@eecs.umich.edu    /**
2814793Sgblack@eecs.umich.edu     * Read the current value of a counter.
2826399Sgblack@eecs.umich.edu     */
2836399Sgblack@eecs.umich.edu    uint64_t read() const;
2846399Sgblack@eecs.umich.edu
2856399Sgblack@eecs.umich.edu    /**
2864793Sgblack@eecs.umich.edu     * Enable signal delivery to a thread on counter overflow.
2874793Sgblack@eecs.umich.edu     *
2884793Sgblack@eecs.umich.edu     * @param tid Thread to deliver signal to
2894793Sgblack@eecs.umich.edu     * @param signal Signal to send upon overflow
2903114Sgblack@eecs.umich.edu     */
2913114Sgblack@eecs.umich.edu    void enableSignals(pid_t tid, int signal);
2923114Sgblack@eecs.umich.edu
2933114Sgblack@eecs.umich.edu    /**
2943114Sgblack@eecs.umich.edu     * Enable signal delivery on counter overflow. Identical to
2953114Sgblack@eecs.umich.edu     * enableSignals(pid_t) when called with the current TID as its
2963114Sgblack@eecs.umich.edu     * parameter.
2979144Ssteve.reinhardt@amd.com     *
29811140Sjthestness@gmail.com     * @param signal Signal to send upon overflow
2999144Ssteve.reinhardt@amd.com     */
3003669Sbinkertn@umich.edu    void enableSignals(int signal) { enableSignals(gettid(), signal); }
3013669Sbinkertn@umich.edu
3023669Sbinkertn@umich.eduprivate:
3033669Sbinkertn@umich.edu    // Disallow copying
3043669Sbinkertn@umich.edu    PerfKvmCounter(const PerfKvmCounter &that);
3053669Sbinkertn@umich.edu    // Disallow assignment
3063669Sbinkertn@umich.edu    PerfKvmCounter &operator=(const PerfKvmCounter &that);
3073669Sbinkertn@umich.edu
3083669Sbinkertn@umich.edu    void attach(PerfKvmCounterConfig &config, pid_t tid, int group_fd);
3093669Sbinkertn@umich.edu
3103669Sbinkertn@umich.edu    /**
3113669Sbinkertn@umich.edu     * Get the TID of the current thread.
3123669Sbinkertn@umich.edu     *
3133669Sbinkertn@umich.edu     * @return Current thread's TID
3145513SMichael.Adler@intel.com     */
3155513SMichael.Adler@intel.com    pid_t gettid();
3162680Sktlim@umich.edu
3176701Sgblack@eecs.umich.edu    /**
3186701Sgblack@eecs.umich.edu     * MMAP the PerfEvent file descriptor.
3196701Sgblack@eecs.umich.edu     *
3205958Sgblack@eecs.umich.edu     * @note We currently don't use the ring buffer, but PerfEvent
3215958Sgblack@eecs.umich.edu     * requires this to be mapped for overflow handling to work.
3225958Sgblack@eecs.umich.edu     *
3235958Sgblack@eecs.umich.edu     * @note Overflow handling requires at least one buf_page to be
3242093SN/A     * mapped.
3258325Ssteve.reinhardt@amd.com     *
3262715Sstever@eecs.umich.edu     * @param pages number of pages in circular sample buffer. Must be
32710496Ssteve.reinhardt@amd.com     * an even power of 2.
32810496Ssteve.reinhardt@amd.com     */
32910496Ssteve.reinhardt@amd.com    void mmapPerf(int pages);
33010496Ssteve.reinhardt@amd.com
33110496Ssteve.reinhardt@amd.com    /** @{ */
33210496Ssteve.reinhardt@amd.com    /**
33310496Ssteve.reinhardt@amd.com     * PerfEvent fnctl interface.
33410496Ssteve.reinhardt@amd.com     *
3352715Sstever@eecs.umich.edu     * @param cmd fcntl command
3362715Sstever@eecs.umich.edu     * @param p1 Request parameter
3372715Sstever@eecs.umich.edu     *
3388325Ssteve.reinhardt@amd.com     * @return -1 on error (error number in errno), ioctl dependent
3392SN/A     * value otherwise.
3402SN/A     */
341360SN/A    int fcntl(int cmd, long p1);
342360SN/A    int fcntl(int cmd, void *p1) { return fcntl(cmd, (long)p1); }
343    /** @} */
344
345    /** @{ */
346    /**
347     * PerfEvent ioctl interface.
348     *
349     * @param request PerfEvent request
350     * @param p1 Optional request parameter
351     *
352     * @return -1 on error (error number in errno), ioctl dependent
353     * value otherwise.
354     */
355    int ioctl(int request, long p1);
356    int ioctl(int request, void *p1) { return ioctl(request, (long)p1); }
357    int ioctl(int request) { return ioctl(request, 0L); }
358    /** @} */
359
360    /**
361     * Perform a read from the counter file descriptor.
362     *
363     * @param buf Destination buffer
364     * @param size Amount of data to read
365     */
366    void read(void *buf, size_t size) const;
367
368    /**
369     * PerfEvent file descriptor associated with counter. -1 if not
370     * attached to PerfEvent.
371     */
372    int fd;
373
374    /** Memory mapped PerfEvent sample ring buffer */
375    struct perf_event_mmap_page *ringBuffer;
376    /** Total number of pages in ring buffer */
377    int ringNumPages;
378
379    /** Cached host page size */
380    long pageSize;
381};
382
383#endif
384