19651SAndreas.Sandberg@ARM.com/*
29651SAndreas.Sandberg@ARM.com * Copyright (c) 2012 ARM Limited
39651SAndreas.Sandberg@ARM.com * All rights reserved
49651SAndreas.Sandberg@ARM.com *
59651SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall
69651SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual
79651SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating
89651SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software
99651SAndreas.Sandberg@ARM.com * licensed hereunder.  You may use the software subject to the license
109651SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated
119651SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software,
129651SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form.
139651SAndreas.Sandberg@ARM.com *
149651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
159651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
169651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
179651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
189651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
199651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
209651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
219651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
229651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from
239651SAndreas.Sandberg@ARM.com * this software without specific prior written permission.
249651SAndreas.Sandberg@ARM.com *
259651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369651SAndreas.Sandberg@ARM.com *
379651SAndreas.Sandberg@ARM.com * Authors: Andreas Sandberg
389651SAndreas.Sandberg@ARM.com */
399651SAndreas.Sandberg@ARM.com
409651SAndreas.Sandberg@ARM.com#ifndef __CPU_KVM_PERFEVENT_HH__
419651SAndreas.Sandberg@ARM.com#define __CPU_KVM_PERFEVENT_HH__
429651SAndreas.Sandberg@ARM.com
439651SAndreas.Sandberg@ARM.com#include <linux/perf_event.h>
449651SAndreas.Sandberg@ARM.com#include <sys/types.h>
459651SAndreas.Sandberg@ARM.com
469651SAndreas.Sandberg@ARM.com#include <inttypes.h>
479651SAndreas.Sandberg@ARM.com
489986Sandreas@sandberg.pp.se#include "config/have_perf_attr_exclude_host.hh"
499986Sandreas@sandberg.pp.se
509651SAndreas.Sandberg@ARM.com/**
519651SAndreas.Sandberg@ARM.com * PerfEvent counter configuration.
529651SAndreas.Sandberg@ARM.com */
539651SAndreas.Sandberg@ARM.comclass PerfKvmCounterConfig
549651SAndreas.Sandberg@ARM.com{
559651SAndreas.Sandberg@ARM.com  public:
569651SAndreas.Sandberg@ARM.com    /**
579651SAndreas.Sandberg@ARM.com     * Initialize PerfEvent counter configuration structure
589651SAndreas.Sandberg@ARM.com     *
599651SAndreas.Sandberg@ARM.com     * PerfEvent has the concept of counter types, which is a way to
609651SAndreas.Sandberg@ARM.com     * abstract hardware performance counters or access software
619651SAndreas.Sandberg@ARM.com     * events. The type field in the configuration specifies what type
629651SAndreas.Sandberg@ARM.com     * of counter this is. For hardware performance counters, it's
639651SAndreas.Sandberg@ARM.com     * typically PERF_TYPE_HARDWARE, PERF_TYPE_HW_CACHE, or
649651SAndreas.Sandberg@ARM.com     * PERF_TYPE_RAW.
659651SAndreas.Sandberg@ARM.com     *
669651SAndreas.Sandberg@ARM.com     * The 'config' field has different meanings depending on the type
679651SAndreas.Sandberg@ARM.com     * of counter. Possible values are listed in perf_event.h in the
689651SAndreas.Sandberg@ARM.com     * kernel headers. When using raw counters, the value is the raw
699651SAndreas.Sandberg@ARM.com     * value written to the performance counter configuration register
709651SAndreas.Sandberg@ARM.com     * (some bits dealing with sampling and similar features are
719651SAndreas.Sandberg@ARM.com     * usually masked).
729651SAndreas.Sandberg@ARM.com     *
739651SAndreas.Sandberg@ARM.com     * @param type Counter type.
749651SAndreas.Sandberg@ARM.com     * @param config Counter configuration
759651SAndreas.Sandberg@ARM.com     */
769651SAndreas.Sandberg@ARM.com    PerfKvmCounterConfig(uint32_t type, uint64_t config);
779651SAndreas.Sandberg@ARM.com    ~PerfKvmCounterConfig();
789651SAndreas.Sandberg@ARM.com
799651SAndreas.Sandberg@ARM.com    /**
809651SAndreas.Sandberg@ARM.com     * Set the initial sample period (overflow count) of an event. If
819651SAndreas.Sandberg@ARM.com     * this is set to 0, the event acts as a normal counting event and
829651SAndreas.Sandberg@ARM.com     * does not trigger overflows.
839651SAndreas.Sandberg@ARM.com     *
849651SAndreas.Sandberg@ARM.com     * @param period Number of counter events before the counter
859651SAndreas.Sandberg@ARM.com     * overflows
869651SAndreas.Sandberg@ARM.com     */
879651SAndreas.Sandberg@ARM.com    PerfKvmCounterConfig &samplePeriod(uint64_t period) {
889651SAndreas.Sandberg@ARM.com        attr.freq = 0;
899651SAndreas.Sandberg@ARM.com        attr.sample_period = period;
909651SAndreas.Sandberg@ARM.com        return *this;
919651SAndreas.Sandberg@ARM.com    }
929651SAndreas.Sandberg@ARM.com
939651SAndreas.Sandberg@ARM.com    /**
949651SAndreas.Sandberg@ARM.com     * Set the number of samples that need to be triggered before
959651SAndreas.Sandberg@ARM.com     * reporting data as being available on the perf event
969651SAndreas.Sandberg@ARM.com     * FD. Defaults to 0, which disables overflow reporting.
979651SAndreas.Sandberg@ARM.com     *
989651SAndreas.Sandberg@ARM.com     * @param events Number of overflows before signaling a wake up
999651SAndreas.Sandberg@ARM.com     */
1009651SAndreas.Sandberg@ARM.com    PerfKvmCounterConfig &wakeupEvents(uint32_t events) {
1019651SAndreas.Sandberg@ARM.com        attr.watermark = 0;
1029651SAndreas.Sandberg@ARM.com        attr.wakeup_events = events;
1039651SAndreas.Sandberg@ARM.com        return *this;
1049651SAndreas.Sandberg@ARM.com    }
1059651SAndreas.Sandberg@ARM.com
1069651SAndreas.Sandberg@ARM.com    /**
1079651SAndreas.Sandberg@ARM.com     * Don't start the performance counter automatically when
1089651SAndreas.Sandberg@ARM.com     * attaching it.
1099651SAndreas.Sandberg@ARM.com     *
1109651SAndreas.Sandberg@ARM.com     * @param val true to disable, false to enable the counter
1119651SAndreas.Sandberg@ARM.com     */
1129651SAndreas.Sandberg@ARM.com    PerfKvmCounterConfig &disabled(bool val) {
1139651SAndreas.Sandberg@ARM.com        attr.disabled = val;
1149651SAndreas.Sandberg@ARM.com        return *this;
1159651SAndreas.Sandberg@ARM.com    }
1169651SAndreas.Sandberg@ARM.com
1179651SAndreas.Sandberg@ARM.com    /**
1189651SAndreas.Sandberg@ARM.com     * Force the group to be on the active all the time (i.e.,
1199651SAndreas.Sandberg@ARM.com     * disallow multiplexing).
1209651SAndreas.Sandberg@ARM.com     *
1219651SAndreas.Sandberg@ARM.com     * Only applies to group leaders.
1229651SAndreas.Sandberg@ARM.com     *
1239651SAndreas.Sandberg@ARM.com     * @param val true to pin the counter
1249651SAndreas.Sandberg@ARM.com     */
1259651SAndreas.Sandberg@ARM.com    PerfKvmCounterConfig &pinned(bool val) {
1269651SAndreas.Sandberg@ARM.com        attr.pinned = val;
1279651SAndreas.Sandberg@ARM.com        return *this;
1289651SAndreas.Sandberg@ARM.com    }
1299651SAndreas.Sandberg@ARM.com
1309986Sandreas@sandberg.pp.se    /**
1319986Sandreas@sandberg.pp.se     * Exclude the events from the host (i.e., only include events
1329986Sandreas@sandberg.pp.se     * from the guest system).
1339986Sandreas@sandberg.pp.se     *
1349986Sandreas@sandberg.pp.se     * Intel CPUs seem to support this attribute from Linux 3.2 and
1359986Sandreas@sandberg.pp.se     * onwards. Non-x86 architectures currently ignore this attribute
1369986Sandreas@sandberg.pp.se     * (Linux 3.12-rc5).
1379986Sandreas@sandberg.pp.se     *
1389986Sandreas@sandberg.pp.se     * @warn This attribute is ignored if it isn't present in the
1399986Sandreas@sandberg.pp.se     * kernel headers or if the kernel doesn't support it.
1409986Sandreas@sandberg.pp.se     *
1419986Sandreas@sandberg.pp.se     * @param val true to exclude host events
1429986Sandreas@sandberg.pp.se     */
1439986Sandreas@sandberg.pp.se    PerfKvmCounterConfig &exclude_host(bool val) {
1449986Sandreas@sandberg.pp.se#if HAVE_PERF_ATTR_EXCLUDE_HOST == 1
1459986Sandreas@sandberg.pp.se        attr.exclude_host = val;
1469986Sandreas@sandberg.pp.se#endif
1479986Sandreas@sandberg.pp.se        return *this;
1489986Sandreas@sandberg.pp.se    }
1499986Sandreas@sandberg.pp.se
1509986Sandreas@sandberg.pp.se    /**
1519986Sandreas@sandberg.pp.se     * Exclude the hyper visor (i.e., only include events from the
1529986Sandreas@sandberg.pp.se     * guest system).
1539986Sandreas@sandberg.pp.se     *
1549986Sandreas@sandberg.pp.se     * @warn This is attribute only seems to be ignored on Intel.
1559986Sandreas@sandberg.pp.se     *
1569986Sandreas@sandberg.pp.se     * @param val true to exclude host events
1579986Sandreas@sandberg.pp.se     */
1589986Sandreas@sandberg.pp.se    PerfKvmCounterConfig &exclude_hv(bool val) {
1599986Sandreas@sandberg.pp.se        attr.exclude_hv = val;
1609986Sandreas@sandberg.pp.se        return *this;
1619986Sandreas@sandberg.pp.se    }
1629986Sandreas@sandberg.pp.se
1639651SAndreas.Sandberg@ARM.com    /** Underlying perf_event_attr structure describing the counter */
1649651SAndreas.Sandberg@ARM.com    struct perf_event_attr attr;
1659651SAndreas.Sandberg@ARM.com};
1669651SAndreas.Sandberg@ARM.com
1679651SAndreas.Sandberg@ARM.com/**
1689651SAndreas.Sandberg@ARM.com * An instance of a performance counter.
1699651SAndreas.Sandberg@ARM.com */
1709651SAndreas.Sandberg@ARM.comclass PerfKvmCounter
1719651SAndreas.Sandberg@ARM.com{
1729651SAndreas.Sandberg@ARM.compublic:
1739651SAndreas.Sandberg@ARM.com    /**
1749651SAndreas.Sandberg@ARM.com     * Create and attach a new counter group.
1759651SAndreas.Sandberg@ARM.com     *
1769651SAndreas.Sandberg@ARM.com     * @param config Counter configuration
1779651SAndreas.Sandberg@ARM.com     * @param tid Thread to sample (0 indicates current thread)
1789651SAndreas.Sandberg@ARM.com     */
1799651SAndreas.Sandberg@ARM.com    PerfKvmCounter(PerfKvmCounterConfig &config, pid_t tid);
1809651SAndreas.Sandberg@ARM.com    /**
1819651SAndreas.Sandberg@ARM.com     * Create and attach a new counter and make it a member of an
1829651SAndreas.Sandberg@ARM.com     * exist counter group.
1839651SAndreas.Sandberg@ARM.com     *
1849651SAndreas.Sandberg@ARM.com     * @param config Counter configuration
1859651SAndreas.Sandberg@ARM.com     * @param tid Thread to sample (0 indicates current thread)
1869651SAndreas.Sandberg@ARM.com     * @param parent Group leader
1879651SAndreas.Sandberg@ARM.com     */
1889651SAndreas.Sandberg@ARM.com    PerfKvmCounter(PerfKvmCounterConfig &config,
1899651SAndreas.Sandberg@ARM.com                pid_t tid, const PerfKvmCounter &parent);
1909651SAndreas.Sandberg@ARM.com    /**
1919651SAndreas.Sandberg@ARM.com     * Create a new counter, but don't attach it.
1929651SAndreas.Sandberg@ARM.com     */
1939651SAndreas.Sandberg@ARM.com    PerfKvmCounter();
1949651SAndreas.Sandberg@ARM.com    ~PerfKvmCounter();
1959651SAndreas.Sandberg@ARM.com
1969651SAndreas.Sandberg@ARM.com
1979651SAndreas.Sandberg@ARM.com    /**
1989651SAndreas.Sandberg@ARM.com     * Attach a counter.
1999651SAndreas.Sandberg@ARM.com     *
2009651SAndreas.Sandberg@ARM.com     * @note This operation is only supported if the counter isn't
2019651SAndreas.Sandberg@ARM.com     * already attached.
2029651SAndreas.Sandberg@ARM.com     *
2039651SAndreas.Sandberg@ARM.com     * @param config Counter configuration
2049651SAndreas.Sandberg@ARM.com     * @param tid Thread to sample (0 indicates current thread)
2059651SAndreas.Sandberg@ARM.com     */
2069651SAndreas.Sandberg@ARM.com    void attach(PerfKvmCounterConfig &config, pid_t tid) {
2079651SAndreas.Sandberg@ARM.com        attach(config, tid, -1);
2089651SAndreas.Sandberg@ARM.com    }
2099651SAndreas.Sandberg@ARM.com
2109651SAndreas.Sandberg@ARM.com    /**
2119651SAndreas.Sandberg@ARM.com     * Attach a counter and make it a member of an existing counter
2129651SAndreas.Sandberg@ARM.com     * group.
2139651SAndreas.Sandberg@ARM.com     *
2149651SAndreas.Sandberg@ARM.com     * @note This operation is only supported if the counter isn't
2159651SAndreas.Sandberg@ARM.com     * already attached.
2169651SAndreas.Sandberg@ARM.com     *
2179651SAndreas.Sandberg@ARM.com     * @param config Counter configuration
2189651SAndreas.Sandberg@ARM.com     * @param tid Thread to sample (0 indicates current thread)
2199651SAndreas.Sandberg@ARM.com     * @param parent Group leader
2209651SAndreas.Sandberg@ARM.com     */
2219651SAndreas.Sandberg@ARM.com    void attach(PerfKvmCounterConfig &config,
2229651SAndreas.Sandberg@ARM.com                pid_t tid, const PerfKvmCounter &parent) {
2239651SAndreas.Sandberg@ARM.com        attach(config, tid, parent.fd);
2249651SAndreas.Sandberg@ARM.com    }
2259651SAndreas.Sandberg@ARM.com
2269651SAndreas.Sandberg@ARM.com    /** Detach a counter from PerfEvent. */
2279651SAndreas.Sandberg@ARM.com    void detach();
2289651SAndreas.Sandberg@ARM.com
2299651SAndreas.Sandberg@ARM.com    /** Check if a counter is attached. */
2309651SAndreas.Sandberg@ARM.com    bool attached() const { return fd != -1; }
2319651SAndreas.Sandberg@ARM.com
2329651SAndreas.Sandberg@ARM.com    /**
2339651SAndreas.Sandberg@ARM.com     * Start counting.
2349651SAndreas.Sandberg@ARM.com     *
2359651SAndreas.Sandberg@ARM.com     * @note If this counter is a group leader, it will start the
2369651SAndreas.Sandberg@ARM.com     * entire group.
2379651SAndreas.Sandberg@ARM.com     */
2389651SAndreas.Sandberg@ARM.com    void start();
2399651SAndreas.Sandberg@ARM.com
2409651SAndreas.Sandberg@ARM.com    /**
2419651SAndreas.Sandberg@ARM.com     * Stop counting.
2429651SAndreas.Sandberg@ARM.com     *
2439651SAndreas.Sandberg@ARM.com     * @note If this counter is a group leader, it will stop the
2449651SAndreas.Sandberg@ARM.com     * entire group.
2459651SAndreas.Sandberg@ARM.com     */
2469651SAndreas.Sandberg@ARM.com    void stop();
2479651SAndreas.Sandberg@ARM.com
2489651SAndreas.Sandberg@ARM.com    /**
2499651SAndreas.Sandberg@ARM.com     * Update the period of an overflow counter.
2509651SAndreas.Sandberg@ARM.com     *
2519651SAndreas.Sandberg@ARM.com     * @warning This ioctl has some pretty bizarre semantics. It seems
2529651SAndreas.Sandberg@ARM.com     * like the new period isn't effective until after the next
2539651SAndreas.Sandberg@ARM.com     * counter overflow. If you use this method to change the sample
2549651SAndreas.Sandberg@ARM.com     * period, you will see one sample with the old period and then
2559655SAndreas.Sandberg@ARM.com     * start sampling with the new period. This problem was fixed for
2569655SAndreas.Sandberg@ARM.com     * ARM in version 3.7 of the kernel.
2579651SAndreas.Sandberg@ARM.com     *
2589651SAndreas.Sandberg@ARM.com     * @warning This method doesn't work at all on some 2.6.3x kernels
2599651SAndreas.Sandberg@ARM.com     * since it has inverted check for the return value when copying
2609651SAndreas.Sandberg@ARM.com     * parameters from userspace.
2619651SAndreas.Sandberg@ARM.com     *
2629651SAndreas.Sandberg@ARM.com     * @param period Overflow period in events
2639651SAndreas.Sandberg@ARM.com     */
2649651SAndreas.Sandberg@ARM.com    void period(uint64_t period);
2659651SAndreas.Sandberg@ARM.com
2669651SAndreas.Sandberg@ARM.com    /**
2679651SAndreas.Sandberg@ARM.com     * Enable a counter for a fixed number of events.
2689651SAndreas.Sandberg@ARM.com     *
2699651SAndreas.Sandberg@ARM.com     * When this method is called, perf event enables the counter if
2709651SAndreas.Sandberg@ARM.com     * it was disabled. It then leaves the counter enabled until it
2719651SAndreas.Sandberg@ARM.com     * has overflowed a refresh times.
2729651SAndreas.Sandberg@ARM.com     *
2739651SAndreas.Sandberg@ARM.com     * @note This does not update the period of the counter.
2749651SAndreas.Sandberg@ARM.com     *
2759651SAndreas.Sandberg@ARM.com     * @param refresh Number of overflows before disabling the
2769651SAndreas.Sandberg@ARM.com     * counter.
2779651SAndreas.Sandberg@ARM.com     */
2789651SAndreas.Sandberg@ARM.com    void refresh(int refresh);
2799651SAndreas.Sandberg@ARM.com
2809651SAndreas.Sandberg@ARM.com    /**
2819651SAndreas.Sandberg@ARM.com     * Read the current value of a counter.
2829651SAndreas.Sandberg@ARM.com     */
2839651SAndreas.Sandberg@ARM.com    uint64_t read() const;
2849651SAndreas.Sandberg@ARM.com
2859651SAndreas.Sandberg@ARM.com    /**
2869651SAndreas.Sandberg@ARM.com     * Enable signal delivery to a thread on counter overflow.
2879651SAndreas.Sandberg@ARM.com     *
2889651SAndreas.Sandberg@ARM.com     * @param tid Thread to deliver signal to
2899651SAndreas.Sandberg@ARM.com     * @param signal Signal to send upon overflow
2909651SAndreas.Sandberg@ARM.com     */
2919651SAndreas.Sandberg@ARM.com    void enableSignals(pid_t tid, int signal);
2929651SAndreas.Sandberg@ARM.com
2939651SAndreas.Sandberg@ARM.com    /**
2949651SAndreas.Sandberg@ARM.com     * Enable signal delivery on counter overflow. Identical to
2959651SAndreas.Sandberg@ARM.com     * enableSignals(pid_t) when called with the current TID as its
2969651SAndreas.Sandberg@ARM.com     * parameter.
2979651SAndreas.Sandberg@ARM.com     *
2989651SAndreas.Sandberg@ARM.com     * @param signal Signal to send upon overflow
2999651SAndreas.Sandberg@ARM.com     */
3009651SAndreas.Sandberg@ARM.com    void enableSignals(int signal) { enableSignals(gettid(), signal); }
3019651SAndreas.Sandberg@ARM.com
3029651SAndreas.Sandberg@ARM.comprivate:
3039651SAndreas.Sandberg@ARM.com    // Disallow copying
3049651SAndreas.Sandberg@ARM.com    PerfKvmCounter(const PerfKvmCounter &that);
3059651SAndreas.Sandberg@ARM.com    // Disallow assignment
3069651SAndreas.Sandberg@ARM.com    PerfKvmCounter &operator=(const PerfKvmCounter &that);
3079651SAndreas.Sandberg@ARM.com
3089651SAndreas.Sandberg@ARM.com    void attach(PerfKvmCounterConfig &config, pid_t tid, int group_fd);
3099651SAndreas.Sandberg@ARM.com
3109651SAndreas.Sandberg@ARM.com    /**
3119651SAndreas.Sandberg@ARM.com     * Get the TID of the current thread.
3129651SAndreas.Sandberg@ARM.com     *
3139651SAndreas.Sandberg@ARM.com     * @return Current thread's TID
3149651SAndreas.Sandberg@ARM.com     */
3159651SAndreas.Sandberg@ARM.com    pid_t gettid();
3169651SAndreas.Sandberg@ARM.com
3179651SAndreas.Sandberg@ARM.com    /**
3189651SAndreas.Sandberg@ARM.com     * MMAP the PerfEvent file descriptor.
3199651SAndreas.Sandberg@ARM.com     *
3209651SAndreas.Sandberg@ARM.com     * @note We currently don't use the ring buffer, but PerfEvent
3219651SAndreas.Sandberg@ARM.com     * requires this to be mapped for overflow handling to work.
3229651SAndreas.Sandberg@ARM.com     *
3239651SAndreas.Sandberg@ARM.com     * @note Overflow handling requires at least one buf_page to be
3249651SAndreas.Sandberg@ARM.com     * mapped.
3259651SAndreas.Sandberg@ARM.com     *
3269651SAndreas.Sandberg@ARM.com     * @param pages number of pages in circular sample buffer. Must be
3279651SAndreas.Sandberg@ARM.com     * an even power of 2.
3289651SAndreas.Sandberg@ARM.com     */
3299651SAndreas.Sandberg@ARM.com    void mmapPerf(int pages);
3309651SAndreas.Sandberg@ARM.com
3319651SAndreas.Sandberg@ARM.com    /** @{ */
3329651SAndreas.Sandberg@ARM.com    /**
3339651SAndreas.Sandberg@ARM.com     * PerfEvent fnctl interface.
3349651SAndreas.Sandberg@ARM.com     *
3359651SAndreas.Sandberg@ARM.com     * @param cmd fcntl command
3369651SAndreas.Sandberg@ARM.com     * @param p1 Request parameter
3379651SAndreas.Sandberg@ARM.com     *
3389651SAndreas.Sandberg@ARM.com     * @return -1 on error (error number in errno), ioctl dependent
3399651SAndreas.Sandberg@ARM.com     * value otherwise.
3409651SAndreas.Sandberg@ARM.com     */
3419651SAndreas.Sandberg@ARM.com    int fcntl(int cmd, long p1);
3429651SAndreas.Sandberg@ARM.com    int fcntl(int cmd, void *p1) { return fcntl(cmd, (long)p1); }
3439651SAndreas.Sandberg@ARM.com    /** @} */
3449651SAndreas.Sandberg@ARM.com
3459651SAndreas.Sandberg@ARM.com    /** @{ */
3469651SAndreas.Sandberg@ARM.com    /**
3479651SAndreas.Sandberg@ARM.com     * PerfEvent ioctl interface.
3489651SAndreas.Sandberg@ARM.com     *
3499651SAndreas.Sandberg@ARM.com     * @param request PerfEvent request
3509651SAndreas.Sandberg@ARM.com     * @param p1 Optional request parameter
3519651SAndreas.Sandberg@ARM.com     *
3529651SAndreas.Sandberg@ARM.com     * @return -1 on error (error number in errno), ioctl dependent
3539651SAndreas.Sandberg@ARM.com     * value otherwise.
3549651SAndreas.Sandberg@ARM.com     */
3559651SAndreas.Sandberg@ARM.com    int ioctl(int request, long p1);
3569651SAndreas.Sandberg@ARM.com    int ioctl(int request, void *p1) { return ioctl(request, (long)p1); }
3579651SAndreas.Sandberg@ARM.com    int ioctl(int request) { return ioctl(request, 0L); }
3589651SAndreas.Sandberg@ARM.com    /** @} */
3599651SAndreas.Sandberg@ARM.com
3609651SAndreas.Sandberg@ARM.com    /**
3619651SAndreas.Sandberg@ARM.com     * Perform a read from the counter file descriptor.
3629651SAndreas.Sandberg@ARM.com     *
3639651SAndreas.Sandberg@ARM.com     * @param buf Destination buffer
3649651SAndreas.Sandberg@ARM.com     * @param size Amount of data to read
3659651SAndreas.Sandberg@ARM.com     */
3669651SAndreas.Sandberg@ARM.com    void read(void *buf, size_t size) const;
3679651SAndreas.Sandberg@ARM.com
3689651SAndreas.Sandberg@ARM.com    /**
3699651SAndreas.Sandberg@ARM.com     * PerfEvent file descriptor associated with counter. -1 if not
3709651SAndreas.Sandberg@ARM.com     * attached to PerfEvent.
3719651SAndreas.Sandberg@ARM.com     */
3729651SAndreas.Sandberg@ARM.com    int fd;
3739651SAndreas.Sandberg@ARM.com
3749651SAndreas.Sandberg@ARM.com    /** Memory mapped PerfEvent sample ring buffer */
3759651SAndreas.Sandberg@ARM.com    struct perf_event_mmap_page *ringBuffer;
3769651SAndreas.Sandberg@ARM.com    /** Total number of pages in ring buffer */
3779651SAndreas.Sandberg@ARM.com    int ringNumPages;
3789651SAndreas.Sandberg@ARM.com
3799651SAndreas.Sandberg@ARM.com    /** Cached host page size */
3809651SAndreas.Sandberg@ARM.com    long pageSize;
3819651SAndreas.Sandberg@ARM.com};
3829651SAndreas.Sandberg@ARM.com
3839651SAndreas.Sandberg@ARM.com#endif
384