perfevent.cc revision 13787
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2012 ARM Limited 311308Santhony.gutierrez@amd.com * All rights reserved 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * The license below extends only to copyright in the software and shall 611308Santhony.gutierrez@amd.com * not be construed as granting a license to any other intellectual 711308Santhony.gutierrez@amd.com * property including but not limited to intellectual property relating 811308Santhony.gutierrez@amd.com * to a hardware implementation of the functionality of the software 911308Santhony.gutierrez@amd.com * licensed hereunder. You may use the software subject to the license 1011308Santhony.gutierrez@amd.com * terms below provided that you ensure that this notice is replicated 1111308Santhony.gutierrez@amd.com * unmodified and in its entirety in all distributions of the software, 1211308Santhony.gutierrez@amd.com * modified or unmodified, in source code or in binary form. 1311308Santhony.gutierrez@amd.com * 1411308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 1511308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 1611308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 1711308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 1811308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1911308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 2011308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 2111308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 2211308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 2311308Santhony.gutierrez@amd.com * this software without specific prior written permission. 2411308Santhony.gutierrez@amd.com * 2511308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2611308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2711308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2811308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2911308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3011308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3111308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3211308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3311308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3411308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3511308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3611308Santhony.gutierrez@amd.com * 3711308Santhony.gutierrez@amd.com * Authors: Andreas Sandberg 3811308Santhony.gutierrez@amd.com */ 3911308Santhony.gutierrez@amd.com 4011308Santhony.gutierrez@amd.com#include <fcntl.h> 4111308Santhony.gutierrez@amd.com#include <sys/ioctl.h> 4211308Santhony.gutierrez@amd.com#include <sys/mman.h> 4311308Santhony.gutierrez@amd.com#include <sys/syscall.h> 4411308Santhony.gutierrez@amd.com#include <sys/types.h> 4511308Santhony.gutierrez@amd.com#include <syscall.h> 4611308Santhony.gutierrez@amd.com#include <unistd.h> 4711308Santhony.gutierrez@amd.com 4811308Santhony.gutierrez@amd.com#include <cassert> 4911308Santhony.gutierrez@amd.com#include <cerrno> 5011308Santhony.gutierrez@amd.com#include <csignal> 5111308Santhony.gutierrez@amd.com#include <cstring> 5211308Santhony.gutierrez@amd.com 5311308Santhony.gutierrez@amd.com#include "base/logging.hh" 5411308Santhony.gutierrez@amd.com#include "perfevent.hh" 5511308Santhony.gutierrez@amd.com 5611308Santhony.gutierrez@amd.comPerfKvmCounterConfig::PerfKvmCounterConfig(uint32_t type, uint64_t config) 5711308Santhony.gutierrez@amd.com{ 5811308Santhony.gutierrez@amd.com memset(&attr, 0, sizeof(attr)); 5911308Santhony.gutierrez@amd.com 6011308Santhony.gutierrez@amd.com attr.size = PERF_ATTR_SIZE_VER0; 6111308Santhony.gutierrez@amd.com attr.type = type; 6211308Santhony.gutierrez@amd.com attr.config = config; 6311308Santhony.gutierrez@amd.com} 6411308Santhony.gutierrez@amd.com 6511308Santhony.gutierrez@amd.comPerfKvmCounterConfig::~PerfKvmCounterConfig() 6611308Santhony.gutierrez@amd.com{ 6711308Santhony.gutierrez@amd.com} 6811308Santhony.gutierrez@amd.com 6911308Santhony.gutierrez@amd.com 7011308Santhony.gutierrez@amd.comPerfKvmCounter::PerfKvmCounter(PerfKvmCounterConfig &config, pid_t tid) 7111308Santhony.gutierrez@amd.com : fd(-1), ringBuffer(NULL), pageSize(-1) 7211308Santhony.gutierrez@amd.com{ 7311308Santhony.gutierrez@amd.com attach(config, tid, -1); 7411308Santhony.gutierrez@amd.com} 7511308Santhony.gutierrez@amd.com 7611308Santhony.gutierrez@amd.comPerfKvmCounter::PerfKvmCounter(PerfKvmCounterConfig &config, 7711308Santhony.gutierrez@amd.com pid_t tid, const PerfKvmCounter &parent) 7811308Santhony.gutierrez@amd.com : fd(-1), ringBuffer(NULL), pageSize(-1) 7911308Santhony.gutierrez@amd.com{ 8011308Santhony.gutierrez@amd.com attach(config, tid, parent); 8111308Santhony.gutierrez@amd.com} 8211308Santhony.gutierrez@amd.com 8311308Santhony.gutierrez@amd.comPerfKvmCounter::PerfKvmCounter() 8411308Santhony.gutierrez@amd.com : fd(-1), ringBuffer(NULL), pageSize(-1) 8511308Santhony.gutierrez@amd.com{ 8611308Santhony.gutierrez@amd.com} 8711308Santhony.gutierrez@amd.com 8811308Santhony.gutierrez@amd.comPerfKvmCounter::~PerfKvmCounter() 8911308Santhony.gutierrez@amd.com{ 9011308Santhony.gutierrez@amd.com if (attached()) 9111308Santhony.gutierrez@amd.com detach(); 9211308Santhony.gutierrez@amd.com} 9311308Santhony.gutierrez@amd.com 9411308Santhony.gutierrez@amd.comvoid 9511308Santhony.gutierrez@amd.comPerfKvmCounter::detach() 9611308Santhony.gutierrez@amd.com{ 9711308Santhony.gutierrez@amd.com assert(attached()); 9811308Santhony.gutierrez@amd.com 9911308Santhony.gutierrez@amd.com if (munmap(ringBuffer, ringNumPages * pageSize) == -1) 10011308Santhony.gutierrez@amd.com warn("PerfKvmCounter: Failed to unmap ring buffer (%i)\n", 10111308Santhony.gutierrez@amd.com errno); 10211308Santhony.gutierrez@amd.com close(fd); 10311308Santhony.gutierrez@amd.com 10411308Santhony.gutierrez@amd.com fd = -1; 10511308Santhony.gutierrez@amd.com ringBuffer = NULL; 10611308Santhony.gutierrez@amd.com} 10711308Santhony.gutierrez@amd.com 10811308Santhony.gutierrez@amd.comvoid 10911308Santhony.gutierrez@amd.comPerfKvmCounter::start() 11011308Santhony.gutierrez@amd.com{ 11111308Santhony.gutierrez@amd.com if (ioctl(PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) 11211308Santhony.gutierrez@amd.com panic("KVM: Failed to enable performance counters (%i)\n", errno); 11311308Santhony.gutierrez@amd.com} 11411308Santhony.gutierrez@amd.com 11511308Santhony.gutierrez@amd.comvoid 11611308Santhony.gutierrez@amd.comPerfKvmCounter::stop() 11711308Santhony.gutierrez@amd.com{ 11811308Santhony.gutierrez@amd.com if (ioctl(PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) 11911308Santhony.gutierrez@amd.com panic("KVM: Failed to disable performance counters (%i)\n", errno); 12011308Santhony.gutierrez@amd.com} 12111308Santhony.gutierrez@amd.com 12211308Santhony.gutierrez@amd.comvoid 12311308Santhony.gutierrez@amd.comPerfKvmCounter::period(uint64_t period) 12411308Santhony.gutierrez@amd.com{ 12511308Santhony.gutierrez@amd.com if (ioctl(PERF_EVENT_IOC_PERIOD, &period) == -1) 12611308Santhony.gutierrez@amd.com panic("KVM: Failed to set period of performance counter (%i)\n", errno); 12711308Santhony.gutierrez@amd.com} 12811308Santhony.gutierrez@amd.com 12911308Santhony.gutierrez@amd.comvoid 13011308Santhony.gutierrez@amd.comPerfKvmCounter::refresh(int refresh) 13111308Santhony.gutierrez@amd.com{ 13211308Santhony.gutierrez@amd.com if (ioctl(PERF_EVENT_IOC_REFRESH, refresh) == -1) 13311308Santhony.gutierrez@amd.com panic("KVM: Failed to refresh performance counter (%i)\n", errno); 13411308Santhony.gutierrez@amd.com} 13511308Santhony.gutierrez@amd.com 13611308Santhony.gutierrez@amd.comuint64_t 13711308Santhony.gutierrez@amd.comPerfKvmCounter::read() const 13811308Santhony.gutierrez@amd.com{ 13911308Santhony.gutierrez@amd.com uint64_t value; 14011308Santhony.gutierrez@amd.com 14111308Santhony.gutierrez@amd.com read(&value, sizeof(uint64_t)); 14211308Santhony.gutierrez@amd.com return value; 14311308Santhony.gutierrez@amd.com} 14411308Santhony.gutierrez@amd.com 14511308Santhony.gutierrez@amd.comvoid 14611308Santhony.gutierrez@amd.comPerfKvmCounter::enableSignals(pid_t tid, int signal) 14711308Santhony.gutierrez@amd.com{ 14811308Santhony.gutierrez@amd.com struct f_owner_ex sigowner; 14911308Santhony.gutierrez@amd.com 15011308Santhony.gutierrez@amd.com sigowner.type = F_OWNER_TID; 15111308Santhony.gutierrez@amd.com sigowner.pid = tid; 15211308Santhony.gutierrez@amd.com 15311308Santhony.gutierrez@amd.com if (fcntl(F_SETOWN_EX, &sigowner) == -1 || 15411308Santhony.gutierrez@amd.com fcntl(F_SETSIG, signal) == -1 || 15511308Santhony.gutierrez@amd.com fcntl(F_SETFL, O_ASYNC) == -1) 15611308Santhony.gutierrez@amd.com panic("PerfKvmCounter: Failed to enable signals for counter (%i)\n", 15711308Santhony.gutierrez@amd.com errno); 15811308Santhony.gutierrez@amd.com} 15911308Santhony.gutierrez@amd.com 16011308Santhony.gutierrez@amd.comvoid 16111308Santhony.gutierrez@amd.comPerfKvmCounter::attach(PerfKvmCounterConfig &config, 16211308Santhony.gutierrez@amd.com pid_t tid, int group_fd) 16311308Santhony.gutierrez@amd.com{ 16411308Santhony.gutierrez@amd.com assert(!attached()); 16511308Santhony.gutierrez@amd.com 16611308Santhony.gutierrez@amd.com fd = syscall(__NR_perf_event_open, 16711308Santhony.gutierrez@amd.com &config.attr, tid, 16811308Santhony.gutierrez@amd.com -1, // CPU (-1 => Any CPU that the task happens to run on) 16911308Santhony.gutierrez@amd.com group_fd, 17011308Santhony.gutierrez@amd.com 0); // Flags 17111308Santhony.gutierrez@amd.com if (fd == -1) 17211308Santhony.gutierrez@amd.com { 17311308Santhony.gutierrez@amd.com if (errno == EACCES) 17411308Santhony.gutierrez@amd.com { 17511308Santhony.gutierrez@amd.com panic("PerfKvmCounter::attach recieved error EACCESS\n" 17611308Santhony.gutierrez@amd.com " This error may be caused by a too restrictive setting\n" 17711308Santhony.gutierrez@amd.com " in the file '/proc/sys/kernel/perf_event_paranoid'\n" 17811308Santhony.gutierrez@amd.com " The default value was changed to 2 in kernel 4.6\n" 17911308Santhony.gutierrez@amd.com " A value greater than 1 prevents gem5 from making\n" 18011308Santhony.gutierrez@amd.com " the syscall to perf_event_open"); 18111308Santhony.gutierrez@amd.com } 18211308Santhony.gutierrez@amd.com panic("PerfKvmCounter::attach failed (%i)\n", errno); 18311308Santhony.gutierrez@amd.com } 18411308Santhony.gutierrez@amd.com 18511308Santhony.gutierrez@amd.com mmapPerf(1); 18611308Santhony.gutierrez@amd.com} 18711308Santhony.gutierrez@amd.com 18811308Santhony.gutierrez@amd.compid_t 18911308Santhony.gutierrez@amd.comPerfKvmCounter::gettid() 19011308Santhony.gutierrez@amd.com{ 19111308Santhony.gutierrez@amd.com return syscall(__NR_gettid); 19211308Santhony.gutierrez@amd.com} 19311308Santhony.gutierrez@amd.com 19411308Santhony.gutierrez@amd.comvoid 19511308Santhony.gutierrez@amd.comPerfKvmCounter::mmapPerf(int pages) 19611308Santhony.gutierrez@amd.com{ 19711308Santhony.gutierrez@amd.com assert(attached()); 19811308Santhony.gutierrez@amd.com assert(ringBuffer == NULL); 19911308Santhony.gutierrez@amd.com 20011308Santhony.gutierrez@amd.com if (pageSize == -1) { 20111308Santhony.gutierrez@amd.com pageSize = sysconf(_SC_PAGE_SIZE); 20211308Santhony.gutierrez@amd.com if (pageSize == -1) 20311308Santhony.gutierrez@amd.com panic("PerfKvmCounter: Failed to determine page size (%i)\n", 20411308Santhony.gutierrez@amd.com errno); 20511308Santhony.gutierrez@amd.com } 20611308Santhony.gutierrez@amd.com 20711308Santhony.gutierrez@amd.com ringNumPages = pages + 1; 20811308Santhony.gutierrez@amd.com ringBuffer = (struct perf_event_mmap_page *)mmap( 20911308Santhony.gutierrez@amd.com NULL, ringNumPages * 4096, 21011308Santhony.gutierrez@amd.com PROT_READ | PROT_WRITE, MAP_SHARED, 21111308Santhony.gutierrez@amd.com fd, 0); 21211308Santhony.gutierrez@amd.com if (ringBuffer == MAP_FAILED) 21311308Santhony.gutierrez@amd.com panic("PerfKvmCounter: MMAP failed (%i)\n", 21411308Santhony.gutierrez@amd.com errno); 21511308Santhony.gutierrez@amd.com} 21611308Santhony.gutierrez@amd.com 21711308Santhony.gutierrez@amd.comint 21811308Santhony.gutierrez@amd.comPerfKvmCounter::fcntl(int cmd, long p1) 21911308Santhony.gutierrez@amd.com{ 22011308Santhony.gutierrez@amd.com assert(attached()); 22111308Santhony.gutierrez@amd.com return ::fcntl(fd, cmd, p1); 22211308Santhony.gutierrez@amd.com} 22311308Santhony.gutierrez@amd.com 22411308Santhony.gutierrez@amd.comint 22511435Smitch.hayenga@arm.comPerfKvmCounter::ioctl(int request, long p1) 22611308Santhony.gutierrez@amd.com{ 22711308Santhony.gutierrez@amd.com assert(attached()); 22811308Santhony.gutierrez@amd.com return ::ioctl(fd, request, p1); 22911308Santhony.gutierrez@amd.com} 23011308Santhony.gutierrez@amd.com 23111308Santhony.gutierrez@amd.comvoid 23211308Santhony.gutierrez@amd.comPerfKvmCounter::read(void *buf, size_t size) const 23311308Santhony.gutierrez@amd.com{ 23411308Santhony.gutierrez@amd.com char *_buf = (char *)buf; 23511308Santhony.gutierrez@amd.com size_t _size = size; 23611308Santhony.gutierrez@amd.com 23711308Santhony.gutierrez@amd.com assert(attached()); 23811308Santhony.gutierrez@amd.com 23911308Santhony.gutierrez@amd.com do { 24011308Santhony.gutierrez@amd.com ssize_t ret; 24111308Santhony.gutierrez@amd.com ret = ::read(fd, _buf, _size); 24211308Santhony.gutierrez@amd.com switch (ret) { 24311308Santhony.gutierrez@amd.com case -1: 24411308Santhony.gutierrez@amd.com if (errno != EAGAIN) 24511308Santhony.gutierrez@amd.com panic("PerfKvmCounter::read failed (%i)\n", errno); 24611308Santhony.gutierrez@amd.com break; 24711308Santhony.gutierrez@amd.com 24811308Santhony.gutierrez@amd.com case 0: 24911308Santhony.gutierrez@amd.com panic("PerfKvmCounter::read unexpected EOF.\n"); 25011308Santhony.gutierrez@amd.com 25111308Santhony.gutierrez@amd.com default: 25211308Santhony.gutierrez@amd.com _size -= ret; 25311308Santhony.gutierrez@amd.com _buf += ret; 25411308Santhony.gutierrez@amd.com break; 25511308Santhony.gutierrez@amd.com } 25611308Santhony.gutierrez@amd.com } while (_size); 25711308Santhony.gutierrez@amd.com} 25811308Santhony.gutierrez@amd.com