Commit 7cfb73b5 authored by yonghong-song's avatar yonghong-song Committed by GitHub

Merge pull request #1627 from palmtenor/raw_perf_event

Perf Event interface with raw perf_event_attr argument
parents 1393ec48 6c33a523
......@@ -15,6 +15,7 @@
*/
#include <linux/bpf.h>
#include <linux/perf_event.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
......@@ -292,12 +293,13 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_PERF_EVENT, probe_fd));
auto fds = new std::map<int, int>();
std::vector<int> cpus;
if (cpu >= 0)
cpus.push_back(cpu);
else
cpus = get_online_cpus();
auto fds = new std::vector<std::pair<int, int>>();
fds->reserve(cpus.size());
for (int i : cpus) {
int fd = bpf_attach_perf_event(probe_fd, ev_type, ev_config, sample_period,
sample_freq, pid, i, group_fd);
......@@ -309,7 +311,7 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
return StatusTuple(-1, "Failed to attach perf event type %d config %d",
ev_type, ev_config);
}
fds->emplace(i, fd);
fds->emplace_back(i, fd);
}
open_probe_t p = {};
......@@ -319,6 +321,46 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
return StatusTuple(0);
}
StatusTuple BPF::attach_perf_event_raw(void* perf_event_attr,
const std::string& probe_func,
pid_t pid, int cpu, int group_fd) {
auto attr = static_cast<struct perf_event_attr*>(perf_event_attr);
auto ev_pair = std::make_pair(attr->type, attr->config);
if (perf_events_.find(ev_pair) != perf_events_.end())
return StatusTuple(-1, "Perf event type %d config %d already attached",
attr->type, attr->config);
int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_PERF_EVENT, probe_fd));
std::vector<int> cpus;
if (cpu >= 0)
cpus.push_back(cpu);
else
cpus = get_online_cpus();
auto fds = new std::vector<std::pair<int, int>>();
fds->reserve(cpus.size());
for (int i : cpus) {
int fd = bpf_attach_perf_event_raw(probe_fd, attr, pid, i, group_fd);
if (fd < 0) {
for (const auto& it : *fds)
close(it.second);
delete fds;
TRY2(unload_func(probe_func));
return StatusTuple(-1, "Failed to attach perf event type %d config %d",
attr->type, attr->config);
}
fds->emplace_back(i, fd);
}
open_probe_t p = {};
p.func = probe_func;
p.per_cpu_fd = fds;
perf_events_[ev_pair] = std::move(p);
return StatusTuple(0);
}
StatusTuple BPF::detach_kprobe(const std::string& kernel_func,
bpf_probe_attach_type attach_type) {
std::string event = get_kprobe_event(kernel_func, attach_type);
......@@ -394,6 +436,11 @@ StatusTuple BPF::detach_perf_event(uint32_t ev_type, uint32_t ev_config) {
return StatusTuple(0);
}
StatusTuple BPF::detach_perf_event_raw(void* perf_event_attr) {
auto attr = static_cast<struct perf_event_attr*>(perf_event_attr);
return detach_perf_event(attr->type, attr->config);
}
StatusTuple BPF::open_perf_event(const std::string& name, uint32_t type,
uint64_t config) {
if (perf_event_arrays_.find(name) == perf_event_arrays_.end()) {
......
......@@ -36,7 +36,7 @@ namespace ebpf {
struct open_probe_t {
int perf_event_fd;
std::string func;
std::map<int, int>* per_cpu_fd;
std::vector<std::pair<int, int>>* per_cpu_fd;
};
class USDT;
......@@ -84,7 +84,12 @@ class BPF {
uint64_t sample_period, uint64_t sample_freq,
pid_t pid = -1, int cpu = -1,
int group_fd = -1);
StatusTuple attach_perf_event_raw(void* perf_event_attr,
const std::string& probe_func,
pid_t pid = -1, int cpu = -1,
int group_fd = -1);
StatusTuple detach_perf_event(uint32_t ev_type, uint32_t ev_config);
StatusTuple detach_perf_event_raw(void* perf_event_attr);
BPFTable get_table(const std::string& name) {
TableStorage::iterator it;
......
......@@ -1278,6 +1278,28 @@ cleanup:
return ret;
}
int bpf_attach_perf_event_raw(int progfd, void *perf_event_attr, pid_t pid,
int cpu, int group_fd) {
int fd = syscall(__NR_perf_event_open, perf_event_attr, pid, cpu, group_fd,
PERF_FLAG_FD_CLOEXEC);
if (fd < 0) {
perror("perf_event_open failed");
return -1;
}
if (ioctl(fd, PERF_EVENT_IOC_SET_BPF, progfd) != 0) {
perror("ioctl(PERF_EVENT_IOC_SET_BPF) failed");
close(fd);
return -1;
}
if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) != 0) {
perror("ioctl(PERF_EVENT_IOC_ENABLE) failed");
close(fd);
return -1;
}
return fd;
}
int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config,
uint64_t sample_period, uint64_t sample_freq,
pid_t pid, int cpu, int group_fd) {
......@@ -1303,25 +1325,7 @@ int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config,
attr.sample_period = sample_period;
}
int fd = syscall(
__NR_perf_event_open, &attr, pid, cpu, group_fd, PERF_FLAG_FD_CLOEXEC
);
if (fd < 0) {
perror("perf_event_open failed");
return -1;
}
if (ioctl(fd, PERF_EVENT_IOC_SET_BPF, progfd) != 0) {
perror("ioctl(PERF_EVENT_IOC_SET_BPF) failed");
close(fd);
return -1;
}
if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) != 0) {
perror("ioctl(PERF_EVENT_IOC_ENABLE) failed");
close(fd);
return -1;
}
return fd;
return bpf_attach_perf_event_raw(progfd, &attr, pid, cpu, group_fd);
}
int bpf_close_perf_event_fd(int fd) {
......
......@@ -88,6 +88,10 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,
/* attached a prog expressed by progfd to the device specified in dev_name */
int bpf_attach_xdp(const char *dev_name, int progfd, uint32_t flags);
// attach a prog expressed by progfd to run on a specific perf event. The perf
// event will be created using the perf_event_attr pointer provided.
int bpf_attach_perf_event_raw(int progfd, void *perf_event_attr, pid_t pid,
int cpu, int group_fd);
// attach a prog expressed by progfd to run on a specific perf event, with
// certain sample period or sample frequency
int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment