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 @@ ...@@ -15,6 +15,7 @@
*/ */
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/perf_event.h>
#include <unistd.h> #include <unistd.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
...@@ -292,12 +293,13 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config, ...@@ -292,12 +293,13 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
int probe_fd; int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_PERF_EVENT, 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; std::vector<int> cpus;
if (cpu >= 0) if (cpu >= 0)
cpus.push_back(cpu); cpus.push_back(cpu);
else else
cpus = get_online_cpus(); cpus = get_online_cpus();
auto fds = new std::vector<std::pair<int, int>>();
fds->reserve(cpus.size());
for (int i : cpus) { for (int i : cpus) {
int fd = bpf_attach_perf_event(probe_fd, ev_type, ev_config, sample_period, int fd = bpf_attach_perf_event(probe_fd, ev_type, ev_config, sample_period,
sample_freq, pid, i, group_fd); sample_freq, pid, i, group_fd);
...@@ -309,7 +311,7 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config, ...@@ -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", return StatusTuple(-1, "Failed to attach perf event type %d config %d",
ev_type, ev_config); ev_type, ev_config);
} }
fds->emplace(i, fd); fds->emplace_back(i, fd);
} }
open_probe_t p = {}; open_probe_t p = {};
...@@ -319,6 +321,46 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config, ...@@ -319,6 +321,46 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
return StatusTuple(0); 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, StatusTuple BPF::detach_kprobe(const std::string& kernel_func,
bpf_probe_attach_type attach_type) { bpf_probe_attach_type attach_type) {
std::string event = get_kprobe_event(kernel_func, 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) { ...@@ -394,6 +436,11 @@ StatusTuple BPF::detach_perf_event(uint32_t ev_type, uint32_t ev_config) {
return StatusTuple(0); 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, StatusTuple BPF::open_perf_event(const std::string& name, uint32_t type,
uint64_t config) { uint64_t config) {
if (perf_event_arrays_.find(name) == perf_event_arrays_.end()) { if (perf_event_arrays_.find(name) == perf_event_arrays_.end()) {
......
...@@ -36,7 +36,7 @@ namespace ebpf { ...@@ -36,7 +36,7 @@ namespace ebpf {
struct open_probe_t { struct open_probe_t {
int perf_event_fd; int perf_event_fd;
std::string func; std::string func;
std::map<int, int>* per_cpu_fd; std::vector<std::pair<int, int>>* per_cpu_fd;
}; };
class USDT; class USDT;
...@@ -84,7 +84,12 @@ class BPF { ...@@ -84,7 +84,12 @@ class BPF {
uint64_t sample_period, uint64_t sample_freq, uint64_t sample_period, uint64_t sample_freq,
pid_t pid = -1, int cpu = -1, pid_t pid = -1, int cpu = -1,
int group_fd = -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(uint32_t ev_type, uint32_t ev_config);
StatusTuple detach_perf_event_raw(void* perf_event_attr);
BPFTable get_table(const std::string& name) { BPFTable get_table(const std::string& name) {
TableStorage::iterator it; TableStorage::iterator it;
......
...@@ -1278,6 +1278,28 @@ cleanup: ...@@ -1278,6 +1278,28 @@ cleanup:
return ret; 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, int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config,
uint64_t sample_period, uint64_t sample_freq, uint64_t sample_period, uint64_t sample_freq,
pid_t pid, int cpu, int group_fd) { 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, ...@@ -1303,25 +1325,7 @@ int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config,
attr.sample_period = sample_period; attr.sample_period = sample_period;
} }
int fd = syscall( return bpf_attach_perf_event_raw(progfd, &attr, pid, cpu, group_fd);
__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;
} }
int bpf_close_perf_event_fd(int fd) { int bpf_close_perf_event_fd(int fd) {
......
...@@ -88,6 +88,10 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, ...@@ -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 */ /* 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); 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 // attach a prog expressed by progfd to run on a specific perf event, with
// certain sample period or sample frequency // certain sample period or sample frequency
int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config, 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