From 04d2039e6407ca14a2673cf585db20b0c6593ef4 Mon Sep 17 00:00:00 2001 From: Dave Marchevsky Date: Wed, 18 Aug 2021 17:06:00 -0700 Subject: [PATCH] bcc/python: Add x86 and sw test to test_attach_perf_event.py Since the current test can't run on github actions since there's no HW perf counter access, add a test using software page faults perf event, which might work. Also, rename the current HW test in there to highlight that it'll work for PowerPC, and add a similar test for x86. --- tests/python/test_attach_perf_event.py | 98 +++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/tests/python/test_attach_perf_event.py b/tests/python/test_attach_perf_event.py index d0cea065..a843b575 100755 --- a/tests/python/test_attach_perf_event.py +++ b/tests/python/test_attach_perf_event.py @@ -6,7 +6,7 @@ import bcc import os import time import unittest -from bcc import BPF, PerfType, PerfHWConfig, PerfEventSampleFormat +from bcc import BPF, PerfType, PerfHWConfig, PerfSWConfig, PerfEventSampleFormat from bcc import Perf from time import sleep from utils import kernel_version_ge, mayFail @@ -14,7 +14,8 @@ from utils import kernel_version_ge, mayFail class TestPerfAttachRaw(unittest.TestCase): @mayFail("This fails on github actions environment, hw perf events are not supported") @unittest.skipUnless(kernel_version_ge(4,9), "requires kernel >= 4.9") - def test_attach_raw_event(self): + def test_attach_raw_event_powerpc(self): + # on PowerPC, 'addr' is always written to; for x86 see _x86 version of test bpf_text=""" #include struct key_t { @@ -41,7 +42,7 @@ int on_sample_hit(struct bpf_perf_event_data *ctx) { if (data) bpf_probe_read(&addr, sizeof(u64), &(data->addr)); - bpf_trace_printk("Hit a sample with pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr); + bpf_trace_printk("test_attach_raw_event_powerpc: pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr); return 0; } @@ -63,5 +64,96 @@ int on_sample_hit(struct bpf_perf_event_data *ctx) { print("Running for 2 seconds or hit Ctrl-C to end. Check trace file for samples information written by bpf_trace_printk.") sleep(2) + @mayFail("This fails on github actions environment, hw perf events are not supported") + @unittest.skipUnless(kernel_version_ge(4,17), "bpf_perf_event_data->addr requires kernel >= 4.17") + def test_attach_raw_event_x86(self): + # on x86, need to set precise_ip in order for perf_events to write to 'addr' + bpf_text=""" +#include +struct key_t { + int cpu; + int pid; + char name[100]; +}; + +static inline __attribute__((always_inline)) void get_key(struct key_t* key) { + key->cpu = bpf_get_smp_processor_id(); + key->pid = bpf_get_current_pid_tgid(); + bpf_get_current_comm(&(key->name), sizeof(key->name)); +} + +int on_sample_hit(struct bpf_perf_event_data *ctx) { + struct key_t key = {}; + get_key(&key); + u64 addr = ctx->addr; + + bpf_trace_printk("test_attach_raw_event_x86: pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr); + return 0; +} + +""" + + b = BPF(text=bpf_text) + try: + event_attr = Perf.perf_event_attr() + event_attr.type = Perf.PERF_TYPE_HARDWARE + event_attr.config = PerfHWConfig.CPU_CYCLES + event_attr.sample_period = 1000000 + event_attr.sample_type = PerfEventSampleFormat.ADDR + event_attr.exclude_kernel = 1 + event_attr.precise_ip = 2 + b.attach_perf_event_raw(attr=event_attr, fn_name="on_sample_hit", pid=-1, cpu=-1) + except Exception: + print("Failed to attach to a raw event. Please check the event attr used") + exit() + + print("Running for 1 seconds or hit Ctrl-C to end. Check trace file for samples information written by bpf_trace_printk.") + sleep(1) + + + # SW perf events should work on GH actions, so expect this to succeed + @unittest.skipUnless(kernel_version_ge(4,17), "bpf_perf_event_data->addr requires kernel >= 4.17") + def test_attach_raw_sw_event(self): + bpf_text=""" +#include +struct key_t { + int cpu; + int pid; + char name[100]; +}; + +static inline __attribute__((always_inline)) void get_key(struct key_t* key) { + key->cpu = bpf_get_smp_processor_id(); + key->pid = bpf_get_current_pid_tgid(); + bpf_get_current_comm(&(key->name), sizeof(key->name)); +} + +int on_sample_hit(struct bpf_perf_event_data *ctx) { + struct key_t key = {}; + get_key(&key); + u64 addr = ctx->addr; + + bpf_trace_printk("test_attach_raw_sw_event: pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr); + return 0; +} + +""" + + b = BPF(text=bpf_text) + try: + event_attr = Perf.perf_event_attr() + event_attr.type = Perf.PERF_TYPE_SOFTWARE + event_attr.config = PerfSWConfig.PAGE_FAULTS + event_attr.sample_period = 100 + event_attr.sample_type = PerfEventSampleFormat.ADDR + event_attr.exclude_kernel = 1 + b.attach_perf_event_raw(attr=event_attr, fn_name="on_sample_hit", pid=-1, cpu=-1) + except Exception: + print("Failed to attach to a raw event. Please check the event attr used") + exit() + + print("Running for 1 seconds or hit Ctrl-C to end. Check trace file for samples information written by bpf_trace_printk.") + sleep(1) + if __name__ == "__main__": unittest.main() -- 2.34.1