Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1946006AbbGQKpz (ORCPT ); Fri, 17 Jul 2015 06:45:55 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:16739 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757695AbbGQKpX (ORCPT ); Fri, 17 Jul 2015 06:45:23 -0400 From: kaixu xia To: , , , , , , CC: , , , , Subject: [RFC PATCH 6/6] samples/bpf: example of get selected PMU counter value Date: Fri, 17 Jul 2015 18:43:36 +0800 Message-ID: <1437129816-13176-7-git-send-email-xiakaixu@huawei.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1437129816-13176-1-git-send-email-xiakaixu@huawei.com> References: <1437129816-13176-1-git-send-email-xiakaixu@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.110.52.33] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020205.55A8DCBF.01EE,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 70712217bcfcfebb18f574787482278d Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6957 Lines: 206 This is a simple example and shows how to use the new ability to get the selected PMU counter value. The trace output: $ ./bpf_pmu_test $ cat /sys/kernel/debug/tracing/trace ... syslog-ng-555 [001] dn.1 10189.004626: : bpf count: CPU-0 9935764297 syslog-ng-555 [001] d..1 10189.053776: : bpf count: CPU-0 10000706398 syslog-ng-555 [001] dn.1 10189.102972: : bpf count: CPU-0 10067117321 syslog-ng-555 [001] d..1 10189.152925: : bpf count: CPU-0 10134551505 syslog-ng-555 [001] dn.1 10189.202043: : bpf count: CPU-0 10200869299 syslog-ng-555 [001] d..1 10189.251167: : bpf count: CPU-0 10267179481 syslog-ng-555 [001] dn.1 10189.300285: : bpf count: CPU-0 10333493522 syslog-ng-555 [001] d..1 10189.349410: : bpf count: CPU-0 10399808073 syslog-ng-555 [001] dn.1 10189.398528: : bpf count: CPU-0 10466121583 syslog-ng-555 [001] d..1 10189.447645: : bpf count: CPU-0 10532433368 syslog-ng-555 [001] d..1 10189.496841: : bpf count: CPU-0 10598841104 syslog-ng-555 [001] d..1 10189.546891: : bpf count: CPU-0 10666410564 syslog-ng-555 [001] dn.1 10189.596016: : bpf count: CPU-0 10732729739 syslog-ng-555 [001] d..1 10189.645146: : bpf count: CPU-0 12884941186 syslog-ng-555 [001] d..1 10189.694263: : bpf count: CPU-0 12951249903 syslog-ng-555 [001] dn.1 10189.743382: : bpf count: CPU-0 13017561470 syslog-ng-555 [001] d..1 10189.792506: : bpf count: CPU-0 13083873521 syslog-ng-555 [001] d..1 10189.841631: : bpf count: CPU-0 13150190416 syslog-ng-555 [001] d..1 10189.890749: : bpf count: CPU-0 13216505962 syslog-ng-555 [001] d..1 10189.939945: : bpf count: CPU-0 13282913062 ... Signed-off-by: kaixu xia --- samples/bpf/bpf_helpers.h | 2 + samples/bpf/bpf_pmu_test.c | 143 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 samples/bpf/bpf_pmu_test.c diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h index bdf1c16..a421be1 100644 --- a/samples/bpf/bpf_helpers.h +++ b/samples/bpf/bpf_helpers.h @@ -31,6 +31,8 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) = (void *) BPF_FUNC_get_current_uid_gid; static int (*bpf_get_current_comm)(void *buf, int buf_size) = (void *) BPF_FUNC_get_current_comm; +static int (*bpf_read_pmu)(void *pmu) = + (void *) BPF_FUNC_read_pmu; /* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions diff --git a/samples/bpf/bpf_pmu_test.c b/samples/bpf/bpf_pmu_test.c new file mode 100644 index 0000000..aced233 --- /dev/null +++ b/samples/bpf/bpf_pmu_test.c @@ -0,0 +1,143 @@ +/* eBPF example program shows how to get hardware PMU counter + * - creates hashmap in kernel + * + * - save the pointer to struct perf_event to map + * + * - loads eBPF program: + * r0 = 0 (the chosen key: CPU-0) + * *(u32 *)(fp - 4) = r0 + * value = bpf_map_lookup_elem(map_fd, fp - 4); + * count = bpf_read_pmu(value); + * bpf_trace_printk(fmt, fmt_size, key, count); + * + * - attaches this program to kprobes/sys_write + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libbpf.h" + +static int test_pmu(void) +{ + int kprobe_fd, prog_fd, i; + int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + int *pmu_fd = malloc(nr_cpus * sizeof(int)); + int key, map_fd; + unsigned long value; + + char fmt[] = "bpf count: CPU-%d %lld\n"; + int fmt_size = sizeof(fmt); + + int type = BPF_MAP_TYPE_HASH | BPF_MAP_FLAG_PERF_EVENT; + + map_fd = bpf_create_map(type, sizeof(key), sizeof(value), + nr_cpus); + if(map_fd < 0) { + printf("failed to create map '%s'\n", strerror(errno)); + return -1; + } + + struct perf_event_attr attr_insn_kprobe = { + .sample_period = 1, + .type = PERF_TYPE_TRACEPOINT, + .sample_type = PERF_SAMPLE_RAW, + .wakeup_events = 1, + .config = 0x46B, /* sys_write (this ID maybe change) */ + }; + + struct perf_event_attr attr_insn_pmu = { + .freq = 0, + .sample_period = 0x7fffffffffffffffULL, + .inherit = 0, + .type = PERF_TYPE_RAW, + .read_format = 0, + .sample_type = 0, + .config = 0x11,/* PMU: cycles (ARM) */ + + }; + + for(i = 0; i < nr_cpus; i++) { + pmu_fd[i] = perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0); + if (pmu_fd[i] < 0) { + printf("event syscall failed ****\n"); + return -1; + } + + ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0); + + bpf_update_elem(map_fd, &i, (pmu_fd + i), BPF_ANY); + } + + kprobe_fd = perf_event_open(&attr_insn_kprobe, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); + if (kprobe_fd < 0) { + printf("kprobe event syscall failed ****\n"); + return -1; + } + ioctl(kprobe_fd, PERF_EVENT_IOC_ENABLE, 0); + + struct bpf_insn prog[] = { + BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */ + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */ + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ + BPF_LD_MAP_FD(BPF_REG_1, map_fd), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_read_pmu), + BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), + BPF_MOV64_IMM(BPF_REG_1, 0), + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, -8), + BPF_LD_IMM64(BPF_REG_1, 748842649785475172), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16), + BPF_LD_IMM64(BPF_REG_1, 2678891156567243380), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -24), + BPF_LD_IMM64(BPF_REG_1, 7959390387983249506), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -32), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -32), + BPF_MOV64_IMM(BPF_REG_2, 25), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_MOV64_REG(BPF_REG_4, BPF_REG_6), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk), + BPF_EXIT_INSN(), + }; + + prog_fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, prog, sizeof(prog), + "GPL", 0); + if (prog_fd < 0) { + printf("failed to load prog '%s'\n", strerror(errno)); + return -1; + } + + ioctl(kprobe_fd, PERF_EVENT_IOC_SET_BPF, prog_fd); + + system("ls"); + system("pwd"); + system("sleep 4"); + + for(i = 0; i < nr_cpus; i++) { + close(pmu_fd[i]); + } + + close(map_fd); + + free(pmu_fd); + return 0; +} + +int main(int argc, char **argv) +{ + test_pmu(); + + return 0; +} -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/