39 #include <sys/ioctl.h> 41 #include <sys/syscall.h> 42 #include <sys/types.h> 58 attr.size = PERF_ATTR_SIZE_VER0;
69 :
fd(-1), ringBuffer(NULL), pageSize(-1)
78 attach(config, tid, parent);
98 warn(
"PerfKvmCounter: Failed to unmap ring buffer (%i)\n",
109 if (
ioctl(PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1)
110 panic(
"KVM: Failed to enable performance counters (%i)\n", errno);
116 if (
ioctl(PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1)
117 panic(
"KVM: Failed to disable performance counters (%i)\n", errno);
123 if (
ioctl(PERF_EVENT_IOC_PERIOD, &period) == -1)
124 panic(
"KVM: Failed to set period of performance counter (%i)\n", errno);
130 if (
ioctl(PERF_EVENT_IOC_REFRESH, refresh) == -1)
131 panic(
"KVM: Failed to refresh performance counter (%i)\n", errno);
139 read(&value,
sizeof(uint64_t));
146 struct f_owner_ex sigowner;
148 sigowner.type = F_OWNER_TID;
151 if (
fcntl(F_SETOWN_EX, &sigowner) == -1 ||
152 fcntl(F_SETSIG, signal) == -1 ||
153 fcntl(F_SETFL, O_ASYNC) == -1)
154 panic(
"PerfKvmCounter: Failed to enable signals for counter (%i)\n",
160 pid_t tid,
int group_fd)
164 fd = syscall(__NR_perf_event_open,
173 panic(
"PerfKvmCounter::attach recieved error EACCESS\n" 174 " This error may be caused by a too restrictive setting\n" 175 " in the file '/proc/sys/kernel/perf_event_paranoid'\n" 176 " The default value was changed to 2 in kernel 4.6\n" 177 " A value greater than 1 prevents gem5 from making\n" 178 " the syscall to perf_event_open");
180 panic(
"PerfKvmCounter::attach failed (%i)\n", errno);
189 return syscall(__NR_gettid);
201 panic(
"PerfKvmCounter: Failed to determine page size (%i)\n",
206 ringBuffer = (
struct perf_event_mmap_page *)mmap(
208 PROT_READ | PROT_WRITE, MAP_SHARED,
211 panic(
"PerfKvmCounter: MMAP failed (%i)\n",
219 return ::fcntl(
fd, cmd, p1);
226 return ::ioctl(
fd, request, p1);
232 char *_buf = (
char *)buf;
243 panic(
"PerfKvmCounter::read failed (%i)\n", errno);
247 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.