41 #include <sys/ioctl.h> 43 #include <sys/syscall.h> 44 #include <sys/types.h> 60 attr.size = PERF_ATTR_SIZE_VER0;
71 :
fd(-1), ringBuffer(NULL), pageSize(-1)
80 attach(config, tid, parent);
100 warn(
"PerfKvmCounter: Failed to unmap ring buffer (%i)\n",
111 if (
ioctl(PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1)
112 panic(
"KVM: Failed to enable performance counters (%i)\n", errno);
118 if (
ioctl(PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1)
119 panic(
"KVM: Failed to disable performance counters (%i)\n", errno);
125 if (
ioctl(PERF_EVENT_IOC_PERIOD, &period) == -1)
126 panic(
"KVM: Failed to set period of performance counter (%i)\n", errno);
132 if (
ioctl(PERF_EVENT_IOC_REFRESH, refresh) == -1)
133 panic(
"KVM: Failed to refresh performance counter (%i)\n", errno);
141 read(&value,
sizeof(uint64_t));
148 struct f_owner_ex sigowner;
150 sigowner.type = F_OWNER_TID;
153 if (
fcntl(F_SETOWN_EX, &sigowner) == -1 ||
154 fcntl(F_SETSIG, signal) == -1 ||
155 fcntl(F_SETFL, O_ASYNC) == -1)
156 panic(
"PerfKvmCounter: Failed to enable signals for counter (%i)\n",
162 pid_t tid,
int group_fd)
166 fd = syscall(__NR_perf_event_open,
175 panic(
"PerfKvmCounter::attach recieved error EACCESS\n" 176 " This error may be caused by a too restrictive setting\n" 177 " in the file '/proc/sys/kernel/perf_event_paranoid'\n" 178 " The default value was changed to 2 in kernel 4.6\n" 179 " A value greater than 1 prevents gem5 from making\n" 180 " the syscall to perf_event_open");
182 panic(
"PerfKvmCounter::attach failed (%i)\n", errno);
191 return syscall(__NR_gettid);
203 panic(
"PerfKvmCounter: Failed to determine page size (%i)\n",
208 ringBuffer = (
struct perf_event_mmap_page *)mmap(
210 PROT_READ | PROT_WRITE, MAP_SHARED,
213 panic(
"PerfKvmCounter: MMAP failed (%i)\n",
221 return ::fcntl(
fd, cmd, p1);
228 return ::ioctl(
fd, request, p1);
234 char *_buf = (
char *)buf;
245 panic(
"PerfKvmCounter::read failed (%i)\n", errno);
249 panic(
"PerfKvmCounter::read unexpected EOF.\n");
#define panic(...)
This implements a cprintf based panic() function.
void detach()
Detach a counter from PerfEvent.
long pageSize
Cached host page size.
struct perf_event_attr attr
Underlying perf_event_attr structure describing the counter.
PerfKvmCounter()
Create a new counter, but don't attach it.
struct perf_event_mmap_page * ringBuffer
Memory mapped PerfEvent sample ring buffer.
void enableSignals(pid_t tid, int signal)
Enable signal delivery to a thread on counter overflow.
int fd
PerfEvent file descriptor associated with counter.
void refresh(int refresh)
Enable a counter for a fixed number of events.
PerfKvmCounterConfig(uint32_t type, uint64_t config)
Initialize PerfEvent counter configuration structure.
void mmapPerf(int pages)
MMAP the PerfEvent file descriptor.
void period(uint64_t period)
Update the period of an overflow counter.
int ringNumPages
Total number of pages in ring buffer.
bool attached() const
Check if a counter is attached.
uint64_t read() const
Read the current value of a counter.
An instance of a performance counter.
void attach(PerfKvmCounterConfig &config, pid_t tid)
Attach a counter.
PerfEvent counter configuration.
pid_t sysGettid()
Get the TID of the current thread.
int ioctl(int request, long p1)
PerfEvent ioctl interface.
void stop()
Stop counting.
void start()
Start counting.
int fcntl(int cmd, long p1)
PerfEvent fnctl interface.