用bcc打印調用函數和返回的時間

#!/usr/bin/python

from __future__ import print_function
from bcc import BPF
import socket

# load BPF program
b = BPF(text="""
#include <linux/pci.h>
BPF_PERF_OUTPUT(events);
struct data_t {
    char name[64];
    u64 ts;
    char pci[64];
    u16 func_id;
    int npages;
};
struct mlx5_core_dev {
    struct pci_dev *pdev;
};
void kprobe__give_pages(struct pt_regs *ctx, void *dev, u16 func_id, int npages) {
    u64 tsp = bpf_ktime_get_ns();
    struct data_t data = {};
    char name[] = "give_pages";
    data.npages = npages;
    data.func_id = func_id;
    data.ts = tsp / 1000;
    bpf_probe_read_str(&data.name, sizeof(data.name), name);
    bpf_probe_read_str(&data.pci, sizeof(data.pci), ((struct mlx5_core_dev *)dev)->pdev->dev.kobj.name);
    events.perf_submit(ctx, &data, sizeof(data));
}
void kretprobe__give_pages(struct pt_regs *ctx) {
    char name[] = "give_pages_ret";
    u64 tsp = bpf_ktime_get_ns();
    struct data_t data = {};
    data.ts = tsp / 1000;
    bpf_probe_read_str(&data.name, sizeof(data.name), name);
    events.perf_submit(ctx, &data, sizeof(data));
}
void kprobe__mlx5_cmd_init_hca(struct pt_regs *ctx, void *dev) {
    u64 tsp = bpf_ktime_get_ns();
    struct data_t data = {};
    char name[] = "mlx5_cmd_init_hca";
    data.ts = tsp / 1000;
    bpf_probe_read_str(&data.name, sizeof(data.name), name);
    bpf_probe_read_str(&data.pci, sizeof(data.pci), ((struct mlx5_core_dev *)dev)->pdev->dev.kobj.name);
    events.perf_submit(ctx, &data, sizeof(data));
}
void kretprobe__mlx5_cmd_init_hca(struct pt_regs *ctx) {
    char name[] = "mlx5_cmd_init_hca_ret";
    u64 tsp = bpf_ktime_get_ns();
    struct data_t data = {};
    data.ts = tsp / 1000;
    bpf_probe_read_str(&data.name, sizeof(data.name), name);
    events.perf_submit(ctx, &data, sizeof(data));
}
""")

# header
print("%-25s%-18s%-15s%-10s%-10s" % ("function", "timestamp", "PCI", "func_id", "pages"))

def print_give_pages(cpu, data, size):
    event = b["events"].event(data)
    print("%-25s" % event.name, end="")
    if event.name.find('ret') != -1:
        print("%-18.4f" % (float(event.ts) / 1000000))
    else:
        print("%-18.4f" % (float(event.ts) / 1000000), end="")
        print("%-15s" % event.pci, end="")
        print("%-10d" % event.func_id, end="")
        print('0x%-10lx' % int(event.npages))

# format output
b["events"].open_perf_buffer(print_give_pages, page_cnt=64)
while 1:
    try:
        b.perf_buffer_poll()

    except KeyboardInterrupt:
        exit()

輸出如下:

mlx5_cmd_init_hca        1456.6938         0000:04:00.2   0         0x0
give_pages               1456.6943         0000:04:00.0   1         0x2050
give_pages_ret           1456.7063
mlx5_cmd_init_hca_ret    1456.8700

可以看出初始化第一個VF的時候會向firmware發送INIT_HCA命令,然後firmware會向驅動發送中斷,請求分配內存。一共分配了0x2050個page,give_pages分配成功後,mlx5_cmd_init_hca才返回。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章