41#include <sys/syscall.h>
61 attr.size = PERF_ATTR_SIZE_VER0;
72 :
fd(-1), ringBuffer(NULL), pageSize(-1)
79 :
fd(-1), ringBuffer(NULL), pageSize(-1)
81 attach(config, tid, parent);
85 :
fd(-1), ringBuffer(NULL), pageSize(-1)
101 warn(
"PerfKvmCounter: Failed to unmap ring buffer (%i)\n",
112 if (
ioctl(PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1)
113 panic(
"KVM: Failed to enable performance counters (%i)\n", errno);
119 if (
ioctl(PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1)
120 panic(
"KVM: Failed to disable performance counters (%i)\n", errno);
127 panic(
"KVM: Failed to set period of performance counter (%i)\n", errno);
134 panic(
"KVM: Failed to refresh performance counter (%i)\n", errno);
142 read(&value,
sizeof(uint64_t));
149 struct f_owner_ex sigowner;
151 sigowner.type = F_OWNER_TID;
154 if (
fcntl(F_SETOWN_EX, &sigowner) == -1 ||
155 fcntl(F_SETSIG, signal) == -1 ||
156 fcntl(F_SETFL, O_ASYNC) == -1)
157 panic(
"PerfKvmCounter: Failed to enable signals for counter (%i)\n",
163 pid_t tid,
int group_fd)
167 fd = syscall(__NR_perf_event_open,
176 panic(
"PerfKvmCounter::attach received error EACCESS.\n"
177 " This error may be caused by a too restrictive setting\n"
178 " in the file '/proc/sys/kernel/perf_event_paranoid'.\n"
179 " The default value was changed to 2 in kernel 4.6.\n"
180 " A value greater than 1 prevents gem5 from making\n"
181 " the syscall to perf_event_open.\n"
182 " Alternatively, you can set the usePerf flag of the KVM\n"
183 " CPU to False. Setting this flag to False will limit some\n"
184 " functionalities of KVM CPU, such as counting the number of\n"
185 " cycles and the number of instructions, as well as the\n"
186 " ability of exiting to gem5 after a certain amount of cycles\n"
187 " or instructions when using KVM CPU. An example can be found\n"
188 " here, configs/example/gem5_library/"
189 "x86-ubuntu-run-with-kvm-no-perf.py.");
191 panic(
"PerfKvmCounter::attach failed (%i)\n", errno);
200 return syscall(__NR_gettid);
212 panic(
"PerfKvmCounter: Failed to determine page size (%i)\n",
217 ringBuffer = (
struct perf_event_mmap_page *)mmap(
219 PROT_READ | PROT_WRITE, MAP_SHARED,
222 panic(
"PerfKvmCounter: MMAP failed (%i)\n",
230 return ::fcntl(
fd, cmd, p1);
237 return ::ioctl(
fd, request, p1);
243 char *_buf = (
char *)buf;
254 panic(
"PerfKvmCounter::read failed (%i)\n", errno);
258 panic(
"PerfKvmCounter::read unexpected EOF.\n");
PerfEvent counter configuration.
struct perf_event_attr attr
Underlying perf_event_attr structure describing the counter.
PerfKvmCounterConfig(uint32_t type, uint64_t config)
Initialize PerfEvent counter configuration structure.
An instance of a performance counter.
int ringNumPages
Total number of pages in ring buffer.
pid_t sysGettid()
Get the TID of the current thread.
int fcntl(int cmd, long p1)
PerfEvent fnctl interface.
void mmapPerf(int pages)
MMAP the PerfEvent file descriptor.
PerfKvmCounter()
Create a new counter, but don't attach it.
struct perf_event_mmap_page * ringBuffer
Memory mapped PerfEvent sample ring buffer.
long pageSize
Cached host page size.
void period(uint64_t period)
Update the period of an overflow counter.
uint64_t read() const
Read the current value of a counter.
void attach(PerfKvmCounterConfig &config, pid_t tid)
Attach a counter.
int fd
PerfEvent file descriptor associated with counter.
void detach()
Detach a counter from PerfEvent.
int ioctl(int request, long p1)
PerfEvent ioctl interface.
bool attached() const
Check if a counter is attached.
void refresh(int refresh)
Enable a counter for a fixed number of events.
void enableSignals(pid_t tid, int signal)
Enable signal delivery to a thread on counter overflow.
void start()
Start counting.
void stop()
Stop counting.
#define panic(...)
This implements a cprintf based panic() function.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.